mirror of https://github.com/openssl/openssl.git
				
				
				
			
		
			
	
	
		
			306 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			306 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | #!/usr/local/bin/perl | ||
|  | # | ||
|  | # der_chop ... this is one total hack that Eric is really not proud of | ||
|  | #              so don't look at it and don't ask for support | ||
|  | # | ||
|  | # The "documentation" for this (i.e. all the comments) are my fault --tjh | ||
|  | # | ||
|  | # This program takes the "raw" output of derparse/asn1parse and  | ||
|  | # converts it into tokens and then runs regular expression matches | ||
|  | # to try to figure out what to grab to get the things that are needed | ||
|  | # and it is possible that this will do the wrong thing as it is a *hack* | ||
|  | # | ||
|  | # SSLeay 0.5.2+ should have direct read support for x509 (via -inform NET) | ||
|  | # [I know ... promises promises :-)] | ||
|  | # | ||
|  | # To convert a Netscape Certificate: | ||
|  | #    der_chop < ServerCert.der > cert.pem | ||
|  | # To convert a Netscape Key (and encrypt it again to protect it) | ||
|  | #    rsa -inform NET -in ServerKey.der -des > key.pem | ||
|  | # | ||
|  | # 23-Apr-96 eay    Added the extra ASN.1 string types, I still think this | ||
|  | #		   is an evil hack.  If nothing else the parsing should | ||
|  | #		   be relative, not absolute. | ||
|  | # 19-Apr-96 tjh    hacked (with eay) into 0.5.x format | ||
|  | # | ||
|  | # Tim Hudson | ||
|  | # tjh@cryptsoft.com | ||
|  | # | ||
|  | 
 | ||
|  | 
 | ||
|  | require 'getopts.pl'; | ||
|  | 
 | ||
|  | $debug=0; | ||
|  | 
 | ||
|  | # this was the 0.4.x way of doing things ... | ||
|  | $cmd="derparse"; | ||
|  | $x509_cmd="x509"; | ||
|  | $crl_cmd="crl"; | ||
|  | $rc4_cmd="rc4"; | ||
|  | $md2_cmd="md2"; | ||
|  | $md4_cmd="md4"; | ||
|  | $rsa_cmd="rsa -des -inform der "; | ||
|  | 
 | ||
|  | # this was the 0.5.x way of doing things ... | ||
|  | $cmd="ssleay asn1parse"; | ||
|  | $x509_cmd="ssleay x509"; | ||
|  | $crl_cmd="ssleay crl"; | ||
|  | $rc4_cmd="ssleay rc4"; | ||
|  | $md2_cmd="ssleay md2"; | ||
|  | $md4_cmd="ssleay md4"; | ||
|  | $rsa_cmd="ssleay rsa -des -inform der "; | ||
|  | 
 | ||
|  | &Getopts('vd:') || die "usage:$0 [-v] [-d num] file"; | ||
|  | $depth=($opt_d =~ /^\d+$/)?$opt_d:0; | ||
|  | 
 | ||
|  | &init_der(); | ||
|  | 
 | ||
