michael@0: #!/usr/bin/perl michael@0: # Usage: michael@0: # PATH=$NSS_PREFIX/bin:$NSS_PREFIX/lib:$PATH ./generate.pl michael@0: michael@0: use Cwd; michael@0: use File::Temp qw/ tempfile tempdir /; michael@0: michael@0: use strict; michael@0: michael@0: my $srcdir=getcwd(); michael@0: my $db = tempdir( CLEANUP => 1 ); michael@0: my $noisefile=$db."/noise"; michael@0: my $passwordfile=$db."/passwordfile"; michael@0: my $ca_responses=$srcdir."/ca_responses"; michael@0: my $ee_responses=$srcdir."/ee_responses"; michael@0: michael@0: #my $db=$tmpdir; michael@0: michael@0: my @base_usages=("", michael@0: "certSigning,crlSigning", michael@0: "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,certSigning,crlSigning", michael@0: "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,crlSigning"); michael@0: michael@0: my @ee_usages=("", michael@0: "digitalSignature,keyEncipherment,dataEncipherment", michael@0: "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement", michael@0: "certSigning"); michael@0: my @eku_usages=("serverAuth,clientAuth,codeSigning,emailProtection,timeStamp,ocspResponder,stepUp,msTrustListSign", michael@0: "serverAuth,clientAuth", michael@0: "codeSigning,emailProtection", michael@0: "timeStamp,ocspResponder,stepUp,msTrustListSign" michael@0: ); michael@0: michael@0: sub dsystem{ michael@0: my @args = @_; michael@0: system(@args) == 0 michael@0: or die "system @args failed: $?"; michael@0: } michael@0: michael@0: sub generate_certs(){ michael@0: for (my $i = 1; $i < scalar(@base_usages) + 1; $i++) { michael@0: my $ca_name = "ca-$i"; michael@0: my $ca_key_usage = $base_usages[$i - 1]; michael@0: if (length($ca_key_usage) > 1) { michael@0: $ca_key_usage = " --keyUsage $ca_key_usage,critical"; michael@0: } michael@0: my $ca_email = "$ca_name\@example.com"; michael@0: my $ca_subject = "CN=$ca_name, E=$ca_email"; michael@0: print "key_usage=$ca_key_usage\n"; michael@0: dsystem("certutil -S -s '$ca_name' -s '$ca_subject' -t 'C,,' -x -m $i -v 120 -n '$ca_name' $ca_key_usage -Z SHA256 -2 -d $db -f $passwordfile -z $noisefile < $ca_responses"); michael@0: michael@0: #and now export michael@0: dsystem("certutil -d $db -f $passwordfile -L -n $ca_name -r -o $srcdir/$ca_name.der"); michael@0: michael@0: for (my $j = 1; $j < scalar(@ee_usages) + 1; $j++) { michael@0: ##do ee certs michael@0: my $ee_name = "ee-$j-ca-$i"; michael@0: my $ee_key_usage = $ee_usages[$j - 1]; michael@0: if (length($ee_key_usage) > 1) { michael@0: $ee_key_usage=" --keyUsage $ee_key_usage,critical"; michael@0: } michael@0: my $serial = (scalar(@base_usages) + 1) * $j + $i; michael@0: dsystem("certutil -S -n '$ee_name' -s 'CN=$ee_name' -c '$ca_name' $ee_key_usage -t 'P,,' -k rsa -g 1024 -Z SHA256 -m $serial -v 120 -d $db -f $passwordfile -z $noisefile < $ee_responses"); michael@0: #and export michael@0: dsystem("certutil -d $db -f $passwordfile -L -n $ee_name -r -o $srcdir/$ee_name.der"); michael@0: } michael@0: for (my $j = 1; $j < scalar(@eku_usages) + 1; $j++){ michael@0: my $ee_name = "ee-" . ($j + scalar(@ee_usages)) . "-ca-$i"; michael@0: my $eku_key_usage = $eku_usages[$j - 1]; michael@0: $eku_key_usage = " --extKeyUsage $eku_key_usage,critical"; michael@0: my $serial = 10000 + (scalar(@base_usages) + 1) * $j + $i; michael@0: dsystem("certutil -S -n '$ee_name' -s 'CN=$ee_name' -c '$ca_name' $eku_key_usage -t 'P,,' -k rsa -g 1024 -Z SHA256 -m $serial -v 120 -d $db -f $passwordfile -z $noisefile < $ee_responses"); michael@0: #and export michael@0: dsystem("certutil -d $db -f $passwordfile -L -n $ee_name -r -o $srcdir/$ee_name.der"); michael@0: michael@0: } michael@0: } michael@0: } michael@0: michael@0: michael@0: sub main(){ michael@0: michael@0: ##setup michael@0: dsystem("echo password1 > $passwordfile"); michael@0: dsystem("head --bytes 32 /dev/urandom > $noisefile"); michael@0: michael@0: ##why no include this in the source dir? michael@0: # XXX: certutil cannot generate basic constraints without interactive prompts, michael@0: # so we need to build response files to answer its questions michael@0: # XXX: certutil cannot generate AKI/SKI without interactive prompts so we just michael@0: # skip them. michael@0: dsystem("echo y > $ca_responses"); # Is this a CA? michael@0: dsystem("echo >> $ca_responses");# Accept default path length constraint (no constraint) michael@0: dsystem("echo y >> $ca_responses"); # Is this a critical constraint? michael@0: dsystem("echo n > $ee_responses"); # Is this a CA? michael@0: dsystem("echo >> $ee_responses"); # Accept default path length constraint (no constraint) michael@0: dsystem("echo y >> $ee_responses"); # Is this a critical constraint? michael@0: michael@0: dsystem("certutil -d $db -N -f $passwordfile"); michael@0: michael@0: generate_certs(); michael@0: michael@0: print "Done\n"; michael@0: michael@0: } michael@0: michael@0: michael@0: main();