os/security/cryptoservices/certificateandkeymgmt/tx509/Data/extensions/certextbuilder.pl
Update contrib.
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 # This component and the accompanying materials are made available
5 # under the terms of the License "Eclipse Public License v1.0"
6 # which accompanies this distribution, and is available
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 # Initial Contributors:
10 # Nokia Corporation - initial contribution.
21 my $OID_DEVICE_ID_LIST="1.2.826.0.1.1796587.1.1.1.1";
22 my $OID_SID_LIST="1.2.826.0.1.1796587.1.1.1.4";
23 my $OID_VID_LIST="1.2.826.0.1.1796587.1.1.1.5";
24 my $OID_CAPABILITIES="1.2.826.0.1.1796587.1.1.1.6";
26 # Reserved for future use
27 #my $OID_SUBSCRIBER_ID_LIST="1.2.826.0.1.1796587.1.1.2.2";
28 #my $OID_ICC_ID_LIST="1.2.826.0.1.1796587.1.1.1.3";
30 my $DER_UTF8STRING_TAG="0C";
31 my $DER_PRINTABLESTRING_TAG="13";
32 my $DER_SEQUENCE_TAG="30";
33 my $DER_INTEGER_TAG="02";
34 my $DER_BITSTRING_TAG="03";
35 my $DER_OCTET_TAG="04";
37 my %CAPABILITY_SET = (
42 "READDEVICEDATA" => 4,
43 "WRITEDEVICEDATA" => 5,
48 "NETWORKCONTROL" => 10,
51 "NETWORKSERVICES" => 13,
52 "LOCALSERVICES" => 14,
54 "WRITEUSERDATA" => 16,
56 "SURROUNDINGSDD" => 18,
57 "USERENVIRONMENT" => 19
60 # Sections encountered
63 # Fields within sectins
64 my @device_id_list = ();
67 my $capabilities = '';
73 # Loops through the input file and creates lists of items for each section.
76 my $output_binary = 0;
78 GetOptions('binary' => \$output_binary);
79 my ($infile, $outfile) = @ARGV;
81 if (defined $infile) {
82 open IN, "$infile" || die "Cannot open input file $infile";
88 if (defined $outfile) {
89 open OUT, ">$outfile" || die "Cannot open input file $outfile";
98 # Process the new section name
100 s/.*\[\s*(.*)\s*].*/$1/g;
102 $sections{$section} = 1;
108 # Process element within section
110 if ($section eq "device_id_list") {
111 push @device_id_list, $_;
113 elsif ($section eq "sid_list") {
116 elsif ($section eq "vid_list") {
119 elsif ($section eq "cert_capabilities") {
121 if (! $capabilities eq "") {
122 die "Error: Multiple capability constraints defined.";
126 if ($capabilities eq "" || $capabilities =~ /^\s*[01]+\s*$/) {
127 # Handle explicit bit strings
128 $capabilities =~ s/\s//g;
131 # Convert MMP syntax into an explicit bit string
132 $capabilities = &encode_capabilities($capabilities);
136 # Not in a section so ignore text
141 if ($output_binary) {
151 # Test function which outputs the binary DER encoding. This can be vieweed using an
153 # This is really a debug function.
156 my $seq_content = "";
158 if (defined $sections{"device_id_list"}) {
159 $seq_content .= ":" . &encode_string_list(\@device_id_list, \$seq_octets);
162 if (defined $sections{"sid_list"}) {
163 $seq_content .= ":" . &encode_integer_list(\@sid_list, \$seq_octets);
166 if (defined $sections{"vid_list"}) {
167 $seq_content .= ":" . &encode_integer_list(\@vid_list, \$seq_octets);
170 if (defined $sections{"cert_capabilities"}) {
171 $seq_content .= ":" . &encode_bit_string($capabilities, \$seq_octets);
173 # Tidy up repreated colons
174 $seq_content =~ s/::/:/;
175 $seq_content =~ s/^://g;
177 my $seq_length_octets;
178 my $seq_length = &encode_length($seq_octets, \$seq_length_octets);
179 my $seq ="$DER_SEQUENCE_TAG:$seq_length:$seq_content";
185 foreach (split(/:/, $seq)){
186 print OUT pack('C', hex);
190 # Output to a format that can be read by Open SSL using the -extfile parameter
192 print OUT "extensions = extend\n";
193 print OUT "[extend]\n";
198 if (defined $sections{"device_id_list"}) {
199 $output .= "# Device ID List\n" .
200 $OID_DEVICE_ID_LIST . "= critical, " . "DER:" .
201 uc(&encode_string_list(\@device_id_list, \$octets)) . "\n";
204 if (defined $sections{"sid_list"}) {
205 $output .= "# SID List\n" .
206 $OID_SID_LIST . "= critical, " . "DER:" .
207 uc(&encode_integer_list(\@sid_list, \$octets)) . "\n";
210 if (defined $sections{"vid_list"}) {
211 $output .= "# VID List\n" .
212 $OID_VID_LIST . "= critical, " . "DER:" . uc(&encode_integer_list(\@vid_list, \$octets)) . "\n";
215 if (defined $sections{"cert_capabilities"}) {
216 $output .= "# Capabilities\n" .
217 $OID_CAPABILITIES . "= critical, " . "DER:" . uc(&encode_bit_string($capabilities, \$octets)) . "\n";
220 # Remove trailing colons
221 $output=~ s/\:*$//mg;
225 # Creates a hex representation of the DER encoding of a sequence of strings.
226 sub encode_string_list($$) {
227 my ($list, $octets) = @_;
229 my $sequence_body = "";
231 my $sequence_octets = 0;
233 my $hex_string = &encode_utf8_string($_, \$sequence_octets);
235 # Add to string sequence body
236 if ($sequence_body ne "") {
237 $sequence_body .= ":";
239 $sequence_body .= $hex_string;
241 my $seq_length_octets = 0;
242 my $seq_length = &encode_length($sequence_octets, \$seq_length_octets);
244 $$octets += 1 + $seq_length_octets + $sequence_octets;
246 return "$DER_SEQUENCE_TAG:$seq_length:$sequence_body";
249 # Creates a hex represenation of the DER encoding of a sequence of integers.
250 sub encode_integer_list($$) {
251 my ($list, $octets) = @_;
253 my $sequence_body = "";
254 my $sequence_octets = 0;
256 # Increment for integer tag value
257 # Increment for integer length < 127 octets assumed !
264 # Convert the integer to base 256 hex and find out how
265 # many octets were required
273 $hex_integer = &to_hex_base256($_, \$hex_octets);
274 $sequence_octets += $hex_octets;
277 # Add to integer sequence body
278 if ($sequence_body ne "") {
279 $sequence_body .= ":";
282 # No need to store length in long form because in base256
283 # we never need more than 7 octets to store the largest number
285 my $int_header = sprintf("%2.2x", $hex_octets);
286 $sequence_body .= "$DER_INTEGER_TAG:$int_header:$hex_integer";
289 # Get the number of octets of the entire sequence. This could require
290 # encoding in long form.
291 my $seq_length_octets = 0;
292 my $seq_length = &encode_length($sequence_octets, \$seq_length_octets);
294 $$octets += 1 + $seq_length_octets + $sequence_octets;
296 return "$DER_SEQUENCE_TAG:$seq_length:$sequence_body";
299 # Creates a hex represenation of the DER encoding of a UTF-8 string.
300 sub encode_utf8_string($$) {
301 my ($input, $octets) = @_;
305 my $input_len = length($input);
307 while ($i < $input_len) {
308 my $hex_val = ord(substr($input, $i, 1));
312 $output .= sprintf("%2.2x", $hex_val);
316 # Build string header
317 my $output_length_octets = 0;
318 my $output_length = &encode_length($input_len, \$output_length_octets);
320 # Track number of octets added for string header
321 $$octets += 1 + $output_length_octets + $input_len;
322 return "$DER_UTF8STRING_TAG:$output_length:$output";
325 # Converts the text description of capabilities into an ASCII string of 0s and 1s;
326 sub encode_capabilities($) {
332 foreach (split(/[\s,]/, $value)) {
340 foreach (keys %CAPABILITY_SET) {
341 @caps[$CAPABILITY_SET{$_}] = 1;
347 if (defined $CAPABILITY_SET{$_}) {
348 $caps[$CAPABILITY_SET{$_}] = $set_val;
352 # Build the ascii bit string. Bit 0 is the left most bit
353 for (my $i = 0; $i <= $#caps; $i++) {
354 $output .= (defined $caps[$i] && $caps[$i] ? "1" : "0");
360 # Creates a hex representation of the DER encoding of an arbitrary length bit string
361 sub encode_bit_string($$) {
362 my ($text, $octets) = @_;
364 # Bit string in hex including padding length octet
366 my $bit_str_octets = 1; # one octet for padding
370 my $len = length($text);
380 # Read the ith character and insert it in the correct place in the byte
381 # (fill from the left)
382 my $c = substr($text, $i, 1);
384 $byte |= (1 << (7 - ($i % 8)));
387 die "Invalid character $c in bit string $text";
391 # Received 8 bits so output byte in hex
392 if ($bit_str ne "") {
395 $bit_str .= sprintf("%2.2x", $byte);
400 # Pad any remaining bits / make sure 0 is output for empty string
401 if ($byte != 0 || $bit_str_octets == 1) {
402 if ($bit_str ne "") {
405 $bit_str .= sprintf("%2.2x", $byte);
409 my $pad_length = "00";
411 # If this isn't a multiple of 8 bits then calculated
412 # the number of padding bits added.
413 $pad_length = sprintf("%2.2x", 8 - ($len % 8));
416 # Octets used to store the length
417 my $bit_str_length_octets = 0;
418 my $bit_str_length = &encode_length($bit_str_octets, \$bit_str_length_octets);
419 $$octets += 1 + $bit_str_length_octets + $bit_str_octets;
421 return "$DER_BITSTRING_TAG:$bit_str_length:$pad_length:$bit_str";
424 # Return a hex represenation of the length using DER primitive (definate length encoding)
425 sub encode_length($$) {
426 my ($num, $octets) = @_;
429 # Number is < 128 so encode in short form
431 return sprintf("%2.2x", $num);
434 # Number >= 128 so encode in long form
435 my $length_octets = 0;
436 my $base256 = &to_hex_base256($num, \$length_octets);
437 if ($length_octets > 127) {die "Encoding overflow.";}
439 $$octets += 1 + $length_octets;
441 # Set the top bit of the length octet to indicate long form
442 return "" . sprintf("%2.2x", ($length_octets | 0x80)) . ":$base256";
446 # Convert an integer into an ascii hex representation in base 256
447 # $num - the number to encode
448 # $octets - refernce to the octet count to increment
449 sub to_hex_base256($$) {
450 my ($num, $octets) = @_;
455 my $hexoctet = sprintf("%2.2x", $num & 0xFF);
456 if ($base256 ne "") {
457 $base256 = "$hexoctet:$base256";
460 $base256 = $hexoctet;
465 if ($base256 eq "") {