| #!/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="openssl asn1parse"; |
| $x509_cmd="openssl x509"; |
| $crl_cmd="openssl crl"; |
| $rc4_cmd="openssl rc4"; |
| $md2_cmd="openssl md2"; |
| $md4_cmd="openssl md4"; |
| $rsa_cmd="openssl 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); |
| } |
| |