cryptoservices/certificateandkeymgmt/tx509/Data/extensions/certextbuilder.pl
changeset 8 35751d3474b7
parent 0 2c201484c85f
child 11 9d767430696e
child 29 ece3df019add
--- a/cryptoservices/certificateandkeymgmt/tx509/Data/extensions/certextbuilder.pl	Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/certificateandkeymgmt/tx509/Data/extensions/certextbuilder.pl	Thu Sep 10 14:01:51 2009 +0300
@@ -1,493 +1,493 @@
-#
-# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-# All rights reserved.
-# This component and the accompanying materials are made available
-# under the terms of the License "Eclipse Public License v1.0"
-# which accompanies this distribution, and is available
-# at the URL "http://www.eclipse.org/legal/epl-v10.html".
-#
-# Initial Contributors:
-# Nokia Corporation - initial contribution.
-#
-# Contributors:
-#
-# Description: 
-#
-#!/bin/perl -w
-
-# Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
-# All rights reserved.
-# This component and the accompanying materials are made available
-# under the terms of the License "Symbian Foundation License v1.0"
-# which accompanies this distribution, and is available
-# at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
-#
-# Initial Contributors:
-# Nokia Corporation - initial contribution.
-#
-# Contributors:
-#
-# Description:
-# This script converts certificate constraint extensions specified in an INI 
-# format into a hex representation of the DER encoding that OpenSSL can 
-# add to a certificate.
-# This script allows corrupt certificate extensions to be generated for unit 
-# testing and therefore using this script to create production certificates is
-# NOT supported.
-# See SGL.GT0220.255_Developer_Certificates.doc for usage instructions.
-# 
-#
-
-use strict;
-use Getopt::Long;
-
-my $OID_DEVICE_ID_LIST="1.2.826.0.1.1796587.1.1.1.1";
-my $OID_SID_LIST="1.2.826.0.1.1796587.1.1.1.4";
-my $OID_VID_LIST="1.2.826.0.1.1796587.1.1.1.5";
-my $OID_CAPABILITIES="1.2.826.0.1.1796587.1.1.1.6";
-
-# Reserved for future use
-#my $OID_SUBSCRIBER_ID_LIST="1.2.826.0.1.1796587.1.1.2.2"; 
-#my $OID_ICC_ID_LIST="1.2.826.0.1.1796587.1.1.1.3";
-
-my $DER_UTF8STRING_TAG="0C";
-my $DER_PRINTABLESTRING_TAG="13";
-my $DER_SEQUENCE_TAG="30";
-my $DER_INTEGER_TAG="02";
-my $DER_BITSTRING_TAG="03";
-my $DER_OCTET_TAG="04";
-
-my %CAPABILITY_SET = (
-	"TCB" => 0,
-	"COMMDD" => 1,
-	"POWERMGMT" => 2,
-	"MULTIMEDIADD" => 3,
-	"READDEVICEDATA" => 4,
-	"WRITEDEVICEDATA" => 5,
-	"DRM" => 6,
-	"TRUSTEDUI" => 7,
-	"PROTSERV" => 8,
-	"DISKADMIN" => 9,
-	"NETWORKCONTROL" => 10,
-	"ALLFILES" => 11,
-	"SWEVENT" => 12,
-	"NETWORKSERVICES" => 13,
-	"LOCALSERVICES" => 14,
-	"READUSERDATA" => 15,
-	"WRITEUSERDATA" => 16,
-	"LOCATION" => 17,
-	"SURROUNDINGSDD" => 18,
-	"USERENVIRONMENT" => 19	
-	);
-
-# Sections encountered
-my %sections;
-
-# Fields within sectins
-my @device_id_list = ();
-my @sid_list = ();
-my @vid_list = ();
-my $capabilities = '';
-
-main();
-exit(0);
-
-# Main function.
-# Loops through the input file and creates lists of items for each section.
-sub main {
-	my $section = "";
-	my $output_binary = 0;
-
-	GetOptions('binary' => \$output_binary);			   
-	my ($infile, $outfile) = @ARGV;
-	
-	if (defined $infile) {
-		open IN, "$infile" || die "Cannot open input file $infile";
-	}
-	else {
-		*IN = *STDIN;
-	}
-
-	if (defined $outfile) {
-		open OUT,  ">$outfile" || die "Cannot open input file $outfile";
-	}
-	else {
-		*OUT = *STDOUT;
-	}
-	
-	while (<IN>) {
-		chomp;
-		if (/^\s*\[\w*\]/) {
-			# Process the new section name
-			
-			s/.*\[\s*(.*)\s*].*/$1/g;
-			$section = lc($_);
-    		$sections{$section} = 1;
-	    }
-	    elsif (/^\s*\#/) {
-			# Comment - ignore
-		}
-	    elsif (/.*=.*/ ) {
-			# Process element within section
-			s/.*=//g;
-			if ($section eq "device_id_list") {
-				push @device_id_list, $_;
-			}
-            elsif ($section eq "sid_list") {
-                push @sid_list, $_;
-			}
-			elsif ($section eq "vid_list") {
-				push @vid_list, $_;
-			}
-			elsif ($section eq "cert_capabilities") {
-
-				if (! $capabilities eq "") {
-					die "Error: Multiple capability constraints defined.";
-				}
-
-				$capabilities = $_;
-				if ($capabilities eq "" || $capabilities =~ /^\s*[01]+\s*$/)  {
-					# Handle explicit bit strings
-					$capabilities =~ s/\s//g;
-				}
-				else {
-					# Convert MMP syntax into an explicit bit string
-					$capabilities = &encode_capabilities($capabilities);					
-				}
-			}
-			else {
-				# Not in a section so ignore text
-			}
-		}   
-   }   
- 
-   if ($output_binary) {
-	   print_to_der();  
-   }
-   else {
-       print_to_cnf();
-   }
-   close IN;
-   close OUT;
-}
-
-# Test function which outputs the binary DER encoding. This can be vieweed using an
-# ASN.1 viewer.
-# This is really a debug function.
-sub print_to_der {
-	my $seq_octets = 0; 
-	my $seq_content = "";
-
-	if (defined $sections{"device_id_list"}) { 
-		$seq_content .= ":" . &encode_string_list(\@device_id_list, \$seq_octets);
-	}
-	
-	if (defined $sections{"sid_list"}) {
-		$seq_content .= ":" . &encode_integer_list(\@sid_list, \$seq_octets);
-	}
-
-	if (defined $sections{"vid_list"}) {
-		$seq_content .= ":" . &encode_integer_list(\@vid_list, \$seq_octets);
-	}
-
-	if (defined $sections{"cert_capabilities"}) {
-		$seq_content .= ":" . &encode_bit_string($capabilities, \$seq_octets);
-	}
-	# Tidy up repreated colons
-	$seq_content =~ s/::/:/;
-	$seq_content =~ s/^://g;
-	
-	my $seq_length_octets;
-	my $seq_length = &encode_length($seq_octets, \$seq_length_octets);
-	my $seq ="$DER_SEQUENCE_TAG:$seq_length:$seq_content";
-	
-	$seq =~ s/::/:/g;
-	$seq = uc($seq);
-	
-	binmode(OUT);
-	foreach (split(/:/, $seq)){
-		print OUT pack('C', hex);
-	}
-}
-
-# Output to a format that can be read by Open SSL using the -extfile parameter
-sub print_to_cnf {
-   print OUT "extensions = extend\n";
-   print OUT "[extend]\n";
-   
-   my $octets = 0; 
-   my $output = "";
-
-   if (defined $sections{"device_id_list"}) {
-	   $output .= "# Device ID List\n" .
-		   $OID_DEVICE_ID_LIST . "= critical, " . "DER:" . 
-		   uc(&encode_string_list(\@device_id_list, \$octets)) . "\n";
-   }      
-   
-   if (defined $sections{"sid_list"}) {
-	   $output .= "# SID List\n" .
-		   $OID_SID_LIST . "= critical, " . "DER:" . 
-		   uc(&encode_integer_list(\@sid_list, \$octets)) . "\n";
-   }   
-
-   if (defined $sections{"vid_list"}) {
-	   $output .= "# VID List\n" .
-	   $OID_VID_LIST . "= critical, " . "DER:" . uc(&encode_integer_list(\@vid_list, \$octets)) . "\n";
-   }   
-
-   if (defined $sections{"cert_capabilities"}) {
-	   $output .= "# Capabilities\n" .
-		   $OID_CAPABILITIES . "= critical, " . "DER:" . uc(&encode_bit_string($capabilities, \$octets)) . "\n";
-   }   
-   
-   # Remove trailing colons
-   $output=~ s/\:*$//mg;
-   print OUT $output;
-}
-
-# Creates a hex representation of the DER encoding of a sequence of strings.
-sub encode_string_list($$) {
-	my ($list, $octets) = @_;
-	
-	my $sequence_body = "";
-	
-	my $sequence_octets = 0;
-	foreach (@$list) {
-		my $hex_string = &encode_utf8_string($_, \$sequence_octets);
-
-		# Add to string sequence body
-		if ($sequence_body ne "") {
-			$sequence_body .= ":";
-		}
-		$sequence_body .= $hex_string;
-	}
-	my $seq_length_octets = 0;
-	my $seq_length = &encode_length($sequence_octets, \$seq_length_octets);
-
-	$$octets += 1 + $seq_length_octets + $sequence_octets;
-
-	return "$DER_SEQUENCE_TAG:$seq_length:$sequence_body";
-}
-
-# Creates a hex represenation of the DER encoding of a sequence of integers.
-sub encode_integer_list($$) {
-	my ($list, $octets) = @_;	
-
-	my $sequence_body = "";
-	my $sequence_octets = 0;
-	foreach (@$list) {
-		# Increment for integer tag value
-		# Increment for integer length < 127 octets assumed !
-		$sequence_octets+=2;
-
-		if (s/^0x//) {
-			$_ = hex;
-		}
-		
-		# Convert the integer to base 256 hex and find out how
-		# many octets were required
-		my $hex_octets;
-		my $hex_integer;
-		if (//) {
-			$hex_octets = 0;
-			$hex_integer = "";
-		}
-		else {
-			$hex_integer = &to_hex_base256($_, \$hex_octets);
-			$sequence_octets += $hex_octets;
-		}
-		
-		# Add to integer  sequence body
-		if ($sequence_body ne "") {
-			$sequence_body .= ":";
-		}
-		
-		# No need to store length in long form because in base256
-		# we never need more than 7 octets to store the largest number
-		# that we need.
-		my $int_header = sprintf("%2.2x", $hex_octets);
-		$sequence_body .= "$DER_INTEGER_TAG:$int_header:$hex_integer";		
-	}
-
-	# Get the number of octets of the entire sequence. This could require
-	# encoding in long form.
-	my $seq_length_octets = 0;
-	my $seq_length = &encode_length($sequence_octets, \$seq_length_octets);
-
-	$$octets += 1 + $seq_length_octets + $sequence_octets;
-
-	return "$DER_SEQUENCE_TAG:$seq_length:$sequence_body";
-}
-
-# Creates a hex represenation of the DER encoding of a UTF-8 string.
-sub encode_utf8_string($$) {
-	my ($input, $octets) = @_;
-
-	# Hex encoded string
-	my $output = "";
-	my $input_len = length($input);	
-	my $i = 0;
-	while ($i < $input_len) {
-		my $hex_val = ord(substr($input, $i, 1));
-		if ($output ne "") {
-			$output .= ":";
-		}
-		$output .= sprintf("%2.2x", $hex_val);
-		$i++;
-	}
-	
-	# Build string header
-	my $output_length_octets = 0;		
-	my $output_length = &encode_length($input_len, \$output_length_octets);
-	
-	# Track number of octets added for string header
-	$$octets += 1 + $output_length_octets + $input_len;
-	return "$DER_UTF8STRING_TAG:$output_length:$output";
-}
-
-# Converts the text description of capabilities into an ASCII string of 0s and 1s;
-sub encode_capabilities($) {
-	my ($value) = @_;
-	my $output = "";
-	my @caps = (0);
-	
-	$value = uc($value);
-	foreach (split(/[\s,]/, $value)) {
-		my $set_val = 1;
-
-		if (s/^-//g) {
-			$set_val = 0;
-		}
-		
-		if (/^ALL$/) {
-			foreach (keys %CAPABILITY_SET) {
-				@caps[$CAPABILITY_SET{$_}] = 1;
-			}
-		}
-	    elsif (/^NONE$/) {
-			@caps = ();
-		}
-		if (defined $CAPABILITY_SET{$_}) {
-			$caps[$CAPABILITY_SET{$_}] = $set_val;
-		}
-	}
-
-	# Build the ascii bit string. Bit 0 is the left most bit
-	for (my $i = 0; $i <= $#caps; $i++) {
-		$output .= (defined $caps[$i] && $caps[$i] ? "1" : "0");
-	}
-
-	return $output;
-}
-
-# Creates a hex representation of the DER encoding of an arbitrary length bit string
-sub encode_bit_string($$) {
-	my ($text, $octets) = @_;
-
-	# Bit string in hex including padding length octet
-	my $bit_str = "";
-	my $bit_str_octets = 1; # one octet for padding
-
-	# Current byte
-	my $byte = 0;	
-	my $len = length($text);
-
-	if ($len == 0) {
-		$$octets+=2;
-		return "03:00";
-	}
-
-	my $i = 0;
-	while ($i < $len) {		
-
-		# Read the ith character and insert it in the correct place in the byte
-		# (fill from the left)
-		my $c = substr($text, $i, 1);		
-		if ($c eq "1") {
-			$byte |= (1 << (7 - ($i % 8)));
-		}
-		elsif ($c ne "0") {
-			die "Invalid character $c in bit string $text";
-		}
-
-		if (++$i % 8 == 0) {
-			# Received 8 bits so output byte in hex
-			if ($bit_str ne "") {
-				$bit_str .= ":";
-			}
-			$bit_str .= sprintf("%2.2x", $byte);
-			$bit_str_octets++;
-			$byte = 0;
-		}
-	}
-	# Pad any remaining bits / make sure 0 is output for empty string
-	if ($byte != 0 || $bit_str_octets == 1) {
-		if ($bit_str ne "") {
-			$bit_str .= ":";
-		}
-		$bit_str .= sprintf("%2.2x", $byte);
-		$bit_str_octets++;
-	}
-
-	my $pad_length = "00";
-	if ($len % 8 > 0) {
-		# If this isn't a multiple of 8 bits then calculated
-		# the number of padding bits added.
-		$pad_length = sprintf("%2.2x", 8 - ($len % 8));
-	}
-	
-	# Octets used to store the length
-	my $bit_str_length_octets = 0;
-	my $bit_str_length = &encode_length($bit_str_octets, \$bit_str_length_octets);
-	$$octets += 1 + $bit_str_length_octets + $bit_str_octets;
-
-	return "$DER_BITSTRING_TAG:$bit_str_length:$pad_length:$bit_str";
-}
-
-# Return a hex represenation of the length using DER primitive (definate length encoding)
-sub encode_length($$) {
-	my ($num, $octets) = @_;
-
-	if ($num < 128) {
-		# Number is < 128 so encode in short form
-		$$octets++;
-		return sprintf("%2.2x", $num);
-	}
-	else {
-		# Number >= 128 so encode in long form
-		my $length_octets = 0;
-		my $base256 = &to_hex_base256($num, \$length_octets);
-		if ($length_octets > 127) {die "Encoding overflow.";}
-		
-		$$octets += 1 + $length_octets;
-		
-		# Set the top bit of the length octet to indicate long form		
-		return "" . sprintf("%2.2x", ($length_octets | 0x80)) . ":$base256";
-	}
-}
-
-# Convert an integer into an ascii hex representation in base 256
-# $num    - the number to encode
-# $octets - refernce to the octet count to increment
-sub to_hex_base256($$) {
-	my ($num, $octets) = @_;
-
-	my $base256 = "";
-	$num = int($num);
-	while ($num > 0) {
-		my $hexoctet = sprintf("%2.2x", $num & 0xFF);
-		if ($base256 ne "") {
-			$base256 = "$hexoctet:$base256";
-		}
-		else {
-			$base256 = $hexoctet;
-		}		
-		$num >>= 8;
-		$$octets++;
-	}
-	if ($base256 eq "") {
-		$base256 = "0";
-		$$octets++;
-	}
-	return $base256;
-}
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the License "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description: 
+#
+#!/bin/perl -w
+
+# Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the License "Symbian Foundation License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# This script converts certificate constraint extensions specified in an INI 
+# format into a hex representation of the DER encoding that OpenSSL can 
+# add to a certificate.
+# This script allows corrupt certificate extensions to be generated for unit 
+# testing and therefore using this script to create production certificates is
+# NOT supported.
+# See SGL.GT0220.255_Developer_Certificates.doc for usage instructions.
+# 
+#
+
+use strict;
+use Getopt::Long;
+
+my $OID_DEVICE_ID_LIST="1.2.826.0.1.1796587.1.1.1.1";
+my $OID_SID_LIST="1.2.826.0.1.1796587.1.1.1.4";
+my $OID_VID_LIST="1.2.826.0.1.1796587.1.1.1.5";
+my $OID_CAPABILITIES="1.2.826.0.1.1796587.1.1.1.6";
+
+# Reserved for future use
+#my $OID_SUBSCRIBER_ID_LIST="1.2.826.0.1.1796587.1.1.2.2"; 
+#my $OID_ICC_ID_LIST="1.2.826.0.1.1796587.1.1.1.3";
+
+my $DER_UTF8STRING_TAG="0C";
+my $DER_PRINTABLESTRING_TAG="13";
+my $DER_SEQUENCE_TAG="30";
+my $DER_INTEGER_TAG="02";
+my $DER_BITSTRING_TAG="03";
+my $DER_OCTET_TAG="04";
+
+my %CAPABILITY_SET = (
+	"TCB" => 0,
+	"COMMDD" => 1,
+	"POWERMGMT" => 2,
+	"MULTIMEDIADD" => 3,
+	"READDEVICEDATA" => 4,
+	"WRITEDEVICEDATA" => 5,
+	"DRM" => 6,
+	"TRUSTEDUI" => 7,
+	"PROTSERV" => 8,
+	"DISKADMIN" => 9,
+	"NETWORKCONTROL" => 10,
+	"ALLFILES" => 11,
+	"SWEVENT" => 12,
+	"NETWORKSERVICES" => 13,
+	"LOCALSERVICES" => 14,
+	"READUSERDATA" => 15,
+	"WRITEUSERDATA" => 16,
+	"LOCATION" => 17,
+	"SURROUNDINGSDD" => 18,
+	"USERENVIRONMENT" => 19	
+	);
+
+# Sections encountered
+my %sections;
+
+# Fields within sectins
+my @device_id_list = ();
+my @sid_list = ();
+my @vid_list = ();
+my $capabilities = '';
+
+main();
+exit(0);
+
+# Main function.
+# Loops through the input file and creates lists of items for each section.
+sub main {
+	my $section = "";
+	my $output_binary = 0;
+
+	GetOptions('binary' => \$output_binary);			   
+	my ($infile, $outfile) = @ARGV;
+	
+	if (defined $infile) {
+		open IN, "$infile" || die "Cannot open input file $infile";
+	}
+	else {
+		*IN = *STDIN;
+	}
+
+	if (defined $outfile) {
+		open OUT,  ">$outfile" || die "Cannot open input file $outfile";
+	}
+	else {
+		*OUT = *STDOUT;
+	}
+	
+	while (<IN>) {
+		chomp;
+		if (/^\s*\[\w*\]/) {
+			# Process the new section name
+			
+			s/.*\[\s*(.*)\s*].*/$1/g;
+			$section = lc($_);
+    		$sections{$section} = 1;
+	    }
+	    elsif (/^\s*\#/) {
+			# Comment - ignore
+		}
+	    elsif (/.*=.*/ ) {
+			# Process element within section
+			s/.*=//g;
+			if ($section eq "device_id_list") {
+				push @device_id_list, $_;
+			}
+            elsif ($section eq "sid_list") {
+                push @sid_list, $_;
+			}
+			elsif ($section eq "vid_list") {
+				push @vid_list, $_;
+			}
+			elsif ($section eq "cert_capabilities") {
+
+				if (! $capabilities eq "") {
+					die "Error: Multiple capability constraints defined.";
+				}
+
+				$capabilities = $_;
+				if ($capabilities eq "" || $capabilities =~ /^\s*[01]+\s*$/)  {
+					# Handle explicit bit strings
+					$capabilities =~ s/\s//g;
+				}
+				else {
+					# Convert MMP syntax into an explicit bit string
+					$capabilities = &encode_capabilities($capabilities);					
+				}
+			}
+			else {
+				# Not in a section so ignore text
+			}
+		}   
+   }   
+ 
+   if ($output_binary) {
+	   print_to_der();  
+   }
+   else {
+       print_to_cnf();
+   }
+   close IN;
+   close OUT;
+}
+
+# Test function which outputs the binary DER encoding. This can be vieweed using an
+# ASN.1 viewer.
+# This is really a debug function.
+sub print_to_der {
+	my $seq_octets = 0; 
+	my $seq_content = "";
+
+	if (defined $sections{"device_id_list"}) { 
+		$seq_content .= ":" . &encode_string_list(\@device_id_list, \$seq_octets);
+	}
+	
+	if (defined $sections{"sid_list"}) {
+		$seq_content .= ":" . &encode_integer_list(\@sid_list, \$seq_octets);
+	}
+
+	if (defined $sections{"vid_list"}) {
+		$seq_content .= ":" . &encode_integer_list(\@vid_list, \$seq_octets);
+	}
+
+	if (defined $sections{"cert_capabilities"}) {
+		$seq_content .= ":" . &encode_bit_string($capabilities, \$seq_octets);
+	}
+	# Tidy up repreated colons
+	$seq_content =~ s/::/:/;
+	$seq_content =~ s/^://g;
+	
+	my $seq_length_octets;
+	my $seq_length = &encode_length($seq_octets, \$seq_length_octets);
+	my $seq ="$DER_SEQUENCE_TAG:$seq_length:$seq_content";
+	
+	$seq =~ s/::/:/g;
+	$seq = uc($seq);
+	
+	binmode(OUT);
+	foreach (split(/:/, $seq)){
+		print OUT pack('C', hex);
+	}
+}
+
+# Output to a format that can be read by Open SSL using the -extfile parameter
+sub print_to_cnf {
+   print OUT "extensions = extend\n";
+   print OUT "[extend]\n";
+   
+   my $octets = 0; 
+   my $output = "";
+
+   if (defined $sections{"device_id_list"}) {
+	   $output .= "# Device ID List\n" .
+		   $OID_DEVICE_ID_LIST . "= critical, " . "DER:" . 
+		   uc(&encode_string_list(\@device_id_list, \$octets)) . "\n";
+   }      
+   
+   if (defined $sections{"sid_list"}) {
+	   $output .= "# SID List\n" .
+		   $OID_SID_LIST . "= critical, " . "DER:" . 
+		   uc(&encode_integer_list(\@sid_list, \$octets)) . "\n";
+   }   
+
+   if (defined $sections{"vid_list"}) {
+	   $output .= "# VID List\n" .
+	   $OID_VID_LIST . "= critical, " . "DER:" . uc(&encode_integer_list(\@vid_list, \$octets)) . "\n";
+   }   
+
+   if (defined $sections{"cert_capabilities"}) {
+	   $output .= "# Capabilities\n" .
+		   $OID_CAPABILITIES . "= critical, " . "DER:" . uc(&encode_bit_string($capabilities, \$octets)) . "\n";
+   }   
+   
+   # Remove trailing colons
+   $output=~ s/\:*$//mg;
+   print OUT $output;
+}
+
+# Creates a hex representation of the DER encoding of a sequence of strings.
+sub encode_string_list($$) {
+	my ($list, $octets) = @_;
+	
+	my $sequence_body = "";
+	
+	my $sequence_octets = 0;
+	foreach (@$list) {
+		my $hex_string = &encode_utf8_string($_, \$sequence_octets);
+
+		# Add to string sequence body
+		if ($sequence_body ne "") {
+			$sequence_body .= ":";
+		}
+		$sequence_body .= $hex_string;
+	}
+	my $seq_length_octets = 0;
+	my $seq_length = &encode_length($sequence_octets, \$seq_length_octets);
+
+	$$octets += 1 + $seq_length_octets + $sequence_octets;
+
+	return "$DER_SEQUENCE_TAG:$seq_length:$sequence_body";
+}
+
+# Creates a hex represenation of the DER encoding of a sequence of integers.
+sub encode_integer_list($$) {
+	my ($list, $octets) = @_;	
+
+	my $sequence_body = "";
+	my $sequence_octets = 0;
+	foreach (@$list) {
+		# Increment for integer tag value
+		# Increment for integer length < 127 octets assumed !
+		$sequence_octets+=2;
+
+		if (s/^0x//) {
+			$_ = hex;
+		}
+		
+		# Convert the integer to base 256 hex and find out how
+		# many octets were required
+		my $hex_octets;
+		my $hex_integer;
+		if (//) {
+			$hex_octets = 0;
+			$hex_integer = "";
+		}
+		else {
+			$hex_integer = &to_hex_base256($_, \$hex_octets);
+			$sequence_octets += $hex_octets;
+		}
+		
+		# Add to integer  sequence body
+		if ($sequence_body ne "") {
+			$sequence_body .= ":";
+		}
+		
+		# No need to store length in long form because in base256
+		# we never need more than 7 octets to store the largest number
+		# that we need.
+		my $int_header = sprintf("%2.2x", $hex_octets);
+		$sequence_body .= "$DER_INTEGER_TAG:$int_header:$hex_integer";		
+	}
+
+	# Get the number of octets of the entire sequence. This could require
+	# encoding in long form.
+	my $seq_length_octets = 0;
+	my $seq_length = &encode_length($sequence_octets, \$seq_length_octets);
+
+	$$octets += 1 + $seq_length_octets + $sequence_octets;
+
+	return "$DER_SEQUENCE_TAG:$seq_length:$sequence_body";
+}
+
+# Creates a hex represenation of the DER encoding of a UTF-8 string.
+sub encode_utf8_string($$) {
+	my ($input, $octets) = @_;
+
+	# Hex encoded string
+	my $output = "";
+	my $input_len = length($input);	
+	my $i = 0;
+	while ($i < $input_len) {
+		my $hex_val = ord(substr($input, $i, 1));
+		if ($output ne "") {
+			$output .= ":";
+		}
+		$output .= sprintf("%2.2x", $hex_val);
+		$i++;
+	}
+	
+	# Build string header
+	my $output_length_octets = 0;		
+	my $output_length = &encode_length($input_len, \$output_length_octets);
+	
+	# Track number of octets added for string header
+	$$octets += 1 + $output_length_octets + $input_len;
+	return "$DER_UTF8STRING_TAG:$output_length:$output";
+}
+
+# Converts the text description of capabilities into an ASCII string of 0s and 1s;
+sub encode_capabilities($) {
+	my ($value) = @_;
+	my $output = "";
+	my @caps = (0);
+	
+	$value = uc($value);
+	foreach (split(/[\s,]/, $value)) {
+		my $set_val = 1;
+
+		if (s/^-//g) {
+			$set_val = 0;
+		}
+		
+		if (/^ALL$/) {
+			foreach (keys %CAPABILITY_SET) {
+				@caps[$CAPABILITY_SET{$_}] = 1;
+			}
+		}
+	    elsif (/^NONE$/) {
+			@caps = ();
+		}
+		if (defined $CAPABILITY_SET{$_}) {
+			$caps[$CAPABILITY_SET{$_}] = $set_val;
+		}
+	}
+
+	# Build the ascii bit string. Bit 0 is the left most bit
+	for (my $i = 0; $i <= $#caps; $i++) {
+		$output .= (defined $caps[$i] && $caps[$i] ? "1" : "0");
+	}
+
+	return $output;
+}
+
+# Creates a hex representation of the DER encoding of an arbitrary length bit string
+sub encode_bit_string($$) {
+	my ($text, $octets) = @_;
+
+	# Bit string in hex including padding length octet
+	my $bit_str = "";
+	my $bit_str_octets = 1; # one octet for padding
+
+	# Current byte
+	my $byte = 0;	
+	my $len = length($text);
+
+	if ($len == 0) {
+		$$octets+=2;
+		return "03:00";
+	}
+
+	my $i = 0;
+	while ($i < $len) {		
+
+		# Read the ith character and insert it in the correct place in the byte
+		# (fill from the left)
+		my $c = substr($text, $i, 1);		
+		if ($c eq "1") {
+			$byte |= (1 << (7 - ($i % 8)));
+		}
+		elsif ($c ne "0") {
+			die "Invalid character $c in bit string $text";
+		}
+
+		if (++$i % 8 == 0) {
+			# Received 8 bits so output byte in hex
+			if ($bit_str ne "") {
+				$bit_str .= ":";
+			}
+			$bit_str .= sprintf("%2.2x", $byte);
+			$bit_str_octets++;
+			$byte = 0;
+		}
+	}
+	# Pad any remaining bits / make sure 0 is output for empty string
+	if ($byte != 0 || $bit_str_octets == 1) {
+		if ($bit_str ne "") {
+			$bit_str .= ":";
+		}
+		$bit_str .= sprintf("%2.2x", $byte);
+		$bit_str_octets++;
+	}
+
+	my $pad_length = "00";
+	if ($len % 8 > 0) {
+		# If this isn't a multiple of 8 bits then calculated
+		# the number of padding bits added.
+		$pad_length = sprintf("%2.2x", 8 - ($len % 8));
+	}
+	
+	# Octets used to store the length
+	my $bit_str_length_octets = 0;
+	my $bit_str_length = &encode_length($bit_str_octets, \$bit_str_length_octets);
+	$$octets += 1 + $bit_str_length_octets + $bit_str_octets;
+
+	return "$DER_BITSTRING_TAG:$bit_str_length:$pad_length:$bit_str";
+}
+
+# Return a hex represenation of the length using DER primitive (definate length encoding)
+sub encode_length($$) {
+	my ($num, $octets) = @_;
+
+	if ($num < 128) {
+		# Number is < 128 so encode in short form
+		$$octets++;
+		return sprintf("%2.2x", $num);
+	}
+	else {
+		# Number >= 128 so encode in long form
+		my $length_octets = 0;
+		my $base256 = &to_hex_base256($num, \$length_octets);
+		if ($length_octets > 127) {die "Encoding overflow.";}
+		
+		$$octets += 1 + $length_octets;
+		
+		# Set the top bit of the length octet to indicate long form		
+		return "" . sprintf("%2.2x", ($length_octets | 0x80)) . ":$base256";
+	}
+}
+
+# Convert an integer into an ascii hex representation in base 256
+# $num    - the number to encode
+# $octets - refernce to the octet count to increment
+sub to_hex_base256($$) {
+	my ($num, $octets) = @_;
+
+	my $base256 = "";
+	$num = int($num);
+	while ($num > 0) {
+		my $hexoctet = sprintf("%2.2x", $num & 0xFF);
+		if ($base256 ne "") {
+			$base256 = "$hexoctet:$base256";
+		}
+		else {
+			$base256 = $hexoctet;
+		}		
+		$num >>= 8;
+		$$octets++;
+	}
+	if ($base256 eq "") {
+		$base256 = "0";
+		$$octets++;
+	}
+	return $base256;
+}