|  | if ($#ARGV != -1) | ||
|  | 	{ | ||
|  | 	foreach $file (@ARGV) | ||
|  | 		{ | ||
|  | 		print STDERR "doing $file\n"; | ||
|  | 		&dofile($file); | ||
|  | 		} | ||
|  | 	} | ||
|  | else | ||
|  | 	{ | ||
|  | 	$file="/tmp/a$$.DER"; | ||
|  | 	open(OUT,">$file") || die "unable to open $file:$!\n"; | ||
|  | 	for (;;) | ||
|  | 		{ | ||
|  | 		$i=sysread(STDIN,$b,1024*10); | ||
|  | 		last if ($i <= 0); | ||
|  | 		$i=syswrite(OUT,$b,$i); | ||
|  | 		} | ||
|  | 	&dofile($file); | ||
|  | 	unlink($file); | ||
|  | 	} | ||
|  | 	 | ||
|  | sub dofile | ||
|  | 	{ | ||
|  | 	local($file)=@_; | ||
|  | 	local(@p); | ||
|  | 
 | ||
|  | 	$b=&load_file($file); | ||
|  | 	@p=&load_file_parse($file); | ||
|  | 
 | ||
|  | 	foreach $_ (@p) | ||
|  | 		{ | ||
|  | 		($off,$d,$hl,$len)=&parse_line($_); | ||
|  | 		$d-=$depth; | ||
|  | 		next if ($d != 0); | ||
|  | 		next if ($len == 0); | ||
|  | 
 | ||
|  | 		$o=substr($b,$off,$len+$hl); | ||
|  | 		($str,@data)=&der_str($o); | ||
|  | 		print "$str\n" if ($opt_v); | ||
|  | 		if ($str =~ /^$crl/) | ||
|  | 			{ | ||
|  | 			open(OUT,"|$crl_cmd -inform d -hash -issuer") || | ||
|  | 				die "unable to run $crl_cmd:$!\n"; | ||
|  | 			print OUT $o; | ||
|  | 			close(OUT); | ||
|  | 			} | ||
|  | 		elsif ($str =~ /^$x509/) | ||
|  | 			{ | ||
|  | 			open(OUT,"|$x509_cmd -inform d -hash -subject -issuer") | ||
|  | 				|| die "unable to run $x509_cmd:$!\n"; | ||
|  | 			print OUT $o; | ||
|  | 			close(OUT); | ||
|  | 			} | ||
|  | 		elsif ($str =~ /^$rsa/) | ||
|  | 			{ | ||
|  | 			($type)=($data[3] =~ /OBJECT_IDENTIFIER :(.*)\s*$/); | ||
|  | 			next unless ($type eq "rsaEncryption"); | ||
|  | 			($off,$d,$hl,$len)=&parse_line($data[5]); | ||
|  | 			$os=substr($o,$off+$hl,$len); | ||
|  | 			open(OUT,"|$rsa_cmd") | ||
|  | 				|| die "unable to run $rsa_cmd:$!\n"; | ||
|  | 			print OUT $os; | ||
|  | 			close(OUT); | ||
|  | 			} | ||
|  | 		elsif ($str =~ /^0G-1D-1G/) | ||
|  | 			{ | ||
|  | 			($off,$d,$hl,$len)=&parse_line($data[1]); | ||
|  | 			$os=substr($o,$off+$hl,$len); | ||
|  | 			print STDERR "<$os>\n" if $opt_v; | ||
|  | 			&do_certificate($o,@data) | ||
|  | 				if (($os eq "certificate") && | ||
|  | 				    ($str =! /^0G-1D-1G-2G-3F-3E-2D/)); | ||
|  | 			&do_private_key($o,@data) | ||
|  | 				if (($os eq "private-key") && | ||
|  | 				    ($str =! /^0G-1D-1G-2G-3F-3E-2D/)); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | sub der_str | ||
|  | 	{ | ||
|  | 	local($str)=@_; | ||
|  | 	local(*OUT,*IN,@a,$t,$d,$ret); | ||
|  | 	local($file)="/tmp/b$$.DER"; | ||
|  | 	local(@ret); | ||
|  | 
 | ||
|  | 	open(OUT,">$file"); | ||
|  | 	print OUT $str; | ||
|  | 	close(OUT); | ||
|  | 	open(IN,"$cmd -inform 'd' -in $file |") || | ||
|  | 		die "unable to run $cmd:$!\n"; | ||
|  | 	$ret=""; | ||
|  | 	while (<IN>) | ||
|  | 		{ | ||
|  | 		chop; | ||
|  | 		push(@ret,$_); | ||
|  | 
 | ||
|  | 		print STDERR "$_\n" if ($debug); | ||
|  | 
 | ||
|  | 		@a=split(/\s*:\s*/); | ||
|  | 		($d)=($a[1] =~ /d=\s*(\d+)/); | ||
|  | 		$a[2] =~ s/\s+$//; | ||
|  | 		$t=$DER_s2i{$a[2]}; | ||
|  | 		$ret.="$d$t-"; | ||
|  | 		} | ||
|  | 	close(IN); | ||
|  | 	unlink($file); | ||
|  | 	chop $ret; | ||
|  | 	$ret =~ s/(-3H(-4G-5F-5[IJKMQRS])+)+/-NAME/g; | ||
|  | 	$ret =~ s/(-3G-4B-4L)+/-RCERT/g; | ||
|  | 	return($ret,@ret); | ||
|  | 	} | ||
|  | 
 | ||
|  | sub init_der | ||
|  | 	{ | ||
|  | 	$crl= "0G-1G-2G-3F-3E-2G-NAME-2L-2L-2G-RCERT-1G-2F-2E-1C"; | ||
|  | 	$x509="0G-1G-2B-2G-3F-3E-2G-NAME-2G-3L-3L-2G-NAME-2G-3G-4F-4E-3C-1G-2F-2E-1C"; | ||
|  | 	$rsa= "0G-1B-1G-2F-2E-1D"; | ||
|  | 
 | ||
|  | 	%DER_i2s=( | ||
|  | 		# SSLeay 0.4.x has this list | ||
|  | 		"A","EOC", | ||
|  | 		"B","INTEGER", | ||
|  | 		"C","BIT STRING", | ||
|  | 		"D","OCTET STRING", | ||
|  | 		"E","NULL", | ||
|  | 		"F","OBJECT", | ||
|  | 		"G","SEQUENCE", | ||
|  | 		"H","SET", | ||
|  | 		"I","PRINTABLESTRING", | ||
|  | 		"J","T61STRING", | ||
|  | 		"K","IA5STRING", | ||
|  | 		"L","UTCTIME", | ||
|  | 		"M","NUMERICSTRING", | ||
|  | 		"N","VIDEOTEXSTRING", | ||
|  | 		"O","GENERALIZEDTIME", | ||
|  | 		"P","GRAPHICSTRING", | ||
|  | 		"Q","ISO64STRING", | ||
|  | 		"R","GENERALSTRING", | ||
|  | 		"S","UNIVERSALSTRING", | ||
|  | 
 | ||
|  | 		# SSLeay 0.5.x changed some things ... and I'm | ||
|  | 		# leaving in the old stuff but adding in these | ||
|  | 		# to handle the new as well --tjh | ||
|  | 		# - Well I've just taken them out and added the extra new | ||
|  | 		# ones :-) - eay | ||
|  | 		); | ||
|  | 
 | ||
|  | 	foreach (keys %DER_i2s) | ||
|  | 		{ $DER_s2i{$DER_i2s{$_}}=$_; } | ||
|  | 	} | ||
|  | 
 | ||
|  | sub parse_line | ||
|  | 	{ | ||
|  | 	local($_)=@_; | ||
|  | 
 | ||
|  | 	return(/\s*(\d+):d=\s*(\d+)\s+hl=\s*(\d+)\s+l=\s*(\d+|inf)\s/); | ||
|  | 	} | ||
|  | 
 | ||
|  | #  0:d=0 hl=4 l=377 cons: univ: SEQUENCE           | ||
|  | #  4:d=1 hl=2 l= 11 prim: univ: OCTET_STRING       | ||
|  | # 17:d=1 hl=4 l=360 cons: univ: SEQUENCE           | ||
|  | # 21:d=2 hl=2 l= 12 cons: univ: SEQUENCE           | ||
|  | # 23:d=3 hl=2 l=  8 prim: univ: OBJECT_IDENTIFIER :rc4 | ||
|  | # 33:d=3 hl=2 l=  0 prim: univ: NULL               | ||
|  | # 35:d=2 hl=4 l=342 prim: univ: OCTET_STRING | ||
|  | sub do_private_key | ||
|  | 	{ | ||
|  | 	local($data,@struct)=@_; | ||
|  | 	local($file)="/tmp/b$$.DER"; | ||
|  | 	local($off,$d,$hl,$len,$_,$b,@p,$s); | ||
|  | 
 | ||
|  | 	($type)=($struct[4] =~ /OBJECT_IDENTIFIER :(.*)\s*$/); | ||
|  | 	if ($type eq "rc4") | ||
|  | 		{ | ||
|  | 		($off,$d,$hl,$len)=&parse_line($struct[6]); | ||
|  | 		open(OUT,"|$rc4_cmd >$file") || | ||
|  | 			die "unable to run $rc4_cmd:$!\n"; | ||
|  | 		print OUT substr($data,$off+$hl,$len); | ||
|  | 		close(OUT); | ||
|  | 
 | ||
|  | 		$b=&load_file($file); | ||
|  | 		unlink($file); | ||
|  | 
 | ||
|  | 		($s,@p)=&der_str($b); | ||
|  | 		die "unknown rsa key type\n$s\n" | ||
|  | 			if ($s ne '0G-1B-1G-2F-2E-1D'); | ||
|  | 		local($off,$d,$hl,$len)=&parse_line($p[5]); | ||
|  | 		$b=substr($b,$off+$hl,$len); | ||
|  | 		($s,@p)=&der_str($b); | ||
|  | 		open(OUT,"|$rsa_cmd") || die "unable to run $rsa_cmd:$!\n"; | ||
|  | 		print OUT $b; | ||
|  | 		close(OUT); | ||
|  | 		} | ||
|  | 	else | ||
|  | 		{ | ||
|  | 		print "'$type' is unknown\n"; | ||
|  | 		exit(1); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | sub do_certificate | ||
|  | 	{ | ||
|  | 	local($data,@struct)=@_; | ||
|  | 	local($file)="/tmp/b$$.DER"; | ||
|  | 	local($off,$d,$hl,$len,$_,$b,@p,$s); | ||
|  | 
 | ||
|  | 	($off,$d,$hl,$len)=&parse_line($struct[2]); | ||
|  | 	$b=substr($data,$off,$len+$hl); | ||
|  | 
 | ||
|  | 	open(OUT,"|$x509_cmd -inform d") || die "unable to run $x509_cmd:$!\n"; | ||
|  | 	print OUT $b; | ||
|  | 	close(OUT); | ||
|  | 	} | ||
|  | 
 | ||
|  | sub load_file | ||
|  | 	{ | ||
|  | 	local($file)=@_; | ||
|  | 	local(*IN,$r,$b,$i); | ||
|  | 
 | ||
|  | 	$r=""; | ||
|  | 	open(IN,"<$file") || die "unable to open $file:$!\n"; | ||
|  | 	for (;;) | ||
|  | 		{ | ||
|  | 		$i=sysread(IN,$b,10240); | ||
|  | 		last if ($i <= 0); | ||
|  | 		$r.=$b; | ||
|  | 		} | ||
|  | 	close(IN); | ||
|  | 	return($r); | ||
|  | 	} | ||
|  | 
 | ||
|  | sub load_file_parse | ||
|  | 	{ | ||
|  | 	local($file)=@_; | ||
|  | 	local(*IN,$r,@ret,$_,$i,$n,$b); | ||
|  | 
 | ||
|  | 	open(IN,"$cmd -inform d -in $file|") | ||
|  | 		|| die "unable to run der_parse\n"; | ||
|  | 	while (<IN>) | ||
|  | 		{ | ||
|  | 		chop; | ||
|  | 		push(@ret,$_); | ||
|  | 		} | ||
|  | 	return($r,@ret); | ||
|  | 	} | ||
|  | 
 |