diff options
Diffstat (limited to 'apps')
| -rwxr-xr-x | apps/CA.pl | 188 | ||||
| -rw-r--r-- | apps/CA.pl.in | 362 | ||||
| -rw-r--r-- | apps/CA.sh | 198 | ||||
| -rw-r--r-- | apps/Makefile | 1059 | ||||
| -rw-r--r-- | apps/app_rand.c | 249 | ||||
| -rw-r--r-- | apps/apps.c | 2539 | ||||
| -rw-r--r-- | apps/apps.h | 751 | ||||
| -rw-r--r-- | apps/asn1pars.c | 505 | ||||
| -rw-r--r-- | apps/bf_prefix.c | 177 | ||||
| -rw-r--r-- | apps/build.info | 38 | ||||
| -rw-r--r-- | apps/ca-key.pem | 31 | ||||
| -rw-r--r-- | apps/ca-req.pem | 18 | ||||
| -rw-r--r-- | apps/ca.c | 2171 | ||||
| -rw-r--r-- | apps/ciphers.c | 355 | ||||
| -rw-r--r-- | apps/cms.c | 1307 | ||||
| -rw-r--r-- | apps/crl.c | 440 | ||||
| -rw-r--r-- | apps/crl2p7.c | 281 | ||||
| -rw-r--r-- | apps/ct_log_list.cnf | 9 | ||||
| -rw-r--r-- | apps/dgst.c | 554 | ||||
| -rw-r--r-- | apps/dh.c | 331 | ||||
| -rw-r--r-- | apps/dh1024.pem | 14 | ||||
| -rw-r--r-- | apps/dh2048.pem | 20 | ||||
| -rw-r--r-- | apps/dh4096.pem | 31 | ||||
| -rw-r--r-- | apps/dh512.pem | 9 | ||||
| -rw-r--r-- | apps/dhparam.c | 585 | ||||
| -rw-r--r-- | apps/dsa-ca.pem | 55 | ||||
| -rw-r--r-- | apps/dsa-pca.pem | 61 | ||||
| -rw-r--r-- | apps/dsa.c | 445 | ||||
| -rw-r--r-- | apps/dsaparam.c | 512 | ||||
| -rw-r--r-- | apps/ec.c | 456 | ||||
| -rw-r--r-- | apps/ecparam.c | 669 | ||||
| -rw-r--r-- | apps/enc.c | 809 | ||||
| -rw-r--r-- | apps/engine.c | 492 | ||||
| -rw-r--r-- | apps/errstr.c | 142 | ||||
| -rw-r--r-- | apps/gendh.c | 244 | ||||
| -rw-r--r-- | apps/gendsa.c | 321 | ||||
| -rw-r--r-- | apps/genpkey.c | 347 | ||||
| -rw-r--r-- | apps/genrsa.c | 422 | ||||
| -rw-r--r-- | apps/nseq.c | 180 | ||||
| -rw-r--r-- | apps/ocsp.c | 1732 | ||||
| -rw-r--r-- | apps/oid.cnf | 6 | ||||
| -rw-r--r-- | apps/openssl.c | 1166 | ||||
| -rw-r--r-- | apps/openssl.cnf | 22 | ||||
| -rw-r--r-- | apps/opt.c | 899 | ||||
| -rw-r--r-- | apps/passwd.c | 959 | ||||
| -rw-r--r-- | apps/pca-key.pem | 31 | ||||
| -rw-r--r-- | apps/pca-req.pem | 18 | ||||
| -rw-r--r-- | apps/pkcs12.c | 1117 | ||||
| -rw-r--r-- | apps/pkcs7.c | 282 | ||||
| -rw-r--r-- | apps/pkcs8.c | 528 | ||||
| -rw-r--r-- | apps/pkey.c | 383 | ||||
| -rw-r--r-- | apps/pkeyparam.c | 237 | ||||
| -rw-r--r-- | apps/pkeyutl.c | 575 | ||||
| -rw-r--r-- | apps/prime.c | 215 | ||||
| -rw-r--r-- | apps/privkey.pem | 34 | ||||
| -rw-r--r-- | apps/progs.h | 366 | ||||
| -rw-r--r-- | apps/progs.pl | 251 | ||||
| -rw-r--r-- | apps/rand.c | 264 | ||||
| -rw-r--r-- | apps/rehash.c | 512 | ||||
| -rw-r--r-- | apps/req.c | 1445 | ||||
| -rw-r--r-- | apps/rsa.c | 473 | ||||
| -rw-r--r-- | apps/rsautl.c | 380 | ||||
| -rw-r--r-- | apps/s_apps.h | 215 | ||||
| -rw-r--r-- | apps/s_cb.c | 1788 | ||||
| -rw-r--r-- | apps/s_client.c | 3656 | ||||
| -rw-r--r-- | apps/s_server.c | 3482 | ||||
| -rw-r--r-- | apps/s_socket.c | 846 | ||||
| -rw-r--r-- | apps/s_time.c | 678 | ||||
| -rw-r--r-- | apps/sess_id.c | 291 | ||||
| -rw-r--r-- | apps/set/set-g-ca.pem | 21 | ||||
| -rw-r--r-- | apps/set/set-m-ca.pem | 21 | ||||
| -rw-r--r-- | apps/set/set_b_ca.pem | 23 | ||||
| -rw-r--r-- | apps/set/set_c_ca.pem | 21 | ||||
| -rw-r--r-- | apps/set/set_d_ct.pem | 21 | ||||
| -rw-r--r-- | apps/set/set_root.pem | 21 | ||||
| -rw-r--r-- | apps/smime.c | 830 | ||||
| -rw-r--r-- | apps/speed.c | 4693 | ||||
| -rw-r--r-- | apps/spkac.c | 320 | ||||
| -rw-r--r-- | apps/srp.c | 729 | ||||
| -rw-r--r-- | apps/storeutl.c | 473 | ||||
| -rw-r--r-- | apps/testdsa.h | 135 | ||||
| -rw-r--r-- | apps/testrsa.h | 1554 | ||||
| -rw-r--r-- | apps/timeouts.h | 60 | ||||
| -rw-r--r-- | apps/ts.c | 975 | ||||
| -rw-r--r-- | apps/tsget.in (renamed from apps/tsget) | 15 | ||||
| -rw-r--r-- | apps/verify.c | 445 | ||||
| -rw-r--r-- | apps/version.c | 282 | ||||
| -rw-r--r-- | apps/x509.c | 1334 |
88 files changed, 25578 insertions, 26623 deletions
diff --git a/apps/CA.pl b/apps/CA.pl deleted file mode 100755 index 43c20b201c79..000000000000 --- a/apps/CA.pl +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/perl -# -# CA - wrapper around ca to make it easier to use ... basically ca requires -# some setup stuff to be done before you can use it and this makes -# things easier between now and when Eric is convinced to fix it :-) -# -# CA -newca ... will setup the right stuff -# CA -newreq[-nodes] ... will generate a certificate request -# CA -sign ... will sign the generated request and output -# -# At the end of that grab newreq.pem and newcert.pem (one has the key -# and the other the certificate) and cat them together and that is what -# you want/need ... I'll make even this a little cleaner later. -# -# -# 12-Jan-96 tjh Added more things ... including CA -signcert which -# converts a certificate to a request and then signs it. -# 10-Jan-96 eay Fixed a few more bugs and added the SSLEAY_CONFIG -# environment variable so this can be driven from -# a script. -# 25-Jul-96 eay Cleaned up filenames some more. -# 11-Jun-96 eay Fixed a few filename missmatches. -# 03-May-96 eay Modified to use 'ssleay cmd' instead of 'cmd'. -# 18-Apr-96 tjh Original hacking -# -# Tim Hudson -# tjh@cryptsoft.com -# - -# 27-Apr-98 snh Translation into perl, fix existing CA bug. -# -# -# Steve Henson -# shenson@bigfoot.com - -# default openssl.cnf file has setup as per the following -# demoCA ... where everything is stored - -my $openssl; -if(defined $ENV{OPENSSL}) { - $openssl = $ENV{OPENSSL}; -} else { - $openssl = "openssl"; - $ENV{OPENSSL} = $openssl; -} - -$SSLEAY_CONFIG=$ENV{"SSLEAY_CONFIG"}; -$DAYS="-days 365"; # 1 year -$CADAYS="-days 1095"; # 3 years -$REQ="$openssl req $SSLEAY_CONFIG"; -$CA="$openssl ca $SSLEAY_CONFIG"; -$VERIFY="$openssl verify"; -$X509="$openssl x509"; -$PKCS12="$openssl pkcs12"; - -$CATOP="./demoCA"; -$CAKEY="cakey.pem"; -$CAREQ="careq.pem"; -$CACERT="cacert.pem"; - -$DIRMODE = 0777; - -$RET = 0; - -foreach (@ARGV) { - if ( /^(-\?|-h|-help)$/ ) { - print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-signcert|-verify\n"; - exit 0; - } elsif (/^-newcert$/) { - # create a certificate - system ("$REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS"); - $RET=$?; - print "Certificate is in newcert.pem, private key is in newkey.pem\n" - } elsif (/^-newreq$/) { - # create a certificate request - system ("$REQ -new -keyout newkey.pem -out newreq.pem $DAYS"); - $RET=$?; - print "Request is in newreq.pem, private key is in newkey.pem\n"; - } elsif (/^-newreq-nodes$/) { - # create a certificate request - system ("$REQ -new -nodes -keyout newkey.pem -out newreq.pem $DAYS"); - $RET=$?; - print "Request is in newreq.pem, private key is in newkey.pem\n"; - } elsif (/^-newca$/) { - # if explicitly asked for or it doesn't exist then setup the - # directory structure that Eric likes to manage things - $NEW="1"; - if ( "$NEW" || ! -f "${CATOP}/serial" ) { - # create the directory hierarchy - mkdir $CATOP, $DIRMODE; - mkdir "${CATOP}/certs", $DIRMODE; - mkdir "${CATOP}/crl", $DIRMODE ; - mkdir "${CATOP}/newcerts", $DIRMODE; - mkdir "${CATOP}/private", $DIRMODE; - open OUT, ">${CATOP}/index.txt"; - close OUT; - open OUT, ">${CATOP}/crlnumber"; - print OUT "01\n"; - close OUT; - } - if ( ! -f "${CATOP}/private/$CAKEY" ) { - print "CA certificate filename (or enter to create)\n"; - $FILE = <STDIN>; - - chop $FILE; - - # ask user for existing CA certificate - if ($FILE) { - cp_pem($FILE,"${CATOP}/private/$CAKEY", "PRIVATE"); - cp_pem($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); - $RET=$?; - } else { - print "Making CA certificate ...\n"; - system ("$REQ -new -keyout " . - "${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ"); - system ("$CA -create_serial " . - "-out ${CATOP}/$CACERT $CADAYS -batch " . - "-keyfile ${CATOP}/private/$CAKEY -selfsign " . - "-extensions v3_ca " . - "-infiles ${CATOP}/$CAREQ "); - $RET=$?; - } - } - } elsif (/^-pkcs12$/) { - my $cname = $ARGV[1]; - $cname = "My Certificate" unless defined $cname; - system ("$PKCS12 -in newcert.pem -inkey newkey.pem " . - "-certfile ${CATOP}/$CACERT -out newcert.p12 " . - "-export -name \"$cname\""); - $RET=$?; - print "PKCS #12 file is in newcert.p12\n"; - exit $RET; - } elsif (/^-xsign$/) { - system ("$CA -policy policy_anything -infiles newreq.pem"); - $RET=$?; - } elsif (/^(-sign|-signreq)$/) { - system ("$CA -policy policy_anything -out newcert.pem " . - "-infiles newreq.pem"); - $RET=$?; - print "Signed certificate is in newcert.pem\n"; - } elsif (/^(-signCA)$/) { - system ("$CA -policy policy_anything -out newcert.pem " . - "-extensions v3_ca -infiles newreq.pem"); - $RET=$?; - print "Signed CA certificate is in newcert.pem\n"; - } elsif (/^-signcert$/) { - system ("$X509 -x509toreq -in newreq.pem -signkey newreq.pem " . - "-out tmp.pem"); - system ("$CA -policy policy_anything -out newcert.pem " . - "-infiles tmp.pem"); - $RET = $?; - print "Signed certificate is in newcert.pem\n"; - } elsif (/^-verify$/) { - if (shift) { - foreach $j (@ARGV) { - system ("$VERIFY -CAfile $CATOP/$CACERT $j"); - $RET=$? if ($? != 0); - } - exit $RET; - } else { - system ("$VERIFY -CAfile $CATOP/$CACERT newcert.pem"); - $RET=$?; - exit 0; - } - } else { - print STDERR "Unknown arg $_\n"; - print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n"; - exit 1; - } -} - -exit $RET; - -sub cp_pem { -my ($infile, $outfile, $bound) = @_; -open IN, $infile; -open OUT, ">$outfile"; -my $flag = 0; -while (<IN>) { - $flag = 1 if (/^-----BEGIN.*$bound/) ; - print OUT $_ if ($flag); - if (/^-----END.*$bound/) { - close IN; - close OUT; - return; - } -} -} diff --git a/apps/CA.pl.in b/apps/CA.pl.in index 3bf4c99f3102..db3cc383189e 100644 --- a/apps/CA.pl.in +++ b/apps/CA.pl.in @@ -1,188 +1,214 @@ -#!/usr/local/bin/perl -# -# CA - wrapper around ca to make it easier to use ... basically ca requires -# some setup stuff to be done before you can use it and this makes -# things easier between now and when Eric is convinced to fix it :-) -# -# CA -newca ... will setup the right stuff -# CA -newreq[-nodes] ... will generate a certificate request -# CA -sign ... will sign the generated request and output -# -# At the end of that grab newreq.pem and newcert.pem (one has the key -# and the other the certificate) and cat them together and that is what -# you want/need ... I'll make even this a little cleaner later. -# -# -# 12-Jan-96 tjh Added more things ... including CA -signcert which -# converts a certificate to a request and then signs it. -# 10-Jan-96 eay Fixed a few more bugs and added the SSLEAY_CONFIG -# environment variable so this can be driven from -# a script. -# 25-Jul-96 eay Cleaned up filenames some more. -# 11-Jun-96 eay Fixed a few filename missmatches. -# 03-May-96 eay Modified to use 'ssleay cmd' instead of 'cmd'. -# 18-Apr-96 tjh Original hacking -# -# Tim Hudson -# tjh@cryptsoft.com +#!{- $config{HASHBANGPERL} -} +# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. # +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html -# 27-Apr-98 snh Translation into perl, fix existing CA bug. # +# Wrapper around the ca to make it easier to use # -# Steve Henson -# shenson@bigfoot.com +# {- join("\n# ", @autowarntext) -} -# default openssl.cnf file has setup as per the following -# demoCA ... where everything is stored +use strict; +use warnings; -my $openssl; -if(defined $ENV{OPENSSL}) { - $openssl = $ENV{OPENSSL}; +my $openssl = "openssl"; +if(defined $ENV{'OPENSSL'}) { + $openssl = $ENV{'OPENSSL'}; } else { - $openssl = "openssl"; - $ENV{OPENSSL} = $openssl; + $ENV{'OPENSSL'} = $openssl; } -$SSLEAY_CONFIG=$ENV{"SSLEAY_CONFIG"}; -$DAYS="-days 365"; # 1 year -$CADAYS="-days 1095"; # 3 years -$REQ="$openssl req $SSLEAY_CONFIG"; -$CA="$openssl ca $SSLEAY_CONFIG"; -$VERIFY="$openssl verify"; -$X509="$openssl x509"; -$PKCS12="$openssl pkcs12"; - -$CATOP="./demoCA"; -$CAKEY="cakey.pem"; -$CAREQ="careq.pem"; -$CACERT="cacert.pem"; - -$DIRMODE = 0777; +my $verbose = 1; -$RET = 0; +my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} || ""; +my $DAYS = "-days 365"; +my $CADAYS = "-days 1095"; # 3 years +my $REQ = "$openssl req $OPENSSL_CONFIG"; +my $CA = "$openssl ca $OPENSSL_CONFIG"; +my $VERIFY = "$openssl verify"; +my $X509 = "$openssl x509"; +my $PKCS12 = "$openssl pkcs12"; -foreach (@ARGV) { - if ( /^(-\?|-h|-help)$/ ) { - print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-signcert|-verify\n"; - exit 0; - } elsif (/^-newcert$/) { - # create a certificate - system ("$REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS"); - $RET=$?; - print "Certificate is in newcert.pem, private key is in newkey.pem\n" - } elsif (/^-newreq$/) { - # create a certificate request - system ("$REQ -new -keyout newkey.pem -out newreq.pem $DAYS"); - $RET=$?; - print "Request is in newreq.pem, private key is in newkey.pem\n"; - } elsif (/^-newreq-nodes$/) { - # create a certificate request - system ("$REQ -new -nodes -keyout newkey.pem -out newreq.pem $DAYS"); - $RET=$?; - print "Request is in newreq.pem, private key is in newkey.pem\n"; - } elsif (/^-newca$/) { - # if explicitly asked for or it doesn't exist then setup the - # directory structure that Eric likes to manage things - $NEW="1"; - if ( "$NEW" || ! -f "${CATOP}/serial" ) { - # create the directory hierarchy - mkdir $CATOP, $DIRMODE; - mkdir "${CATOP}/certs", $DIRMODE; - mkdir "${CATOP}/crl", $DIRMODE ; - mkdir "${CATOP}/newcerts", $DIRMODE; - mkdir "${CATOP}/private", $DIRMODE; - open OUT, ">${CATOP}/index.txt"; - close OUT; - open OUT, ">${CATOP}/crlnumber"; - print OUT "01\n"; - close OUT; - } - if ( ! -f "${CATOP}/private/$CAKEY" ) { - print "CA certificate filename (or enter to create)\n"; - $FILE = <STDIN>; +# default openssl.cnf file has setup as per the following +my $CATOP = "./demoCA"; +my $CAKEY = "cakey.pem"; +my $CAREQ = "careq.pem"; +my $CACERT = "cacert.pem"; +my $CACRL = "crl.pem"; +my $DIRMODE = 0777; - chop $FILE; +my $NEWKEY = "newkey.pem"; +my $NEWREQ = "newreq.pem"; +my $NEWCERT = "newcert.pem"; +my $NEWP12 = "newcert.p12"; +my $RET = 0; +my $WHAT = shift @ARGV || ""; +my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); +my %EXTRA = extra_args(\@ARGV, "-extra-"); +my $FILE; - # ask user for existing CA certificate - if ($FILE) { - cp_pem($FILE,"${CATOP}/private/$CAKEY", "PRIVATE"); - cp_pem($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); - $RET=$?; - } else { - print "Making CA certificate ...\n"; - system ("$REQ -new -keyout " . - "${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ"); - system ("$CA -create_serial " . - "-out ${CATOP}/$CACERT $CADAYS -batch " . - "-keyfile ${CATOP}/private/$CAKEY -selfsign " . - "-extensions v3_ca " . - "-infiles ${CATOP}/$CAREQ "); - $RET=$?; - } - } - } elsif (/^-pkcs12$/) { - my $cname = $ARGV[1]; - $cname = "My Certificate" unless defined $cname; - system ("$PKCS12 -in newcert.pem -inkey newkey.pem " . - "-certfile ${CATOP}/$CACERT -out newcert.p12 " . - "-export -name \"$cname\""); - $RET=$?; - print "PKCS #12 file is in newcert.p12\n"; - exit $RET; - } elsif (/^-xsign$/) { - system ("$CA -policy policy_anything -infiles newreq.pem"); - $RET=$?; - } elsif (/^(-sign|-signreq)$/) { - system ("$CA -policy policy_anything -out newcert.pem " . - "-infiles newreq.pem"); - $RET=$?; - print "Signed certificate is in newcert.pem\n"; - } elsif (/^(-signCA)$/) { - system ("$CA -policy policy_anything -out newcert.pem " . - "-extensions v3_ca -infiles newreq.pem"); - $RET=$?; - print "Signed CA certificate is in newcert.pem\n"; - } elsif (/^-signcert$/) { - system ("$X509 -x509toreq -in newreq.pem -signkey newreq.pem " . - "-out tmp.pem"); - system ("$CA -policy policy_anything -out newcert.pem " . - "-infiles tmp.pem"); - $RET = $?; - print "Signed certificate is in newcert.pem\n"; - } elsif (/^-verify$/) { - if (shift) { - foreach $j (@ARGV) { - system ("$VERIFY -CAfile $CATOP/$CACERT $j"); - $RET=$? if ($? != 0); - } - exit $RET; - } else { - system ("$VERIFY -CAfile $CATOP/$CACERT newcert.pem"); - $RET=$?; - exit 0; - } +sub extra_args { + my ($args_ref, $arg_prefix) = @_; + my %eargs = map { + if ($_ < $#$args_ref) { + my ($arg, $value) = splice(@$args_ref, $_, 2); + $arg =~ s/$arg_prefix//; + ($arg, $value); } else { - print STDERR "Unknown arg $_\n"; - print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n"; - exit 1; + (); } + } reverse grep($$args_ref[$_] =~ /$arg_prefix/, 0..$#$args_ref); + my %empty = map { ($_, "") } @OPENSSL_CMDS; + return (%empty, %eargs); } -exit $RET; +# See if reason for a CRL entry is valid; exit if not. +sub crl_reason_ok +{ + my $r = shift; -sub cp_pem { -my ($infile, $outfile, $bound) = @_; -open IN, $infile; -open OUT, ">$outfile"; -my $flag = 0; -while (<IN>) { - $flag = 1 if (/^-----BEGIN.*$bound/) ; - print OUT $_ if ($flag); - if (/^-----END.*$bound/) { - close IN; - close OUT; - return; - } + if ($r eq 'unspecified' || $r eq 'keyCompromise' + || $r eq 'CACompromise' || $r eq 'affiliationChanged' + || $r eq 'superseded' || $r eq 'cessationOfOperation' + || $r eq 'certificateHold' || $r eq 'removeFromCRL') { + return 1; + } + print STDERR "Invalid CRL reason; must be one of:\n"; + print STDERR " unspecified, keyCompromise, CACompromise,\n"; + print STDERR " affiliationChanged, superseded, cessationOfOperation\n"; + print STDERR " certificateHold, removeFromCRL"; + exit 1; } + +# Copy a PEM-format file; return like exit status (zero means ok) +sub copy_pemfile +{ + my ($infile, $outfile, $bound) = @_; + my $found = 0; + + open IN, $infile || die "Cannot open $infile, $!"; + open OUT, ">$outfile" || die "Cannot write to $outfile, $!"; + while (<IN>) { + $found = 1 if /^-----BEGIN.*$bound/; + print OUT $_ if $found; + $found = 2, last if /^-----END.*$bound/; + } + close IN; + close OUT; + return $found == 2 ? 0 : 1; +} + +# Wrapper around system; useful for debugging. Returns just the exit status +sub run +{ + my $cmd = shift; + print "====\n$cmd\n" if $verbose; + my $status = system($cmd); + print "==> $status\n====\n" if $verbose; + return $status >> 8; } + + +if ( $WHAT =~ /^(-\?|-h|-help)$/ ) { + print STDERR "usage: CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd extra-params]\n"; + print STDERR " CA.pl -pkcs12 [-extra-pkcs12 extra-params] [certname]\n"; + print STDERR " CA.pl -verify [-extra-verify extra-params] certfile ...\n"; + print STDERR " CA.pl -revoke [-extra-ca extra-params] certfile [reason]\n"; + exit 0; +} +if ($WHAT eq '-newcert' ) { + # create a certificate + $RET = run("$REQ -new -x509 -keyout $NEWKEY -out $NEWCERT $DAYS $EXTRA{req}"); + print "Cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0; +} elsif ($WHAT eq '-precert' ) { + # create a pre-certificate + $RET = run("$REQ -x509 -precert -keyout $NEWKEY -out $NEWCERT $DAYS"); + print "Pre-cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0; +} elsif ($WHAT =~ /^\-newreq(\-nodes)?$/ ) { + # create a certificate request + $RET = run("$REQ -new $1 -keyout $NEWKEY -out $NEWREQ $DAYS $EXTRA{req}"); + print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0; +} elsif ($WHAT eq '-newca' ) { + # create the directory hierarchy + mkdir ${CATOP}, $DIRMODE; + mkdir "${CATOP}/certs", $DIRMODE; + mkdir "${CATOP}/crl", $DIRMODE ; + mkdir "${CATOP}/newcerts", $DIRMODE; + mkdir "${CATOP}/private", $DIRMODE; + open OUT, ">${CATOP}/index.txt"; + close OUT; + open OUT, ">${CATOP}/crlnumber"; + print OUT "01\n"; + close OUT; + # ask user for existing CA certificate + print "CA certificate filename (or enter to create)\n"; + $FILE = "" unless defined($FILE = <STDIN>); + $FILE =~ s{\R$}{}; + if ($FILE ne "") { + copy_pemfile($FILE,"${CATOP}/private/$CAKEY", "PRIVATE"); + copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); + } else { + print "Making CA certificate ...\n"; + $RET = run("$REQ -new -keyout" + . " ${CATOP}/private/$CAKEY" + . " -out ${CATOP}/$CAREQ $EXTRA{req}"); + $RET = run("$CA -create_serial" + . " -out ${CATOP}/$CACERT $CADAYS -batch" + . " -keyfile ${CATOP}/private/$CAKEY -selfsign" + . " -extensions v3_ca $EXTRA{ca}" + . " -infiles ${CATOP}/$CAREQ") if $RET == 0; + print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; + } +} elsif ($WHAT eq '-pkcs12' ) { + my $cname = $ARGV[0]; + $cname = "My Certificate" unless defined $cname; + $RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY" + . " -certfile ${CATOP}/$CACERT" + . " -out $NEWP12" + . " -export -name \"$cname\" $EXTRA{pkcs12}"); + print "PKCS #12 file is in $NEWP12\n" if $RET == 0; +} elsif ($WHAT eq '-xsign' ) { + $RET = run("$CA -policy policy_anything $EXTRA{ca} -infiles $NEWREQ"); +} elsif ($WHAT eq '-sign' ) { + $RET = run("$CA -policy policy_anything -out $NEWCERT $EXTRA{ca} -infiles $NEWREQ"); + print "Signed certificate is in $NEWCERT\n" if $RET == 0; +} elsif ($WHAT eq '-signCA' ) { + $RET = run("$CA -policy policy_anything -out $NEWCERT" + . " -extensions v3_ca $EXTRA{ca} -infiles $NEWREQ"); + print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; +} elsif ($WHAT eq '-signcert' ) { + $RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ" + . " -out tmp.pem $EXTRA{x509}"); + $RET = run("$CA -policy policy_anything -out $NEWCERT" + . "$EXTRA{ca} -infiles tmp.pem") if $RET == 0; + print "Signed certificate is in $NEWCERT\n" if $RET == 0; +} elsif ($WHAT eq '-verify' ) { + my @files = @ARGV ? @ARGV : ( $NEWCERT ); + my $file; + foreach $file (@files) { + my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file $EXTRA{verify}"); + $RET = $status if $status != 0; + } +} elsif ($WHAT eq '-crl' ) { + $RET = run("$CA -gencrl -out ${CATOP}/crl/$CACRL $EXTRA{ca}"); + print "Generated CRL is in ${CATOP}/crl/$CACRL\n" if $RET == 0; +} elsif ($WHAT eq '-revoke' ) { + my $cname = $ARGV[0]; + if (!defined $cname) { + print "Certificate filename is required; reason optional.\n"; + exit 1; + } + my $reason = $ARGV[1]; + $reason = " -crl_reason $reason" + if defined $reason && crl_reason_ok($reason); + $RET = run("$CA -revoke \"$cname\"" . $reason . $EXTRA{ca}); +} else { + print STDERR "Unknown arg \"$WHAT\"\n"; + print STDERR "Use -help for help.\n"; + exit 1; +} + +exit $RET; diff --git a/apps/CA.sh b/apps/CA.sh deleted file mode 100644 index 7ad6b8c52e74..000000000000 --- a/apps/CA.sh +++ /dev/null @@ -1,198 +0,0 @@ -#!/bin/sh -# -# CA - wrapper around ca to make it easier to use ... basically ca requires -# some setup stuff to be done before you can use it and this makes -# things easier between now and when Eric is convinced to fix it :-) -# -# CA -newca ... will setup the right stuff -# CA -newreq ... will generate a certificate request -# CA -sign ... will sign the generated request and output -# -# At the end of that grab newreq.pem and newcert.pem (one has the key -# and the other the certificate) and cat them together and that is what -# you want/need ... I'll make even this a little cleaner later. -# -# -# 12-Jan-96 tjh Added more things ... including CA -signcert which -# converts a certificate to a request and then signs it. -# 10-Jan-96 eay Fixed a few more bugs and added the SSLEAY_CONFIG -# environment variable so this can be driven from -# a script. -# 25-Jul-96 eay Cleaned up filenames some more. -# 11-Jun-96 eay Fixed a few filename missmatches. -# 03-May-96 eay Modified to use 'ssleay cmd' instead of 'cmd'. -# 18-Apr-96 tjh Original hacking -# -# Tim Hudson -# tjh@cryptsoft.com -# - -# default openssl.cnf file has setup as per the following -# demoCA ... where everything is stored -cp_pem() { - infile=$1 - outfile=$2 - bound=$3 - flag=0 - exec <$infile; - while read line; do - if [ $flag -eq 1 ]; then - echo $line|grep "^-----END.*$bound" 2>/dev/null 1>/dev/null - if [ $? -eq 0 ] ; then - echo $line >>$outfile - break - else - echo $line >>$outfile - fi - fi - - echo $line|grep "^-----BEGIN.*$bound" 2>/dev/null 1>/dev/null - if [ $? -eq 0 ]; then - echo $line >$outfile - flag=1 - fi - done -} - -usage() { - echo "usage: $0 -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify" >&2 -} - -if [ -z "$OPENSSL" ]; then OPENSSL=openssl; fi - -if [ -z "$DAYS" ] ; then DAYS="-days 365" ; fi # 1 year -CADAYS="-days 1095" # 3 years -REQ="$OPENSSL req $SSLEAY_CONFIG" -CA="$OPENSSL ca $SSLEAY_CONFIG" -VERIFY="$OPENSSL verify" -X509="$OPENSSL x509" -PKCS12="openssl pkcs12" - -if [ -z "$CATOP" ] ; then CATOP=./demoCA ; fi -CAKEY=./cakey.pem -CAREQ=./careq.pem -CACERT=./cacert.pem - -RET=0 - -while [ "$1" != "" ] ; do -case $1 in --\?|-h|-help) - usage - exit 0 - ;; --newcert) - # create a certificate - $REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS - RET=$? - echo "Certificate is in newcert.pem, private key is in newkey.pem" - ;; --newreq) - # create a certificate request - $REQ -new -keyout newkey.pem -out newreq.pem $DAYS - RET=$? - echo "Request is in newreq.pem, private key is in newkey.pem" - ;; --newreq-nodes) - # create a certificate request - $REQ -new -nodes -keyout newreq.pem -out newreq.pem $DAYS - RET=$? - echo "Request (and private key) is in newreq.pem" - ;; --newca) - # if explicitly asked for or it doesn't exist then setup the directory - # structure that Eric likes to manage things - NEW="1" - if [ "$NEW" -o ! -f ${CATOP}/serial ]; then - # create the directory hierarchy - mkdir -p ${CATOP} - mkdir -p ${CATOP}/certs - mkdir -p ${CATOP}/crl - mkdir -p ${CATOP}/newcerts - mkdir -p ${CATOP}/private - touch ${CATOP}/index.txt - fi - if [ ! -f ${CATOP}/private/$CAKEY ]; then - echo "CA certificate filename (or enter to create)" - read FILE - - # ask user for existing CA certificate - if [ "$FILE" ]; then - cp_pem $FILE ${CATOP}/private/$CAKEY PRIVATE - cp_pem $FILE ${CATOP}/$CACERT CERTIFICATE - RET=$? - if [ ! -f "${CATOP}/serial" ]; then - $X509 -in ${CATOP}/$CACERT -noout -next_serial \ - -out ${CATOP}/serial - fi - else - echo "Making CA certificate ..." - $REQ -new -keyout ${CATOP}/private/$CAKEY \ - -out ${CATOP}/$CAREQ - $CA -create_serial -out ${CATOP}/$CACERT $CADAYS -batch \ - -keyfile ${CATOP}/private/$CAKEY -selfsign \ - -extensions v3_ca \ - -infiles ${CATOP}/$CAREQ - RET=$? - fi - fi - ;; --xsign) - $CA -policy policy_anything -infiles newreq.pem - RET=$? - ;; --pkcs12) - if [ -z "$2" ] ; then - CNAME="My Certificate" - else - CNAME="$2" - fi - $PKCS12 -in newcert.pem -inkey newreq.pem -certfile ${CATOP}/$CACERT \ - -out newcert.p12 -export -name "$CNAME" - RET=$? - exit $RET - ;; --sign|-signreq) - $CA -policy policy_anything -out newcert.pem -infiles newreq.pem - RET=$? - cat newcert.pem - echo "Signed certificate is in newcert.pem" - ;; --signCA) - $CA -policy policy_anything -out newcert.pem -extensions v3_ca -infiles newreq.pem - RET=$? - echo "Signed CA certificate is in newcert.pem" - ;; --signcert) - echo "Cert passphrase will be requested twice - bug?" - $X509 -x509toreq -in newreq.pem -signkey newreq.pem -out tmp.pem - $CA -policy policy_anything -out newcert.pem -infiles tmp.pem - RET=$? - cat newcert.pem - echo "Signed certificate is in newcert.pem" - ;; --verify) - shift - if [ -z "$1" ]; then - $VERIFY -CAfile $CATOP/$CACERT newcert.pem - RET=$? - else - for j - do - $VERIFY -CAfile $CATOP/$CACERT $j - if [ $? != 0 ]; then - RET=$? - fi - done - fi - exit $RET - ;; -*) - echo "Unknown arg $i" >&2 - usage - exit 1 - ;; -esac -shift -done -exit $RET diff --git a/apps/Makefile b/apps/Makefile deleted file mode 100644 index 8c3297ea6724..000000000000 --- a/apps/Makefile +++ /dev/null @@ -1,1059 +0,0 @@ -# -# apps/Makefile -# - -DIR= apps -TOP= .. -CC= cc -INCLUDES= -I$(TOP) -I../include $(KRB5_INCLUDES) -CFLAG= -g -static -MAKEFILE= Makefile -PERL= perl -RM= rm -f -# KRB5 stuff -KRB5_INCLUDES= -LIBKRB5= - -PEX_LIBS= -EX_LIBS= -EXE_EXT= - -SHLIB_TARGET= - -CFLAGS= -DMONOLITH $(INCLUDES) $(CFLAG) - -GENERAL=Makefile makeapps.com install.com - -DLIBCRYPTO=../libcrypto.a -DLIBSSL=../libssl.a -LIBCRYPTO=-L.. -lcrypto -LIBSSL=-L.. -lssl - -PROGRAM= openssl - -SCRIPTS=CA.sh CA.pl tsget - -EXE= $(PROGRAM)$(EXE_EXT) - -E_EXE= verify asn1pars req dgst dh dhparam enc passwd gendh errstr \ - ca crl rsa rsautl dsa dsaparam ec ecparam \ - x509 genrsa gendsa genpkey s_server s_client speed \ - s_time version pkcs7 cms crl2pkcs7 sess_id ciphers nseq pkcs12 \ - pkcs8 pkey pkeyparam pkeyutl spkac smime rand engine ocsp prime ts srp - -PROGS= $(PROGRAM).c - -A_OBJ=apps.o -A_SRC=apps.c -S_OBJ= s_cb.o s_socket.o -S_SRC= s_cb.c s_socket.c -RAND_OBJ=app_rand.o -RAND_SRC=app_rand.c - -E_OBJ= verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o errstr.o \ - ca.o pkcs7.o crl2p7.o crl.o \ - rsa.o rsautl.o dsa.o dsaparam.o ec.o ecparam.o \ - x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o \ - s_time.o $(A_OBJ) $(S_OBJ) $(RAND_OBJ) version.o sess_id.o \ - ciphers.o nseq.o pkcs12.o pkcs8.o pkey.o pkeyparam.o pkeyutl.o \ - spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o - -E_SRC= verify.c asn1pars.c req.c dgst.c dh.c enc.c passwd.c gendh.c errstr.c ca.c \ - pkcs7.c crl2p7.c crl.c \ - rsa.c rsautl.c dsa.c dsaparam.c ec.c ecparam.c \ - x509.c genrsa.c gendsa.c genpkey.c s_server.c s_client.c speed.c \ - s_time.c $(A_SRC) $(S_SRC) $(RAND_SRC) version.c sess_id.c \ - ciphers.c nseq.c pkcs12.c pkcs8.c pkey.c pkeyparam.c pkeyutl.c \ - spkac.c smime.c cms.c rand.c engine.c ocsp.c prime.c ts.c srp.c - -SRC=$(E_SRC) - -EXHEADER= -HEADER= apps.h progs.h s_apps.h \ - testdsa.h testrsa.h \ - $(EXHEADER) - -ALL= $(GENERAL) $(SRC) $(HEADER) - -top: - @(cd ..; $(MAKE) DIRS=$(DIR) all) - -all: exe - -exe: $(EXE) - -req: sreq.o $(A_OBJ) $(DLIBCRYPTO) - shlib_target=; if [ -n "$(SHARED_LIBS)" ]; then \ - shlib_target="$(SHLIB_TARGET)"; \ - fi; \ - $(MAKE) -f $(TOP)/Makefile.shared -e \ - APPNAME=req OBJECTS="sreq.o $(A_OBJ) $(RAND_OBJ)" \ - LIBDEPS="$(PEX_LIBS) $(LIBCRYPTO) $(EX_LIBS)" \ - link_app.$${shlib_target} - -sreq.o: req.c - $(CC) -c $(INCLUDES) $(CFLAG) -o sreq.o req.c - -openssl-vms.cnf: openssl.cnf - $(PERL) $(TOP)/VMS/VMSify-conf.pl < openssl.cnf > openssl-vms.cnf - -files: - $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO - -install: - @[ -n "$(INSTALLTOP)" ] # should be set by top Makefile... - @set -e; for i in $(EXE); \ - do \ - (echo installing $$i; \ - cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new; \ - chmod 755 $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i ); \ - done; - @set -e; for i in $(SCRIPTS); \ - do \ - (echo installing $$i; \ - cp $$i $(INSTALL_PREFIX)$(OPENSSLDIR)/misc/$$i.new; \ - chmod 755 $(INSTALL_PREFIX)$(OPENSSLDIR)/misc/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(OPENSSLDIR)/misc/$$i.new $(INSTALL_PREFIX)$(OPENSSLDIR)/misc/$$i ); \ - done - @cp openssl.cnf $(INSTALL_PREFIX)$(OPENSSLDIR)/openssl.cnf.new; \ - chmod 644 $(INSTALL_PREFIX)$(OPENSSLDIR)/openssl.cnf.new; \ - mv -f $(INSTALL_PREFIX)$(OPENSSLDIR)/openssl.cnf.new $(INSTALL_PREFIX)$(OPENSSLDIR)/openssl.cnf - -tags: - ctags $(SRC) - -tests: - -links: - -lint: - lint -DLINT $(INCLUDES) $(SRC)>fluff - -update: openssl-vms.cnf local_depend - -depend: local_depend - @if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi -local_depend: - @[ -z "$(THIS)" ] || $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(SRC) - -dclean: - $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new - mv -f Makefile.new $(MAKEFILE) - rm -f CA.pl - -clean: - rm -f *.o *.obj *.dll lib tags core .pure .nfs* *.old *.bak fluff $(EXE) - rm -f req - -$(DLIBSSL): - (cd ..; $(MAKE) build_libssl) - -$(DLIBCRYPTO): - (cd ..; $(MAKE) build_libcrypto) - -$(EXE): progs.h $(E_OBJ) $(PROGRAM).o $(DLIBCRYPTO) $(DLIBSSL) - $(RM) $(EXE) - shlib_target=; if [ -n "$(SHARED_LIBS)" ]; then \ - shlib_target="$(SHLIB_TARGET)"; \ - elif [ -n "$(FIPSCANLIB)" ]; then \ - FIPSLD_CC="$(CC)"; CC=$(FIPSDIR)/bin/fipsld; export CC FIPSLD_CC; \ - fi; \ - LIBRARIES="$(LIBSSL) $(LIBKRB5) $(LIBCRYPTO)" ; \ - $(MAKE) -f $(TOP)/Makefile.shared -e \ - APPNAME=$(EXE) OBJECTS="$(PROGRAM).o $(E_OBJ)" \ - LIBDEPS="$(PEX_LIBS) $$LIBRARIES $(EX_LIBS)" \ - link_app.$${shlib_target} - @(cd ..; $(MAKE) rehash) - -progs.h: progs.pl - $(PERL) progs.pl $(E_EXE) >progs.h - $(RM) $(PROGRAM).o - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -app_rand.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -app_rand.o: ../include/openssl/buffer.h ../include/openssl/conf.h -app_rand.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -app_rand.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -app_rand.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -app_rand.o: ../include/openssl/evp.h ../include/openssl/lhash.h -app_rand.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -app_rand.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -app_rand.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -app_rand.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -app_rand.o: ../include/openssl/safestack.h ../include/openssl/sha.h -app_rand.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -app_rand.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -app_rand.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h -app_rand.o: app_rand.c apps.h -apps.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -apps.o: ../include/openssl/bn.h ../include/openssl/buffer.h -apps.o: ../include/openssl/conf.h ../include/openssl/crypto.h -apps.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -apps.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -apps.o: ../include/openssl/engine.h ../include/openssl/err.h -apps.o: ../include/openssl/evp.h ../include/openssl/lhash.h -apps.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -apps.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -apps.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -apps.o: ../include/openssl/pem.h ../include/openssl/pem2.h -apps.o: ../include/openssl/pkcs12.h ../include/openssl/pkcs7.h -apps.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -apps.o: ../include/openssl/sha.h ../include/openssl/stack.h -apps.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -apps.o: ../include/openssl/ui.h ../include/openssl/x509.h -apps.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.c apps.h -asn1pars.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -asn1pars.o: ../include/openssl/buffer.h ../include/openssl/conf.h -asn1pars.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -asn1pars.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -asn1pars.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -asn1pars.o: ../include/openssl/err.h ../include/openssl/evp.h -asn1pars.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -asn1pars.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -asn1pars.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -asn1pars.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -asn1pars.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -asn1pars.o: ../include/openssl/safestack.h ../include/openssl/sha.h -asn1pars.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -asn1pars.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -asn1pars.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -asn1pars.o: asn1pars.c -ca.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ca.o: ../include/openssl/bn.h ../include/openssl/buffer.h -ca.o: ../include/openssl/conf.h ../include/openssl/crypto.h -ca.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -ca.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -ca.o: ../include/openssl/engine.h ../include/openssl/err.h -ca.o: ../include/openssl/evp.h ../include/openssl/lhash.h -ca.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -ca.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -ca.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -ca.o: ../include/openssl/pem.h ../include/openssl/pem2.h -ca.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h -ca.o: ../include/openssl/sha.h ../include/openssl/stack.h -ca.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -ca.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -ca.o: ../include/openssl/x509v3.h apps.h ca.c -ciphers.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ciphers.o: ../include/openssl/buffer.h ../include/openssl/comp.h -ciphers.o: ../include/openssl/conf.h ../include/openssl/crypto.h -ciphers.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -ciphers.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -ciphers.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -ciphers.o: ../include/openssl/err.h ../include/openssl/evp.h -ciphers.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -ciphers.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -ciphers.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -ciphers.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -ciphers.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -ciphers.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -ciphers.o: ../include/openssl/pqueue.h ../include/openssl/safestack.h -ciphers.o: ../include/openssl/sha.h ../include/openssl/srtp.h -ciphers.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -ciphers.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -ciphers.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -ciphers.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -ciphers.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -ciphers.o: ../include/openssl/x509v3.h apps.h ciphers.c -cms.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -cms.o: ../include/openssl/buffer.h ../include/openssl/cms.h -cms.o: ../include/openssl/conf.h ../include/openssl/crypto.h -cms.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -cms.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -cms.o: ../include/openssl/engine.h ../include/openssl/err.h -cms.o: ../include/openssl/evp.h ../include/openssl/lhash.h -cms.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -cms.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -cms.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -cms.o: ../include/openssl/pem.h ../include/openssl/pem2.h -cms.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h -cms.o: ../include/openssl/sha.h ../include/openssl/stack.h -cms.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -cms.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -cms.o: ../include/openssl/x509v3.h apps.h cms.c -crl.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -crl.o: ../include/openssl/buffer.h ../include/openssl/conf.h -crl.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -crl.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -crl.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -crl.o: ../include/openssl/err.h ../include/openssl/evp.h -crl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -crl.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -crl.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -crl.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -crl.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -crl.o: ../include/openssl/safestack.h ../include/openssl/sha.h -crl.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -crl.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -crl.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h crl.c -crl2p7.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -crl2p7.o: ../include/openssl/buffer.h ../include/openssl/conf.h -crl2p7.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -crl2p7.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -crl2p7.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -crl2p7.o: ../include/openssl/err.h ../include/openssl/evp.h -crl2p7.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -crl2p7.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -crl2p7.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -crl2p7.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -crl2p7.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -crl2p7.o: ../include/openssl/safestack.h ../include/openssl/sha.h -crl2p7.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -crl2p7.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -crl2p7.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -crl2p7.o: crl2p7.c -dgst.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -dgst.o: ../include/openssl/buffer.h ../include/openssl/conf.h -dgst.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -dgst.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -dgst.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -dgst.o: ../include/openssl/err.h ../include/openssl/evp.h -dgst.o: ../include/openssl/hmac.h ../include/openssl/lhash.h -dgst.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -dgst.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -dgst.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -dgst.o: ../include/openssl/pem.h ../include/openssl/pem2.h -dgst.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h -dgst.o: ../include/openssl/sha.h ../include/openssl/stack.h -dgst.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -dgst.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -dgst.o: ../include/openssl/x509v3.h apps.h dgst.c -dh.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -dh.o: ../include/openssl/bn.h ../include/openssl/buffer.h -dh.o: ../include/openssl/conf.h ../include/openssl/crypto.h -dh.o: ../include/openssl/dh.h ../include/openssl/e_os2.h -dh.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -dh.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -dh.o: ../include/openssl/err.h ../include/openssl/evp.h -dh.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -dh.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -dh.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -dh.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -dh.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -dh.o: ../include/openssl/safestack.h ../include/openssl/sha.h -dh.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -dh.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -dh.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h dh.c -dsa.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -dsa.o: ../include/openssl/bn.h ../include/openssl/buffer.h -dsa.o: ../include/openssl/conf.h ../include/openssl/crypto.h -dsa.o: ../include/openssl/dsa.h ../include/openssl/e_os2.h -dsa.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -dsa.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -dsa.o: ../include/openssl/err.h ../include/openssl/evp.h -dsa.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -dsa.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -dsa.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -dsa.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -dsa.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -dsa.o: ../include/openssl/safestack.h ../include/openssl/sha.h -dsa.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -dsa.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -dsa.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h dsa.c -dsaparam.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -dsaparam.o: ../include/openssl/bn.h ../include/openssl/buffer.h -dsaparam.o: ../include/openssl/conf.h ../include/openssl/crypto.h -dsaparam.o: ../include/openssl/dh.h ../include/openssl/dsa.h -dsaparam.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -dsaparam.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -dsaparam.o: ../include/openssl/engine.h ../include/openssl/err.h -dsaparam.o: ../include/openssl/evp.h ../include/openssl/lhash.h -dsaparam.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -dsaparam.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -dsaparam.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -dsaparam.o: ../include/openssl/pem.h ../include/openssl/pem2.h -dsaparam.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -dsaparam.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -dsaparam.o: ../include/openssl/sha.h ../include/openssl/stack.h -dsaparam.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -dsaparam.o: ../include/openssl/ui.h ../include/openssl/x509.h -dsaparam.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -dsaparam.o: dsaparam.c -ec.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ec.o: ../include/openssl/buffer.h ../include/openssl/conf.h -ec.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -ec.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -ec.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -ec.o: ../include/openssl/err.h ../include/openssl/evp.h -ec.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -ec.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -ec.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -ec.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -ec.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -ec.o: ../include/openssl/safestack.h ../include/openssl/sha.h -ec.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -ec.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -ec.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h ec.c -ecparam.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ecparam.o: ../include/openssl/bn.h ../include/openssl/buffer.h -ecparam.o: ../include/openssl/conf.h ../include/openssl/crypto.h -ecparam.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -ecparam.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -ecparam.o: ../include/openssl/engine.h ../include/openssl/err.h -ecparam.o: ../include/openssl/evp.h ../include/openssl/lhash.h -ecparam.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -ecparam.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -ecparam.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -ecparam.o: ../include/openssl/pem.h ../include/openssl/pem2.h -ecparam.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h -ecparam.o: ../include/openssl/sha.h ../include/openssl/stack.h -ecparam.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -ecparam.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -ecparam.o: ../include/openssl/x509v3.h apps.h ecparam.c -enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h -enc.o: ../include/openssl/conf.h ../include/openssl/crypto.h -enc.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -enc.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -enc.o: ../include/openssl/engine.h ../include/openssl/err.h -enc.o: ../include/openssl/evp.h ../include/openssl/lhash.h -enc.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -enc.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h -enc.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -enc.o: ../include/openssl/safestack.h ../include/openssl/sha.h -enc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -enc.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -enc.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h enc.c -engine.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -engine.o: ../include/openssl/buffer.h ../include/openssl/comp.h -engine.o: ../include/openssl/conf.h ../include/openssl/crypto.h -engine.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -engine.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -engine.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -engine.o: ../include/openssl/err.h ../include/openssl/evp.h -engine.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -engine.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -engine.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -engine.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -engine.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -engine.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -engine.o: ../include/openssl/pqueue.h ../include/openssl/safestack.h -engine.o: ../include/openssl/sha.h ../include/openssl/srtp.h -engine.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -engine.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -engine.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -engine.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -engine.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -engine.o: ../include/openssl/x509v3.h apps.h engine.c -errstr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -errstr.o: ../include/openssl/buffer.h ../include/openssl/comp.h -errstr.o: ../include/openssl/conf.h ../include/openssl/crypto.h -errstr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -errstr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -errstr.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -errstr.o: ../include/openssl/err.h ../include/openssl/evp.h -errstr.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -errstr.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -errstr.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -errstr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -errstr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -errstr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -errstr.o: ../include/openssl/pqueue.h ../include/openssl/safestack.h -errstr.o: ../include/openssl/sha.h ../include/openssl/srtp.h -errstr.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -errstr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -errstr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -errstr.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -errstr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -errstr.o: ../include/openssl/x509v3.h apps.h errstr.c -gendh.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -gendh.o: ../include/openssl/bn.h ../include/openssl/buffer.h -gendh.o: ../include/openssl/conf.h ../include/openssl/crypto.h -gendh.o: ../include/openssl/dh.h ../include/openssl/dsa.h -gendh.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -gendh.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -gendh.o: ../include/openssl/engine.h ../include/openssl/err.h -gendh.o: ../include/openssl/evp.h ../include/openssl/lhash.h -gendh.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -gendh.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -gendh.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -gendh.o: ../include/openssl/pem.h ../include/openssl/pem2.h -gendh.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -gendh.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -gendh.o: ../include/openssl/sha.h ../include/openssl/stack.h -gendh.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -gendh.o: ../include/openssl/ui.h ../include/openssl/x509.h -gendh.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -gendh.o: gendh.c -gendsa.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -gendsa.o: ../include/openssl/bn.h ../include/openssl/buffer.h -gendsa.o: ../include/openssl/conf.h ../include/openssl/crypto.h -gendsa.o: ../include/openssl/dsa.h ../include/openssl/e_os2.h -gendsa.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -gendsa.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -gendsa.o: ../include/openssl/err.h ../include/openssl/evp.h -gendsa.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -gendsa.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -gendsa.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -gendsa.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -gendsa.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -gendsa.o: ../include/openssl/safestack.h ../include/openssl/sha.h -gendsa.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -gendsa.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -gendsa.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -gendsa.o: gendsa.c -genpkey.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -genpkey.o: ../include/openssl/buffer.h ../include/openssl/conf.h -genpkey.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -genpkey.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -genpkey.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -genpkey.o: ../include/openssl/err.h ../include/openssl/evp.h -genpkey.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -genpkey.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -genpkey.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -genpkey.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -genpkey.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -genpkey.o: ../include/openssl/safestack.h ../include/openssl/sha.h -genpkey.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -genpkey.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -genpkey.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -genpkey.o: genpkey.c -genrsa.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -genrsa.o: ../include/openssl/bn.h ../include/openssl/buffer.h -genrsa.o: ../include/openssl/conf.h ../include/openssl/crypto.h -genrsa.o: ../include/openssl/dh.h ../include/openssl/dsa.h -genrsa.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -genrsa.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -genrsa.o: ../include/openssl/engine.h ../include/openssl/err.h -genrsa.o: ../include/openssl/evp.h ../include/openssl/lhash.h -genrsa.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -genrsa.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -genrsa.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -genrsa.o: ../include/openssl/pem.h ../include/openssl/pem2.h -genrsa.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -genrsa.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -genrsa.o: ../include/openssl/sha.h ../include/openssl/stack.h -genrsa.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -genrsa.o: ../include/openssl/ui.h ../include/openssl/x509.h -genrsa.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -genrsa.o: genrsa.c -nseq.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -nseq.o: ../include/openssl/buffer.h ../include/openssl/conf.h -nseq.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -nseq.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -nseq.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -nseq.o: ../include/openssl/err.h ../include/openssl/evp.h -nseq.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -nseq.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -nseq.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -nseq.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -nseq.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -nseq.o: ../include/openssl/safestack.h ../include/openssl/sha.h -nseq.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -nseq.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -nseq.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h nseq.c -ocsp.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ocsp.o: ../include/openssl/bn.h ../include/openssl/buffer.h -ocsp.o: ../include/openssl/comp.h ../include/openssl/conf.h -ocsp.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h -ocsp.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -ocsp.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -ocsp.o: ../include/openssl/engine.h ../include/openssl/err.h -ocsp.o: ../include/openssl/evp.h ../include/openssl/hmac.h -ocsp.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -ocsp.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -ocsp.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -ocsp.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -ocsp.o: ../include/openssl/pem.h ../include/openssl/pem2.h -ocsp.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h -ocsp.o: ../include/openssl/safestack.h ../include/openssl/sha.h -ocsp.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -ocsp.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -ocsp.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -ocsp.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -ocsp.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -ocsp.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h ocsp.c -openssl.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -openssl.o: ../include/openssl/buffer.h ../include/openssl/comp.h -openssl.o: ../include/openssl/conf.h ../include/openssl/crypto.h -openssl.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -openssl.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -openssl.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -openssl.o: ../include/openssl/err.h ../include/openssl/evp.h -openssl.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -openssl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -openssl.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -openssl.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -openssl.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -openssl.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -openssl.o: ../include/openssl/pqueue.h ../include/openssl/rand.h -openssl.o: ../include/openssl/safestack.h ../include/openssl/sha.h -openssl.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -openssl.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -openssl.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -openssl.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -openssl.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -openssl.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -openssl.o: openssl.c progs.h s_apps.h -passwd.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -passwd.o: ../include/openssl/buffer.h ../include/openssl/conf.h -passwd.o: ../include/openssl/crypto.h ../include/openssl/des.h -passwd.o: ../include/openssl/des_old.h ../include/openssl/e_os2.h -passwd.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -passwd.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -passwd.o: ../include/openssl/err.h ../include/openssl/evp.h -passwd.o: ../include/openssl/lhash.h ../include/openssl/md5.h -passwd.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -passwd.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -passwd.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -passwd.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -passwd.o: ../include/openssl/safestack.h ../include/openssl/sha.h -passwd.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -passwd.o: ../include/openssl/txt_db.h ../include/openssl/ui.h -passwd.o: ../include/openssl/ui_compat.h ../include/openssl/x509.h -passwd.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -passwd.o: passwd.c -pkcs12.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -pkcs12.o: ../include/openssl/buffer.h ../include/openssl/conf.h -pkcs12.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -pkcs12.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -pkcs12.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -pkcs12.o: ../include/openssl/err.h ../include/openssl/evp.h -pkcs12.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -pkcs12.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -pkcs12.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -pkcs12.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -pkcs12.o: ../include/openssl/pem2.h ../include/openssl/pkcs12.h -pkcs12.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h -pkcs12.o: ../include/openssl/sha.h ../include/openssl/stack.h -pkcs12.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -pkcs12.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -pkcs12.o: ../include/openssl/x509v3.h apps.h pkcs12.c -pkcs7.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -pkcs7.o: ../include/openssl/buffer.h ../include/openssl/conf.h -pkcs7.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -pkcs7.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -pkcs7.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -pkcs7.o: ../include/openssl/err.h ../include/openssl/evp.h -pkcs7.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -pkcs7.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -pkcs7.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -pkcs7.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -pkcs7.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -pkcs7.o: ../include/openssl/safestack.h ../include/openssl/sha.h -pkcs7.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -pkcs7.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -pkcs7.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -pkcs7.o: pkcs7.c -pkcs8.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -pkcs8.o: ../include/openssl/buffer.h ../include/openssl/conf.h -pkcs8.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -pkcs8.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -pkcs8.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -pkcs8.o: ../include/openssl/err.h ../include/openssl/evp.h -pkcs8.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -pkcs8.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -pkcs8.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -pkcs8.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -pkcs8.o: ../include/openssl/pem2.h ../include/openssl/pkcs12.h -pkcs8.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h -pkcs8.o: ../include/openssl/sha.h ../include/openssl/stack.h -pkcs8.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -pkcs8.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -pkcs8.o: ../include/openssl/x509v3.h apps.h pkcs8.c -pkey.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -pkey.o: ../include/openssl/buffer.h ../include/openssl/conf.h -pkey.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -pkey.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -pkey.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -pkey.o: ../include/openssl/err.h ../include/openssl/evp.h -pkey.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -pkey.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -pkey.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -pkey.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -pkey.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -pkey.o: ../include/openssl/safestack.h ../include/openssl/sha.h -pkey.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -pkey.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -pkey.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h pkey.c -pkeyparam.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -pkeyparam.o: ../include/openssl/buffer.h ../include/openssl/conf.h -pkeyparam.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -pkeyparam.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -pkeyparam.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -pkeyparam.o: ../include/openssl/err.h ../include/openssl/evp.h -pkeyparam.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -pkeyparam.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -pkeyparam.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -pkeyparam.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -pkeyparam.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -pkeyparam.o: ../include/openssl/safestack.h ../include/openssl/sha.h -pkeyparam.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -pkeyparam.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -pkeyparam.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -pkeyparam.o: pkeyparam.c -pkeyutl.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -pkeyutl.o: ../include/openssl/buffer.h ../include/openssl/conf.h -pkeyutl.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -pkeyutl.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -pkeyutl.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -pkeyutl.o: ../include/openssl/err.h ../include/openssl/evp.h -pkeyutl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -pkeyutl.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -pkeyutl.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -pkeyutl.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -pkeyutl.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -pkeyutl.o: ../include/openssl/safestack.h ../include/openssl/sha.h -pkeyutl.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -pkeyutl.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -pkeyutl.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -pkeyutl.o: pkeyutl.c -prime.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -prime.o: ../include/openssl/bn.h ../include/openssl/buffer.h -prime.o: ../include/openssl/conf.h ../include/openssl/crypto.h -prime.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -prime.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -prime.o: ../include/openssl/engine.h ../include/openssl/evp.h -prime.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -prime.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -prime.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -prime.o: ../include/openssl/ossl_typ.h ../include/openssl/pkcs7.h -prime.o: ../include/openssl/safestack.h ../include/openssl/sha.h -prime.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -prime.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -prime.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -prime.o: prime.c -rand.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -rand.o: ../include/openssl/buffer.h ../include/openssl/conf.h -rand.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -rand.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -rand.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -rand.o: ../include/openssl/err.h ../include/openssl/evp.h -rand.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -rand.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -rand.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -rand.o: ../include/openssl/ossl_typ.h ../include/openssl/pkcs7.h -rand.o: ../include/openssl/rand.h ../include/openssl/safestack.h -rand.o: ../include/openssl/sha.h ../include/openssl/stack.h -rand.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -rand.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -rand.o: ../include/openssl/x509v3.h apps.h rand.c -req.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -req.o: ../include/openssl/bn.h ../include/openssl/buffer.h -req.o: ../include/openssl/conf.h ../include/openssl/crypto.h -req.o: ../include/openssl/dh.h ../include/openssl/dsa.h -req.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -req.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -req.o: ../include/openssl/engine.h ../include/openssl/err.h -req.o: ../include/openssl/evp.h ../include/openssl/lhash.h -req.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -req.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -req.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -req.o: ../include/openssl/pem.h ../include/openssl/pem2.h -req.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -req.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -req.o: ../include/openssl/sha.h ../include/openssl/stack.h -req.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -req.o: ../include/openssl/ui.h ../include/openssl/x509.h -req.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h req.c -rsa.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -rsa.o: ../include/openssl/bn.h ../include/openssl/buffer.h -rsa.o: ../include/openssl/conf.h ../include/openssl/crypto.h -rsa.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -rsa.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -rsa.o: ../include/openssl/engine.h ../include/openssl/err.h -rsa.o: ../include/openssl/evp.h ../include/openssl/lhash.h -rsa.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -rsa.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -rsa.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -rsa.o: ../include/openssl/pem.h ../include/openssl/pem2.h -rsa.o: ../include/openssl/pkcs7.h ../include/openssl/rsa.h -rsa.o: ../include/openssl/safestack.h ../include/openssl/sha.h -rsa.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -rsa.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -rsa.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h rsa.c -rsautl.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -rsautl.o: ../include/openssl/buffer.h ../include/openssl/conf.h -rsautl.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -rsautl.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -rsautl.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -rsautl.o: ../include/openssl/err.h ../include/openssl/evp.h -rsautl.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -rsautl.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -rsautl.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -rsautl.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -rsautl.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -rsautl.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -rsautl.o: ../include/openssl/sha.h ../include/openssl/stack.h -rsautl.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -rsautl.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -rsautl.o: ../include/openssl/x509v3.h apps.h rsautl.c -s_cb.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -s_cb.o: ../include/openssl/buffer.h ../include/openssl/comp.h -s_cb.o: ../include/openssl/conf.h ../include/openssl/crypto.h -s_cb.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -s_cb.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -s_cb.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -s_cb.o: ../include/openssl/err.h ../include/openssl/evp.h -s_cb.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -s_cb.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -s_cb.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -s_cb.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -s_cb.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -s_cb.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -s_cb.o: ../include/openssl/pqueue.h ../include/openssl/rand.h -s_cb.o: ../include/openssl/safestack.h ../include/openssl/sha.h -s_cb.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -s_cb.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s_cb.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s_cb.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s_cb.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -s_cb.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -s_cb.o: s_apps.h s_cb.c -s_client.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -s_client.o: ../include/openssl/bn.h ../include/openssl/buffer.h -s_client.o: ../include/openssl/comp.h ../include/openssl/conf.h -s_client.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h -s_client.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -s_client.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -s_client.o: ../include/openssl/engine.h ../include/openssl/err.h -s_client.o: ../include/openssl/evp.h ../include/openssl/hmac.h -s_client.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -s_client.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -s_client.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -s_client.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -s_client.o: ../include/openssl/pem.h ../include/openssl/pem2.h -s_client.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h -s_client.o: ../include/openssl/rand.h ../include/openssl/safestack.h -s_client.o: ../include/openssl/sha.h ../include/openssl/srp.h -s_client.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -s_client.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -s_client.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -s_client.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -s_client.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -s_client.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -s_client.o: s_apps.h s_client.c timeouts.h -s_server.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -s_server.o: ../include/openssl/bn.h ../include/openssl/buffer.h -s_server.o: ../include/openssl/comp.h ../include/openssl/conf.h -s_server.o: ../include/openssl/crypto.h ../include/openssl/dh.h -s_server.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h -s_server.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -s_server.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -s_server.o: ../include/openssl/engine.h ../include/openssl/err.h -s_server.o: ../include/openssl/evp.h ../include/openssl/hmac.h -s_server.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -s_server.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -s_server.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -s_server.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -s_server.o: ../include/openssl/pem.h ../include/openssl/pem2.h -s_server.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h -s_server.o: ../include/openssl/rand.h ../include/openssl/rsa.h -s_server.o: ../include/openssl/safestack.h ../include/openssl/sha.h -s_server.o: ../include/openssl/srp.h ../include/openssl/srtp.h -s_server.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s_server.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s_server.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s_server.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -s_server.o: ../include/openssl/ui.h ../include/openssl/x509.h -s_server.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -s_server.o: s_apps.h s_server.c timeouts.h -s_socket.o: ../e_os.h ../e_os2.h ../include/openssl/asn1.h -s_socket.o: ../include/openssl/bio.h ../include/openssl/buffer.h -s_socket.o: ../include/openssl/comp.h ../include/openssl/conf.h -s_socket.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h -s_socket.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -s_socket.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -s_socket.o: ../include/openssl/engine.h ../include/openssl/evp.h -s_socket.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -s_socket.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -s_socket.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -s_socket.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -s_socket.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -s_socket.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -s_socket.o: ../include/openssl/pqueue.h ../include/openssl/safestack.h -s_socket.o: ../include/openssl/sha.h ../include/openssl/srtp.h -s_socket.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s_socket.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s_socket.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s_socket.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -s_socket.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -s_socket.o: ../include/openssl/x509v3.h apps.h s_apps.h s_socket.c -s_time.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -s_time.o: ../include/openssl/buffer.h ../include/openssl/comp.h -s_time.o: ../include/openssl/conf.h ../include/openssl/crypto.h -s_time.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -s_time.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -s_time.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -s_time.o: ../include/openssl/err.h ../include/openssl/evp.h -s_time.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -s_time.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -s_time.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -s_time.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -s_time.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -s_time.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -s_time.o: ../include/openssl/pqueue.h ../include/openssl/safestack.h -s_time.o: ../include/openssl/sha.h ../include/openssl/srtp.h -s_time.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -s_time.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -s_time.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s_time.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -s_time.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -s_time.o: ../include/openssl/x509v3.h apps.h s_apps.h s_time.c -sess_id.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -sess_id.o: ../include/openssl/buffer.h ../include/openssl/comp.h -sess_id.o: ../include/openssl/conf.h ../include/openssl/crypto.h -sess_id.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -sess_id.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -sess_id.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -sess_id.o: ../include/openssl/err.h ../include/openssl/evp.h -sess_id.o: ../include/openssl/hmac.h ../include/openssl/kssl.h -sess_id.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -sess_id.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -sess_id.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -sess_id.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -sess_id.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -sess_id.o: ../include/openssl/pqueue.h ../include/openssl/safestack.h -sess_id.o: ../include/openssl/sha.h ../include/openssl/srtp.h -sess_id.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h -sess_id.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h -sess_id.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -sess_id.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -sess_id.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -sess_id.o: ../include/openssl/x509v3.h apps.h sess_id.c -smime.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -smime.o: ../include/openssl/buffer.h ../include/openssl/conf.h -smime.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -smime.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -smime.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -smime.o: ../include/openssl/err.h ../include/openssl/evp.h -smime.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -smime.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -smime.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -smime.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -smime.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -smime.o: ../include/openssl/safestack.h ../include/openssl/sha.h -smime.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -smime.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -smime.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -smime.o: smime.c -speed.o: ../e_os.h ../include/openssl/aes.h ../include/openssl/asn1.h -speed.o: ../include/openssl/bio.h ../include/openssl/blowfish.h -speed.o: ../include/openssl/bn.h ../include/openssl/buffer.h -speed.o: ../include/openssl/camellia.h ../include/openssl/cast.h -speed.o: ../include/openssl/conf.h ../include/openssl/crypto.h -speed.o: ../include/openssl/des.h ../include/openssl/des_old.h -speed.o: ../include/openssl/dsa.h ../include/openssl/e_os2.h -speed.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -speed.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -speed.o: ../include/openssl/err.h ../include/openssl/evp.h -speed.o: ../include/openssl/hmac.h ../include/openssl/idea.h -speed.o: ../include/openssl/lhash.h ../include/openssl/md4.h -speed.o: ../include/openssl/md5.h ../include/openssl/mdc2.h -speed.o: ../include/openssl/modes.h ../include/openssl/obj_mac.h -speed.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -speed.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -speed.o: ../include/openssl/ossl_typ.h ../include/openssl/pkcs7.h -speed.o: ../include/openssl/rand.h ../include/openssl/rc2.h -speed.o: ../include/openssl/rc4.h ../include/openssl/ripemd.h -speed.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -speed.o: ../include/openssl/seed.h ../include/openssl/sha.h -speed.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -speed.o: ../include/openssl/txt_db.h ../include/openssl/ui.h -speed.o: ../include/openssl/ui_compat.h ../include/openssl/whrlpool.h -speed.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -speed.o: ../include/openssl/x509v3.h apps.h speed.c testdsa.h testrsa.h -spkac.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -spkac.o: ../include/openssl/buffer.h ../include/openssl/conf.h -spkac.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -spkac.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -spkac.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -spkac.o: ../include/openssl/err.h ../include/openssl/evp.h -spkac.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -spkac.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -spkac.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -spkac.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -spkac.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -spkac.o: ../include/openssl/safestack.h ../include/openssl/sha.h -spkac.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -spkac.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -spkac.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -spkac.o: spkac.c -srp.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -srp.o: ../include/openssl/bn.h ../include/openssl/buffer.h -srp.o: ../include/openssl/conf.h ../include/openssl/crypto.h -srp.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -srp.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -srp.o: ../include/openssl/engine.h ../include/openssl/err.h -srp.o: ../include/openssl/evp.h ../include/openssl/lhash.h -srp.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -srp.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -srp.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -srp.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h -srp.o: ../include/openssl/sha.h ../include/openssl/srp.h -srp.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -srp.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -srp.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h srp.c -ts.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -ts.o: ../include/openssl/bn.h ../include/openssl/buffer.h -ts.o: ../include/openssl/conf.h ../include/openssl/crypto.h -ts.o: ../include/openssl/dh.h ../include/openssl/dsa.h -ts.o: ../include/openssl/e_os2.h ../include/openssl/ec.h -ts.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h -ts.o: ../include/openssl/engine.h ../include/openssl/err.h -ts.o: ../include/openssl/evp.h ../include/openssl/lhash.h -ts.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -ts.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -ts.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -ts.o: ../include/openssl/pem.h ../include/openssl/pem2.h -ts.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -ts.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -ts.o: ../include/openssl/sha.h ../include/openssl/stack.h -ts.o: ../include/openssl/symhacks.h ../include/openssl/ts.h -ts.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -ts.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h ts.c -verify.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -verify.o: ../include/openssl/buffer.h ../include/openssl/conf.h -verify.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h -verify.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -verify.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -verify.o: ../include/openssl/err.h ../include/openssl/evp.h -verify.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -verify.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -verify.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -verify.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -verify.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -verify.o: ../include/openssl/safestack.h ../include/openssl/sha.h -verify.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -verify.o: ../include/openssl/txt_db.h ../include/openssl/x509.h -verify.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h -verify.o: verify.c -version.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -version.o: ../include/openssl/blowfish.h ../include/openssl/bn.h -version.o: ../include/openssl/buffer.h ../include/openssl/conf.h -version.o: ../include/openssl/crypto.h ../include/openssl/des.h -version.o: ../include/openssl/des_old.h ../include/openssl/e_os2.h -version.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -version.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -version.o: ../include/openssl/evp.h ../include/openssl/idea.h -version.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -version.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -version.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -version.o: ../include/openssl/ossl_typ.h ../include/openssl/pkcs7.h -version.o: ../include/openssl/rc4.h ../include/openssl/safestack.h -version.o: ../include/openssl/sha.h ../include/openssl/stack.h -version.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -version.o: ../include/openssl/ui.h ../include/openssl/ui_compat.h -version.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -version.o: ../include/openssl/x509v3.h apps.h version.c -x509.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -x509.o: ../include/openssl/bn.h ../include/openssl/buffer.h -x509.o: ../include/openssl/conf.h ../include/openssl/crypto.h -x509.o: ../include/openssl/dsa.h ../include/openssl/e_os2.h -x509.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -x509.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -x509.o: ../include/openssl/err.h ../include/openssl/evp.h -x509.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h -x509.o: ../include/openssl/objects.h ../include/openssl/ocsp.h -x509.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h -x509.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h -x509.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h -x509.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -x509.o: ../include/openssl/sha.h ../include/openssl/stack.h -x509.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h -x509.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -x509.o: ../include/openssl/x509v3.h apps.h x509.c diff --git a/apps/app_rand.c b/apps/app_rand.c index 0bbf342e7e1a..28caad41a7d8 100644 --- a/apps/app_rand.c +++ b/apps/app_rand.c @@ -1,217 +1,94 @@ -/* apps/app_rand.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#define NON_MAIN #include "apps.h" -#undef NON_MAIN #include <openssl/bio.h> +#include <openssl/err.h> #include <openssl/rand.h> +#include <openssl/conf.h> -static int seeded = 0; -static int egdsocket = 0; +static char *save_rand_file; -int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn) +void app_RAND_load_conf(CONF *c, const char *section) { - int consider_randfile = (file == NULL); - char buffer[200]; - -#ifdef OPENSSL_SYS_WINDOWS - RAND_screen(); -#endif + const char *randfile = NCONF_get_string(c, section, "RANDFILE"); - if (file == NULL) - file = RAND_file_name(buffer, sizeof(buffer)); - else if (RAND_egd(file) > 0) { - /* - * we try if the given filename is an EGD socket. if it is, we don't - * write anything back to the file. - */ - egdsocket = 1; - return 1; + if (randfile == NULL) { + ERR_clear_error(); + return; } - if (file == NULL || !RAND_load_file(file, -1)) { - if (RAND_status() == 0) { - if (!dont_warn) { - BIO_printf(bio_e, "unable to load 'random state'\n"); - BIO_printf(bio_e, - "This means that the random number generator has not been seeded\n"); - BIO_printf(bio_e, "with much random data.\n"); - if (consider_randfile) { /* explanation does not apply when a - * file is explicitly named */ - BIO_printf(bio_e, - "Consider setting the RANDFILE environment variable to point at a file that\n"); - BIO_printf(bio_e, - "'random' data can be kept in (the file will be overwritten).\n"); - } - } - return 0; - } + if (RAND_load_file(randfile, -1) < 0) { + BIO_printf(bio_err, "Can't load %s into RNG\n", randfile); + ERR_print_errors(bio_err); + return; } - seeded = 1; - return 1; + if (save_rand_file == NULL) + save_rand_file = OPENSSL_strdup(randfile); } -long app_RAND_load_files(char *name) +static int loadfiles(char *name) { - char *p, *n; - int last; - long tot = 0; - int egd; + char *p; + int last, ret = 1; - for (;;) { + for ( ; ; ) { last = 0; - for (p = name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++) ; + for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++) + continue; if (*p == '\0') last = 1; *p = '\0'; - n = name; - name = p + 1; - if (*n == '\0') - break; - - egd = RAND_egd(n); - if (egd > 0) - tot += egd; - else - tot += RAND_load_file(n, -1); + if (RAND_load_file(name, -1) < 0) { + BIO_printf(bio_err, "Can't load %s into RNG\n", name); + ERR_print_errors(bio_err); + ret = 0; + } if (last) break; + name = p + 1; + if (*name == '\0') + break; } - if (tot > 512) - app_RAND_allow_write_file(); - return (tot); + return ret; } -int app_RAND_write_file(const char *file, BIO *bio_e) +void app_RAND_write(void) { - char buffer[200]; - - if (egdsocket || !seeded) - /* - * If we did not manage to read the seed file, we should not write a - * low-entropy seed file back -- it would suppress a crucial warning - * the next time we want to use it. - */ - return 0; - - if (file == NULL) - file = RAND_file_name(buffer, sizeof(buffer)); - if (file == NULL || !RAND_write_file(file)) { - BIO_printf(bio_e, "unable to write 'random state'\n"); - return 0; + if (save_rand_file == NULL) + return; + if (RAND_write_file(save_rand_file) == -1) { + BIO_printf(bio_err, "Cannot write random bytes:\n"); + ERR_print_errors(bio_err); } - return 1; + OPENSSL_free(save_rand_file); + save_rand_file = NULL; } -void app_RAND_allow_write_file(void) + +/* + * See comments in opt_verify for explanation of this. + */ +enum r_range { OPT_R_ENUM }; + +int opt_rand(int opt) { - seeded = 1; + switch ((enum r_range)opt) { + case OPT_R__FIRST: + case OPT_R__LAST: + break; + case OPT_R_RAND: + return loadfiles(opt_arg()); + break; + case OPT_R_WRITERAND: + OPENSSL_free(save_rand_file); + save_rand_file = OPENSSL_strdup(opt_arg()); + break; + } + return 1; } diff --git a/apps/apps.c b/apps/apps.c index c5a515229556..9be656054a45 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -1,112 +1,10 @@ -/* apps/apps.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) @@ -116,13 +14,17 @@ */ # define _POSIX_C_SOURCE 2 #endif + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> +#ifndef OPENSSL_NO_POSIX_IO +# include <sys/stat.h> +# include <fcntl.h> +#endif #include <ctype.h> #include <errno.h> -#include <assert.h> #include <openssl/err.h> #include <openssl/x509.h> #include <openssl/x509v3.h> @@ -137,21 +39,13 @@ # include <openssl/rsa.h> #endif #include <openssl/bn.h> -#ifndef OPENSSL_NO_JPAKE -# include <openssl/jpake.h> -#endif - -#define NON_MAIN +#include <openssl/ssl.h> +#include "s_apps.h" #include "apps.h" -#undef NON_MAIN #ifdef _WIN32 static int WIN32_rename(const char *from, const char *to); # define rename(from,to) WIN32_rename((from),(to)) -# ifdef fileno -# undef fileno -# endif -# define fileno(a) (int)_fileno(a) #endif typedef struct { @@ -161,327 +55,137 @@ typedef struct { } NAME_EX_TBL; static UI_METHOD *ui_method = NULL; +static const UI_METHOD *ui_fallback_method = NULL; static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL * in_tbl); static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL * in_tbl); -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) -/* Looks like this stuff is worth moving into separate function */ -static EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file, - const char *key_descrip, int format); -#endif - int app_init(long mesgwin); -#ifdef undef /* never finished - probably never will be - * :-) */ -int args_from_file(char *file, int *argc, char **argv[]) -{ - FILE *fp; - int num, i; - unsigned int len; - static char *buf = NULL; - static char **arg = NULL; - char *p; - fp = fopen(file, "r"); - if (fp == NULL) - return (0); +int chopup_args(ARGS *arg, char *buf) +{ + int quoted; + char c = '\0', *p = NULL; - if (fseek(fp, 0, SEEK_END) == 0) - len = ftell(fp), rewind(fp); - else - len = -1; - if (len <= 0) { - fclose(fp); - return (0); + arg->argc = 0; + if (arg->size == 0) { + arg->size = 20; + arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space"); } - *argc = 0; - *argv = NULL; - - if (buf != NULL) - OPENSSL_free(buf); - buf = (char *)OPENSSL_malloc(len + 1); - if (buf == NULL) - return (0); - - len = fread(buf, 1, len, fp); - if (len <= 1) - return (0); - buf[len] = '\0'; - - i = 0; - for (p = buf; *p; p++) - if (*p == '\n') - i++; - if (arg != NULL) - OPENSSL_free(arg); - arg = (char **)OPENSSL_malloc(sizeof(char *) * (i * 2)); - if (arg == NULL) - return 0; - *argv = arg; - num = 0; - p = buf; - for (;;) { - if (!*p) - break; - if (*p == '#') { /* comment line */ - while (*p && (*p != '\n')) - p++; - continue; - } - /* else we have a line */ - *(arg++) = p; - num++; - while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n'))) + for (p = buf;;) { + /* Skip whitespace. */ + while (*p && isspace(_UC(*p))) p++; if (!*p) break; - if (*p == '\n') { - *(p++) = '\0'; - continue; + + /* The start of something good :-) */ + if (arg->argc >= arg->size) { + char **tmp; + arg->size += 20; + tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size); + if (tmp == NULL) + return 0; + arg->argv = tmp; } - /* else it is a tab or space */ - p++; - while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) - p++; - if (!*p) - break; - if (*p == '\n') { - p++; - continue; + quoted = *p == '\'' || *p == '"'; + if (quoted) + c = *p++; + arg->argv[arg->argc++] = p; + + /* now look for the end of this */ + if (quoted) { + while (*p && *p != c) + p++; + *p++ = '\0'; + } else { + while (*p && !isspace(_UC(*p))) + p++; + if (*p) + *p++ = '\0'; } - *(arg++) = p++; - num++; - while (*p && (*p != '\n')) - p++; - if (!*p) - break; - /* else *p == '\n' */ - *(p++) = '\0'; } - *argc = num; - return (1); + arg->argv[arg->argc] = NULL; + return 1; } -#endif -int str2fmt(char *s) +#ifndef APP_INIT +int app_init(long mesgwin) { - if (s == NULL) - return FORMAT_UNDEF; - if ((*s == 'D') || (*s == 'd')) - return (FORMAT_ASN1); - else if ((*s == 'T') || (*s == 't')) - return (FORMAT_TEXT); - else if ((*s == 'N') || (*s == 'n')) - return (FORMAT_NETSCAPE); - else if ((*s == 'S') || (*s == 's')) - return (FORMAT_SMIME); - else if ((*s == 'M') || (*s == 'm')) - return (FORMAT_MSBLOB); - else if ((*s == '1') - || (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0) - || (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0)) - return (FORMAT_PKCS12); - else if ((*s == 'E') || (*s == 'e')) - return (FORMAT_ENGINE); - else if ((*s == 'H') || (*s == 'h')) - return FORMAT_HTTP; - else if ((*s == 'P') || (*s == 'p')) { - if (s[1] == 'V' || s[1] == 'v') - return FORMAT_PVK; - else - return (FORMAT_PEM); - } else - return (FORMAT_UNDEF); + return 1; } +#endif -#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE) -void program_name(char *in, char *out, int size) +int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath, int noCAfile, int noCApath) { - int i, n; - char *p = NULL; - - n = strlen(in); - /* find the last '/', '\' or ':' */ - for (i = n - 1; i > 0; i--) { - if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':')) { - p = &(in[i + 1]); - break; - } - } - if (p == NULL) - p = in; - n = strlen(p); - -# if defined(OPENSSL_SYS_NETWARE) - /* strip off trailing .nlm if present. */ - if ((n > 4) && (p[n - 4] == '.') && - ((p[n - 3] == 'n') || (p[n - 3] == 'N')) && - ((p[n - 2] == 'l') || (p[n - 2] == 'L')) && - ((p[n - 1] == 'm') || (p[n - 1] == 'M'))) - n -= 4; -# else - /* strip off trailing .exe if present. */ - if ((n > 4) && (p[n - 4] == '.') && - ((p[n - 3] == 'e') || (p[n - 3] == 'E')) && - ((p[n - 2] == 'x') || (p[n - 2] == 'X')) && - ((p[n - 1] == 'e') || (p[n - 1] == 'E'))) - n -= 4; -# endif - - if (n > size - 1) - n = size - 1; + if (CAfile == NULL && CApath == NULL) { + if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0) + return 0; + if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0) + return 0; - for (i = 0; i < n; i++) { - if ((p[i] >= 'A') && (p[i] <= 'Z')) - out[i] = p[i] - 'A' + 'a'; - else - out[i] = p[i]; + return 1; } - out[n] = '\0'; + return SSL_CTX_load_verify_locations(ctx, CAfile, CApath); } -#else -# ifdef OPENSSL_SYS_VMS -void program_name(char *in, char *out, int size) -{ - char *p = in, *q; - char *chars = ":]>"; - while (*chars != '\0') { - q = strrchr(p, *chars); - if (q > p) - p = q + 1; - chars++; - } +#ifndef OPENSSL_NO_CT - q = strrchr(p, '.'); - if (q == NULL) - q = p + strlen(p); - strncpy(out, p, size - 1); - if (q - p >= size) { - out[size - 1] = '\0'; - } else { - out[q - p] = '\0'; - } -} -# else -void program_name(char *in, char *out, int size) +int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path) { - char *p; + if (path == NULL) + return SSL_CTX_set_default_ctlog_list_file(ctx); - p = strrchr(in, '/'); - if (p != NULL) - p++; - else - p = in; - BUF_strlcpy(out, p, size); + return SSL_CTX_set_ctlog_list_file(ctx, path); } -# endif -#endif - -int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]) -{ - int num, i; - char *p; - - *argc = 0; - *argv = NULL; - i = 0; - if (arg->count == 0) { - arg->count = 20; - arg->data = (char **)OPENSSL_malloc(sizeof(char *) * arg->count); - if (arg->data == NULL) - return 0; - } - for (i = 0; i < arg->count; i++) - arg->data[i] = NULL; +#endif - num = 0; - p = buf; - for (;;) { - /* first scan over white space */ - if (!*p) - break; - while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) - p++; - if (!*p) - break; +static unsigned long nmflag = 0; +static char nmflag_set = 0; - /* The start of something good :-) */ - if (num >= arg->count) { - char **tmp_p; - int tlen = arg->count + 20; - tmp_p = (char **)OPENSSL_realloc(arg->data, - sizeof(char *) * tlen); - if (tmp_p == NULL) - return 0; - arg->data = tmp_p; - arg->count = tlen; - /* initialize newly allocated data */ - for (i = num; i < arg->count; i++) - arg->data[i] = NULL; - } - arg->data[num++] = p; +int set_nameopt(const char *arg) +{ + int ret = set_name_ex(&nmflag, arg); - /* now look for the end of this */ - if ((*p == '\'') || (*p == '\"')) { /* scan for closing quote */ - i = *(p++); - arg->data[num - 1]++; /* jump over quote */ - while (*p && (*p != i)) - p++; - *p = '\0'; - } else { - while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n'))) - p++; + if (ret) + nmflag_set = 1; - if (*p == '\0') - p--; - else - *p = '\0'; - } - p++; - } - *argc = num; - *argv = arg->data; - return (1); + return ret; } -#ifndef APP_INIT -int app_init(long mesgwin) +unsigned long get_nameopt(void) { - return (1); + return (nmflag_set) ? nmflag : XN_FLAG_ONELINE; } -#endif int dump_cert_text(BIO *out, X509 *x) { - char *p; - - p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0); - BIO_puts(out, "subject="); - BIO_puts(out, p); - OPENSSL_free(p); - - p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0); - BIO_puts(out, "\nissuer="); - BIO_puts(out, p); + print_name(out, "subject=", X509_get_subject_name(x), get_nameopt()); + BIO_puts(out, "\n"); + print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); BIO_puts(out, "\n"); - OPENSSL_free(p); return 0; } static int ui_open(UI *ui) { - return UI_method_get_opener(UI_OpenSSL())(ui); + int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method); + + if (opener) + return opener(ui); + return 1; } static int ui_read(UI *ui, UI_STRING *uis) { + int (*reader)(UI *ui, UI_STRING *uis) = NULL; + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && UI_get0_user_data(ui)) { switch (UI_get_string_type(uis)) { @@ -495,15 +199,25 @@ static int ui_read(UI *ui, UI_STRING *uis) return 1; } } - default: + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: break; } } - return UI_method_get_reader(UI_OpenSSL())(ui, uis); + + reader = UI_method_get_reader(ui_fallback_method); + if (reader) + return reader(ui, uis); + return 1; } static int ui_write(UI *ui, UI_STRING *uis) { + int (*writer)(UI *ui, UI_STRING *uis) = NULL; + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && UI_get0_user_data(ui)) { switch (UI_get_string_type(uis)) { @@ -515,20 +229,36 @@ static int ui_write(UI *ui, UI_STRING *uis) if (password && password[0] != '\0') return 1; } - default: + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: break; } } - return UI_method_get_writer(UI_OpenSSL())(ui, uis); + + writer = UI_method_get_writer(ui_fallback_method); + if (writer) + return writer(ui, uis); + return 1; } static int ui_close(UI *ui) { - return UI_method_get_closer(UI_OpenSSL())(ui); + int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method); + + if (closer) + return closer(ui); + return 1; } int setup_ui_method(void) { + ui_fallback_method = UI_null(); +#ifndef OPENSSL_NO_UI_CONSOLE + ui_fallback_method = UI_OpenSSL(); +#endif ui_method = UI_create_method("OpenSSL application user interface"); UI_method_set_opener(ui_method, ui_open); UI_method_set_reader(ui_method, ui_read); @@ -545,36 +275,27 @@ void destroy_ui_method(void) } } +const UI_METHOD *get_ui_method(void) +{ + return ui_method; +} + int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) { - UI *ui = NULL; int res = 0; - const char *prompt_info = NULL; - const char *password = NULL; + UI *ui = NULL; PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp; - if (cb_data) { - if (cb_data->password) - password = cb_data->password; - if (cb_data->prompt_info) - prompt_info = cb_data->prompt_info; - } - - if (password) { - res = strlen(password); - if (res > bufsiz) - res = bufsiz; - memcpy(buf, password, res); - return res; - } - ui = UI_new_method(ui_method); if (ui) { int ok = 0; char *buff = NULL; int ui_flags = 0; - char *prompt = NULL; + const char *prompt_info = NULL; + char *prompt; + if (cb_data != NULL && cb_data->prompt_info != NULL) + prompt_info = cb_data->prompt_info; prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); if (!prompt) { BIO_printf(bio_err, "Out of memory\n"); @@ -585,30 +306,23 @@ int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); - if (ok >= 0) - ok = UI_add_input_string(ui, prompt, ui_flags, buf, - PW_MIN_LENGTH, bufsiz - 1); + /* We know that there is no previous user data to return to us */ + (void)UI_add_user_data(ui, cb_data); + + ok = UI_add_input_string(ui, prompt, ui_flags, buf, + PW_MIN_LENGTH, bufsiz - 1); + if (ok >= 0 && verify) { - buff = (char *)OPENSSL_malloc(bufsiz); - if (!buff) { - BIO_printf(bio_err, "Out of memory\n"); - UI_free(ui); - OPENSSL_free(prompt); - return 0; - } + buff = app_malloc(bufsiz, "password buffer"); ok = UI_add_verify_string(ui, prompt, ui_flags, buff, PW_MIN_LENGTH, bufsiz - 1, buf); } if (ok >= 0) do { ok = UI_process(ui); - } - while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); + } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); - if (buff) { - OPENSSL_cleanse(buff, (unsigned int)bufsiz); - OPENSSL_free(buff); - } + OPENSSL_clear_free(buff, (unsigned int)bufsiz); if (ok >= 0) res = strlen(buf); @@ -629,50 +343,53 @@ int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) return res; } -static char *app_get_pass(BIO *err, char *arg, int keepbio); +static char *app_get_pass(const char *arg, int keepbio); -int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2) +int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2) { int same; - if (!arg2 || !arg1 || strcmp(arg1, arg2)) + if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2)) same = 0; else same = 1; - if (arg1) { - *pass1 = app_get_pass(err, arg1, same); - if (!*pass1) + if (arg1 != NULL) { + *pass1 = app_get_pass(arg1, same); + if (*pass1 == NULL) return 0; - } else if (pass1) + } else if (pass1 != NULL) { *pass1 = NULL; - if (arg2) { - *pass2 = app_get_pass(err, arg2, same ? 2 : 0); - if (!*pass2) + } + if (arg2 != NULL) { + *pass2 = app_get_pass(arg2, same ? 2 : 0); + if (*pass2 == NULL) return 0; - } else if (pass2) + } else if (pass2 != NULL) { *pass2 = NULL; + } return 1; } -static char *app_get_pass(BIO *err, char *arg, int keepbio) +static char *app_get_pass(const char *arg, int keepbio) { char *tmp, tpass[APP_PASS_LEN]; static BIO *pwdbio = NULL; int i; - if (!strncmp(arg, "pass:", 5)) - return BUF_strdup(arg + 5); - if (!strncmp(arg, "env:", 4)) { + + if (strncmp(arg, "pass:", 5) == 0) + return OPENSSL_strdup(arg + 5); + if (strncmp(arg, "env:", 4) == 0) { tmp = getenv(arg + 4); - if (!tmp) { - BIO_printf(err, "Can't read environment variable %s\n", arg + 4); + if (tmp == NULL) { + BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4); return NULL; } - return BUF_strdup(tmp); + return OPENSSL_strdup(tmp); } - if (!keepbio || !pwdbio) { - if (!strncmp(arg, "file:", 5)) { + if (!keepbio || pwdbio == NULL) { + if (strncmp(arg, "file:", 5) == 0) { pwdbio = BIO_new_file(arg + 5, "r"); - if (!pwdbio) { - BIO_printf(err, "Can't open file %s\n", arg + 5); + if (pwdbio == NULL) { + BIO_printf(bio_err, "Can't open file %s\n", arg + 5); return NULL; } #if !defined(_WIN32) @@ -684,13 +401,13 @@ static char *app_get_pass(BIO *err, char *arg, int keepbio) * on real Windows descriptors, such as those obtained * with CreateFile. */ - } else if (!strncmp(arg, "fd:", 3)) { + } else if (strncmp(arg, "fd:", 3) == 0) { BIO *btmp; i = atoi(arg + 3); if (i >= 0) pwdbio = BIO_new_fd(i, BIO_NOCLOSE); if ((i < 0) || !pwdbio) { - BIO_printf(err, "Can't access file descriptor %s\n", arg + 3); + BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3); return NULL; } /* @@ -699,14 +416,14 @@ static char *app_get_pass(BIO *err, char *arg, int keepbio) btmp = BIO_new(BIO_f_buffer()); pwdbio = BIO_push(btmp, pwdbio); #endif - } else if (!strcmp(arg, "stdin")) { - pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE); + } else if (strcmp(arg, "stdin") == 0) { + pwdbio = dup_bio_in(FORMAT_TEXT); if (!pwdbio) { - BIO_printf(err, "Can't open BIO for stdin\n"); + BIO_printf(bio_err, "Can't open BIO for stdin\n"); return NULL; } } else { - BIO_printf(err, "Invalid password argument \"%s\"\n", arg); + BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg); return NULL; } } @@ -716,33 +433,107 @@ static char *app_get_pass(BIO *err, char *arg, int keepbio) pwdbio = NULL; } if (i <= 0) { - BIO_printf(err, "Error reading password from BIO\n"); + BIO_printf(bio_err, "Error reading password from BIO\n"); return NULL; } tmp = strchr(tpass, '\n'); - if (tmp) + if (tmp != NULL) *tmp = 0; - return BUF_strdup(tpass); + return OPENSSL_strdup(tpass); +} + +CONF *app_load_config_bio(BIO *in, const char *filename) +{ + long errorline = -1; + CONF *conf; + int i; + + conf = NCONF_new(NULL); + i = NCONF_load_bio(conf, in, &errorline); + if (i > 0) + return conf; + + if (errorline <= 0) { + BIO_printf(bio_err, "%s: Can't load ", opt_getprog()); + } else { + BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(), + errorline); + } + if (filename != NULL) + BIO_printf(bio_err, "config file \"%s\"\n", filename); + else + BIO_printf(bio_err, "config input"); + + NCONF_free(conf); + return NULL; +} + +CONF *app_load_config(const char *filename) +{ + BIO *in; + CONF *conf; + + in = bio_open_default(filename, 'r', FORMAT_TEXT); + if (in == NULL) + return NULL; + + conf = app_load_config_bio(in, filename); + BIO_free(in); + return conf; } -int add_oid_section(BIO *err, CONF *conf) +CONF *app_load_config_quiet(const char *filename) +{ + BIO *in; + CONF *conf; + + in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT); + if (in == NULL) + return NULL; + + conf = app_load_config_bio(in, filename); + BIO_free(in); + return conf; +} + +int app_load_modules(const CONF *config) +{ + CONF *to_free = NULL; + + if (config == NULL) + config = to_free = app_load_config_quiet(default_config_file); + if (config == NULL) + return 1; + + if (CONF_modules_load(config, NULL, 0) <= 0) { + BIO_printf(bio_err, "Error configuring OpenSSL modules\n"); + ERR_print_errors(bio_err); + NCONF_free(to_free); + return 0; + } + NCONF_free(to_free); + return 1; +} + +int add_oid_section(CONF *conf) { char *p; STACK_OF(CONF_VALUE) *sktmp; CONF_VALUE *cnf; int i; - if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) { + + if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { ERR_clear_error(); return 1; } - if (!(sktmp = NCONF_get_section(conf, p))) { - BIO_printf(err, "problem loading oid section %s\n", p); + if ((sktmp = NCONF_get_section(conf, p)) == NULL) { + BIO_printf(bio_err, "problem loading oid section %s\n", p); return 0; } for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { cnf = sk_CONF_VALUE_value(sktmp, i); if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { - BIO_printf(err, "problem creating object %s=%s\n", + BIO_printf(bio_err, "problem creating object %s=%s\n", cnf->name, cnf->value); return 0; } @@ -750,7 +541,7 @@ int add_oid_section(BIO *err, CONF *conf) return 1; } -static int load_pkcs12(BIO *err, BIO *in, const char *desc, +static int load_pkcs12(BIO *in, const char *desc, pem_password_cb *pem_cb, void *cb_data, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) { @@ -760,24 +551,24 @@ static int load_pkcs12(BIO *err, BIO *in, const char *desc, PKCS12 *p12; p12 = d2i_PKCS12_bio(in, NULL); if (p12 == NULL) { - BIO_printf(err, "Error loading PKCS12 file for %s\n", desc); + BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc); goto die; } /* See if an empty password will do */ - if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) + if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) { pass = ""; - else { + } else { if (!pem_cb) pem_cb = (pem_password_cb *)password_callback; len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); if (len < 0) { - BIO_printf(err, "Passpharse callback error for %s\n", desc); + BIO_printf(bio_err, "Passphrase callback error for %s\n", desc); goto die; } if (len < PEM_BUFSIZE) tpass[len] = 0; if (!PKCS12_verify_mac(p12, tpass, len)) { - BIO_printf(err, + BIO_printf(bio_err, "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc); goto die; @@ -786,13 +577,12 @@ static int load_pkcs12(BIO *err, BIO *in, const char *desc, } ret = PKCS12_parse(p12, pass, pkey, cert, ca); die: - if (p12) - PKCS12_free(p12); + PKCS12_free(p12); return ret; } -int load_cert_crl_http(const char *url, BIO *err, - X509 **pcert, X509_CRL **pcrl) +#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) +static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl) { char *host = NULL, *port = NULL, *path = NULL; BIO *bio = NULL; @@ -801,15 +591,14 @@ int load_cert_crl_http(const char *url, BIO *err, if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) goto err; if (use_ssl) { - if (err) - BIO_puts(err, "https not supported\n"); + BIO_puts(bio_err, "https not supported\n"); goto err; } bio = BIO_new_connect(host); if (!bio || !BIO_set_conn_port(bio, port)) goto err; rctx = OCSP_REQ_CTX_new(bio, 1024); - if (!rctx) + if (rctx == NULL) goto err; if (!OCSP_REQ_CTX_http(rctx, "GET", path)) goto err; @@ -818,8 +607,7 @@ int load_cert_crl_http(const char *url, BIO *err, if (pcert) { do { rv = X509_http_nbio(rctx, pcert); - } - while (rv == -1); + } while (rv == -1); } else { do { rv = X509_CRL_http_nbio(rctx, pcrl); @@ -827,91 +615,60 @@ int load_cert_crl_http(const char *url, BIO *err, } err: - if (host) - OPENSSL_free(host); - if (path) - OPENSSL_free(path); - if (port) - OPENSSL_free(port); - if (bio) - BIO_free_all(bio); - if (rctx) - OCSP_REQ_CTX_free(rctx); + OPENSSL_free(host); + OPENSSL_free(path); + OPENSSL_free(port); + BIO_free_all(bio); + OCSP_REQ_CTX_free(rctx); if (rv != 1) { - if (bio && err) - BIO_printf(bio_err, "Error loading %s from %s\n", - pcert ? "certificate" : "CRL", url); + BIO_printf(bio_err, "Error loading %s from %s\n", + pcert ? "certificate" : "CRL", url); ERR_print_errors(bio_err); } return rv; } +#endif -X509 *load_cert(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, const char *cert_descrip) +X509 *load_cert(const char *file, int format, const char *cert_descrip) { X509 *x = NULL; BIO *cert; if (format == FORMAT_HTTP) { - load_cert_crl_http(file, err, &x, NULL); +#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) + load_cert_crl_http(file, &x, NULL); +#endif return x; } - if ((cert = BIO_new(BIO_s_file())) == NULL) { - ERR_print_errors(err); - goto end; - } - if (file == NULL) { -#ifdef _IONBF -# ifndef OPENSSL_NO_SETVBUF_IONBF - setvbuf(stdin, NULL, _IONBF, 0); -# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ -#endif - BIO_set_fp(cert, stdin, BIO_NOCLOSE); + unbuffer(stdin); + cert = dup_bio_in(format); } else { - if (BIO_read_filename(cert, file) <= 0) { - BIO_printf(err, "Error opening %s %s\n", cert_descrip, file); - ERR_print_errors(err); - goto end; - } + cert = bio_open_default(file, 'r', format); } + if (cert == NULL) + goto end; - if (format == FORMAT_ASN1) + if (format == FORMAT_ASN1) { x = d2i_X509_bio(cert, NULL); - else if (format == FORMAT_NETSCAPE) { - NETSCAPE_X509 *nx; - nx = ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509), cert, NULL); - if (nx == NULL) - goto end; - - if ((strncmp(NETSCAPE_CERT_HDR, (char *)nx->header->data, - nx->header->length) != 0)) { - NETSCAPE_X509_free(nx); - BIO_printf(err, "Error reading header on certificate\n"); - goto end; - } - x = nx->cert; - nx->cert = NULL; - NETSCAPE_X509_free(nx); - } else if (format == FORMAT_PEM) + } else if (format == FORMAT_PEM) { x = PEM_read_bio_X509_AUX(cert, NULL, (pem_password_cb *)password_callback, NULL); - else if (format == FORMAT_PKCS12) { - if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL, NULL, &x, NULL)) + } else if (format == FORMAT_PKCS12) { + if (!load_pkcs12(cert, cert_descrip, NULL, NULL, NULL, &x, NULL)) goto end; } else { - BIO_printf(err, "bad input format specified for %s\n", cert_descrip); + BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip); goto end; } end: if (x == NULL) { - BIO_printf(err, "unable to load certificate\n"); - ERR_print_errors(err); + BIO_printf(bio_err, "unable to load certificate\n"); + ERR_print_errors(bio_err); } - if (cert != NULL) - BIO_free(cert); - return (x); + BIO_free(cert); + return x; } X509_CRL *load_crl(const char *infile, int format) @@ -920,29 +677,20 @@ X509_CRL *load_crl(const char *infile, int format) BIO *in = NULL; if (format == FORMAT_HTTP) { - load_cert_crl_http(infile, bio_err, NULL, &x); +#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) + load_cert_crl_http(infile, NULL, &x); +#endif return x; } - in = BIO_new(BIO_s_file()); - if (in == NULL) { - ERR_print_errors(bio_err); + in = bio_open_default(infile, 'r', format); + if (in == NULL) goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } - if (format == FORMAT_ASN1) + if (format == FORMAT_ASN1) { x = d2i_X509_CRL_bio(in, NULL); - else if (format == FORMAT_PEM) + } else if (format == FORMAT_PEM) { x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); - else { + } else { BIO_printf(bio_err, "bad input format specified for input crl\n"); goto end; } @@ -954,10 +702,10 @@ X509_CRL *load_crl(const char *infile, int format) end: BIO_free(in); - return (x); + return x; } -EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, +EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *key_descrip) { BIO *key = NULL; @@ -968,82 +716,68 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, cb_data.prompt_info = file; if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { - BIO_printf(err, "no keyfile specified\n"); + BIO_printf(bio_err, "no keyfile specified\n"); goto end; } -#ifndef OPENSSL_NO_ENGINE if (format == FORMAT_ENGINE) { - if (!e) - BIO_printf(err, "no engine specified\n"); - else { + if (e == NULL) { + BIO_printf(bio_err, "no engine specified\n"); + } else { +#ifndef OPENSSL_NO_ENGINE if (ENGINE_init(e)) { pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); ENGINE_finish(e); } - if (!pkey) { - BIO_printf(err, "cannot load %s from engine\n", key_descrip); - ERR_print_errors(err); + if (pkey == NULL) { + BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); + ERR_print_errors(bio_err); } - } - goto end; - } +#else + BIO_printf(bio_err, "engines not supported\n"); #endif - key = BIO_new(BIO_s_file()); - if (key == NULL) { - ERR_print_errors(err); + } goto end; } if (file == NULL && maybe_stdin) { -#ifdef _IONBF -# ifndef OPENSSL_NO_SETVBUF_IONBF - setvbuf(stdin, NULL, _IONBF, 0); -# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ -#endif - BIO_set_fp(key, stdin, BIO_NOCLOSE); - } else if (BIO_read_filename(key, file) <= 0) { - BIO_printf(err, "Error opening %s %s\n", key_descrip, file); - ERR_print_errors(err); - goto end; + unbuffer(stdin); + key = dup_bio_in(format); + } else { + key = bio_open_default(file, 'r', format); } + if (key == NULL) + goto end; if (format == FORMAT_ASN1) { pkey = d2i_PrivateKey_bio(key, NULL); } else if (format == FORMAT_PEM) { pkey = PEM_read_bio_PrivateKey(key, NULL, (pem_password_cb *)password_callback, &cb_data); - } -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) - else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC) - pkey = load_netscape_key(err, key, file, key_descrip, format); -#endif - else if (format == FORMAT_PKCS12) { - if (!load_pkcs12(err, key, key_descrip, + } else if (format == FORMAT_PKCS12) { + if (!load_pkcs12(key, key_descrip, (pem_password_cb *)password_callback, &cb_data, &pkey, NULL, NULL)) goto end; - } #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) - else if (format == FORMAT_MSBLOB) + } else if (format == FORMAT_MSBLOB) { pkey = b2i_PrivateKey_bio(key); - else if (format == FORMAT_PVK) + } else if (format == FORMAT_PVK) { pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback, &cb_data); #endif - else { - BIO_printf(err, "bad input format specified for key file\n"); + } else { + BIO_printf(bio_err, "bad input format specified for key file\n"); goto end; } end: - if (key != NULL) - BIO_free(key); + BIO_free(key); if (pkey == NULL) { - BIO_printf(err, "unable to load %s\n", key_descrip); - ERR_print_errors(err); + BIO_printf(bio_err, "unable to load %s\n", key_descrip); + ERR_print_errors(bio_err); } - return (pkey); + return pkey; } -EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, +EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *key_descrip) { BIO *key = NULL; @@ -1054,132 +788,83 @@ EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, cb_data.prompt_info = file; if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { - BIO_printf(err, "no keyfile specified\n"); + BIO_printf(bio_err, "no keyfile specified\n"); goto end; } -#ifndef OPENSSL_NO_ENGINE if (format == FORMAT_ENGINE) { - if (!e) + if (e == NULL) { BIO_printf(bio_err, "no engine specified\n"); - else + } else { +#ifndef OPENSSL_NO_ENGINE pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data); - goto end; - } + if (pkey == NULL) { + BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); + ERR_print_errors(bio_err); + } +#else + BIO_printf(bio_err, "engines not supported\n"); #endif - key = BIO_new(BIO_s_file()); - if (key == NULL) { - ERR_print_errors(err); + } goto end; } if (file == NULL && maybe_stdin) { -#ifdef _IONBF -# ifndef OPENSSL_NO_SETVBUF_IONBF - setvbuf(stdin, NULL, _IONBF, 0); -# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ -#endif - BIO_set_fp(key, stdin, BIO_NOCLOSE); - } else if (BIO_read_filename(key, file) <= 0) { - BIO_printf(err, "Error opening %s %s\n", key_descrip, file); - ERR_print_errors(err); - goto end; + unbuffer(stdin); + key = dup_bio_in(format); + } else { + key = bio_open_default(file, 'r', format); } + if (key == NULL) + goto end; if (format == FORMAT_ASN1) { pkey = d2i_PUBKEY_bio(key, NULL); - } + } else if (format == FORMAT_ASN1RSA) { #ifndef OPENSSL_NO_RSA - else if (format == FORMAT_ASN1RSA) { RSA *rsa; rsa = d2i_RSAPublicKey_bio(key, NULL); if (rsa) { pkey = EVP_PKEY_new(); - if (pkey) + if (pkey != NULL) EVP_PKEY_set1_RSA(pkey, rsa); RSA_free(rsa); } else +#else + BIO_printf(bio_err, "RSA keys not supported\n"); +#endif pkey = NULL; } else if (format == FORMAT_PEMRSA) { +#ifndef OPENSSL_NO_RSA RSA *rsa; rsa = PEM_read_bio_RSAPublicKey(key, NULL, (pem_password_cb *)password_callback, &cb_data); - if (rsa) { + if (rsa != NULL) { pkey = EVP_PKEY_new(); - if (pkey) + if (pkey != NULL) EVP_PKEY_set1_RSA(pkey, rsa); RSA_free(rsa); } else - pkey = NULL; - } +#else + BIO_printf(bio_err, "RSA keys not supported\n"); #endif - else if (format == FORMAT_PEM) { + pkey = NULL; + } else if (format == FORMAT_PEM) { pkey = PEM_read_bio_PUBKEY(key, NULL, (pem_password_cb *)password_callback, &cb_data); - } -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) - else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC) - pkey = load_netscape_key(err, key, file, key_descrip, format); -#endif #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) - else if (format == FORMAT_MSBLOB) + } else if (format == FORMAT_MSBLOB) { pkey = b2i_PublicKey_bio(key); #endif - else { - BIO_printf(err, "bad input format specified for key file\n"); - goto end; } end: - if (key != NULL) - BIO_free(key); + BIO_free(key); if (pkey == NULL) - BIO_printf(err, "unable to load %s\n", key_descrip); - return (pkey); -} - -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) -static EVP_PKEY *load_netscape_key(BIO *err, BIO *key, const char *file, - const char *key_descrip, int format) -{ - EVP_PKEY *pkey; - BUF_MEM *buf; - RSA *rsa; - const unsigned char *p; - int size, i; - - buf = BUF_MEM_new(); - pkey = EVP_PKEY_new(); - size = 0; - if (buf == NULL || pkey == NULL) - goto error; - for (;;) { - if (!BUF_MEM_grow_clean(buf, size + 1024 * 10)) - goto error; - i = BIO_read(key, &(buf->data[size]), 1024 * 10); - size += i; - if (i == 0) - break; - if (i < 0) { - BIO_printf(err, "Error reading %s %s", key_descrip, file); - goto error; - } - } - p = (unsigned char *)buf->data; - rsa = d2i_RSA_NET(NULL, &p, (long)size, NULL, - (format == FORMAT_IISSGC ? 1 : 0)); - if (rsa == NULL) - goto error; - BUF_MEM_free(buf); - EVP_PKEY_set1_RSA(pkey, rsa); + BIO_printf(bio_err, "unable to load %s\n", key_descrip); return pkey; - error: - BUF_MEM_free(buf); - EVP_PKEY_free(pkey); - return NULL; } -#endif /* ndef OPENSSL_NO_RC4 */ -static int load_certs_crls(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, const char *desc, +static int load_certs_crls(const char *file, int format, + const char *pass, const char *desc, STACK_OF(X509) **pcerts, STACK_OF(X509_CRL) **pcrls) { @@ -1194,20 +879,13 @@ static int load_certs_crls(BIO *err, const char *file, int format, cb_data.prompt_info = file; if (format != FORMAT_PEM) { - BIO_printf(err, "bad input format specified for %s\n", desc); + BIO_printf(bio_err, "bad input format specified for %s\n", desc); return 0; } - if (file == NULL) - bio = BIO_new_fp(stdin, BIO_NOCLOSE); - else - bio = BIO_new_file(file, "r"); - - if (bio == NULL) { - BIO_printf(err, "Error opening %s %s\n", desc, file ? file : "stdin"); - ERR_print_errors(err); + bio = bio_open_default(file, 'r', FORMAT_PEM); + if (bio == NULL) return 0; - } xis = PEM_X509_INFO_read_bio(bio, NULL, (pem_password_cb *)password_callback, @@ -1215,75 +893,87 @@ static int load_certs_crls(BIO *err, const char *file, int format, BIO_free(bio); - if (pcerts) { + if (pcerts != NULL && *pcerts == NULL) { *pcerts = sk_X509_new_null(); - if (!*pcerts) + if (*pcerts == NULL) goto end; } - if (pcrls) { + if (pcrls != NULL && *pcrls == NULL) { *pcrls = sk_X509_CRL_new_null(); - if (!*pcrls) + if (*pcrls == NULL) goto end; } for (i = 0; i < sk_X509_INFO_num(xis); i++) { xi = sk_X509_INFO_value(xis, i); - if (xi->x509 && pcerts) { + if (xi->x509 != NULL && pcerts != NULL) { if (!sk_X509_push(*pcerts, xi->x509)) goto end; xi->x509 = NULL; } - if (xi->crl && pcrls) { + if (xi->crl != NULL && pcrls != NULL) { if (!sk_X509_CRL_push(*pcrls, xi->crl)) goto end; xi->crl = NULL; } } - if (pcerts && sk_X509_num(*pcerts) > 0) + if (pcerts != NULL && sk_X509_num(*pcerts) > 0) rv = 1; - if (pcrls && sk_X509_CRL_num(*pcrls) > 0) + if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0) rv = 1; end: - if (xis) - sk_X509_INFO_pop_free(xis, X509_INFO_free); + sk_X509_INFO_pop_free(xis, X509_INFO_free); if (rv == 0) { - if (pcerts) { + if (pcerts != NULL) { sk_X509_pop_free(*pcerts, X509_free); *pcerts = NULL; } - if (pcrls) { + if (pcrls != NULL) { sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); *pcrls = NULL; } - BIO_printf(err, "unable to load %s\n", + BIO_printf(bio_err, "unable to load %s\n", pcerts ? "certificates" : "CRLs"); - ERR_print_errors(err); + ERR_print_errors(bio_err); } return rv; } -STACK_OF(X509) *load_certs(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, const char *desc) +void* app_malloc(int sz, const char *what) { - STACK_OF(X509) *certs; - if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL)) - return NULL; - return certs; + void *vp = OPENSSL_malloc(sz); + + if (vp == NULL) { + BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n", + opt_getprog(), sz, what); + ERR_print_errors(bio_err); + exit(1); + } + return vp; +} + +/* + * Initialize or extend, if *certs != NULL, a certificate stack. + */ +int load_certs(const char *file, STACK_OF(X509) **certs, int format, + const char *pass, const char *desc) +{ + return load_certs_crls(file, format, pass, desc, certs, NULL); } -STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, const char *desc) +/* + * Initialize or extend, if *crls != NULL, a certificate stack. + */ +int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, + const char *pass, const char *desc) { - STACK_OF(X509_CRL) *crls; - if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls)) - return NULL; - return crls; + return load_certs_crls(file, format, pass, desc, NULL, crls); } #define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) @@ -1329,6 +1019,7 @@ int set_name_ex(unsigned long *flags, const char *arg) { static const NAME_EX_TBL ex_tbl[] = { {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, + {"esc_2254", ASN1_STRFLGS_ESC_2254, 0}, {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, @@ -1359,18 +1050,19 @@ int set_name_ex(unsigned long *flags, const char *arg) }; if (set_multi_opts(flags, arg, ex_tbl) == 0) return 0; - if ((*flags & XN_FLAG_SEP_MASK) == 0) + if (*flags != XN_FLAG_COMPAT + && (*flags & XN_FLAG_SEP_MASK) == 0) *flags |= XN_FLAG_SEP_CPLUS_SPC; return 1; } int set_ext_copy(int *copy_type, const char *arg) { - if (!strcasecmp(arg, "none")) + if (strcasecmp(arg, "none") == 0) *copy_type = EXT_COPY_NONE; - else if (!strcasecmp(arg, "copy")) + else if (strcasecmp(arg, "copy") == 0) *copy_type = EXT_COPY_ADD; - else if (!strcasecmp(arg, "copyall")) + else if (strcasecmp(arg, "copyall") == 0) *copy_type = EXT_COPY_ALL; else return 0; @@ -1448,11 +1140,12 @@ static int set_table_opts(unsigned long *flags, const char *arg, } else if (c == '+') { c = 1; arg++; - } else + } else { c = 1; + } for (ptbl = in_tbl; ptbl->name; ptbl++) { - if (!strcasecmp(arg, ptbl->name)) { + if (strcasecmp(arg, ptbl->name) == 0) { *flags &= ~ptbl->mask; if (c) *flags |= ptbl->flag; @@ -1490,33 +1183,78 @@ void print_name(BIO *out, const char *title, X509_NAME *nm, } } -X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath) +void print_bignum_var(BIO *out, const BIGNUM *in, const char *var, + int len, unsigned char *buffer) +{ + BIO_printf(out, " static unsigned char %s_%d[] = {", var, len); + if (BN_is_zero(in)) { + BIO_printf(out, "\n 0x00"); + } else { + int i, l; + + l = BN_bn2bin(in, buffer); + for (i = 0; i < l; i++) { + BIO_printf(out, (i % 10) == 0 ? "\n " : " "); + if (i < l - 1) + BIO_printf(out, "0x%02X,", buffer[i]); + else + BIO_printf(out, "0x%02X", buffer[i]); + } + } + BIO_printf(out, "\n };\n"); +} + +void print_array(BIO *out, const char* title, int len, const unsigned char* d) +{ + int i; + + BIO_printf(out, "unsigned char %s[%d] = {", title, len); + for (i = 0; i < len; i++) { + if ((i % 10) == 0) + BIO_printf(out, "\n "); + if (i < len - 1) + BIO_printf(out, "0x%02X, ", d[i]); + else + BIO_printf(out, "0x%02X", d[i]); + } + BIO_printf(out, "\n};\n"); +} + +X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath) { - X509_STORE *store; + X509_STORE *store = X509_STORE_new(); X509_LOOKUP *lookup; - if (!(store = X509_STORE_new())) - goto end; - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - if (lookup == NULL) + + if (store == NULL) goto end; - if (CAfile) { - if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { - BIO_printf(bp, "Error loading file %s\n", CAfile); + + if (CAfile != NULL || !noCAfile) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) goto end; + if (CAfile) { + if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { + BIO_printf(bio_err, "Error loading file %s\n", CAfile); + goto end; + } + } else { + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); } - } else - X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + } - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); - if (lookup == NULL) - goto end; - if (CApath) { - if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { - BIO_printf(bp, "Error loading directory %s\n", CApath); + if (CApath != NULL || !noCApath) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) goto end; + if (CApath) { + if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { + BIO_printf(bio_err, "Error loading directory %s\n", CApath); + goto end; + } + } else { + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); } - } else - X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + } ERR_clear_error(); return store; @@ -1527,7 +1265,7 @@ X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath) #ifndef OPENSSL_NO_ENGINE /* Try to load an engine in a shareable library */ -static ENGINE *try_load_engine(BIO *err, const char *engine, int debug) +static ENGINE *try_load_engine(const char *engine) { ENGINE *e = ENGINE_by_id("dynamic"); if (e) { @@ -1541,35 +1279,35 @@ static ENGINE *try_load_engine(BIO *err, const char *engine, int debug) } #endif -ENGINE *setup_engine(BIO *err, const char *engine, int debug) +ENGINE *setup_engine(const char *engine, int debug) { ENGINE *e = NULL; #ifndef OPENSSL_NO_ENGINE - if (engine) { + if (engine != NULL) { if (strcmp(engine, "auto") == 0) { - BIO_printf(err, "enabling auto ENGINE support\n"); + BIO_printf(bio_err, "enabling auto ENGINE support\n"); ENGINE_register_all_complete(); return NULL; } if ((e = ENGINE_by_id(engine)) == NULL - && (e = try_load_engine(err, engine, debug)) == NULL) { - BIO_printf(err, "invalid engine \"%s\"\n", engine); - ERR_print_errors(err); + && (e = try_load_engine(engine)) == NULL) { + BIO_printf(bio_err, "invalid engine \"%s\"\n", engine); + ERR_print_errors(bio_err); return NULL; } if (debug) { - ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, err, 0); + ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0); } ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1); if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { - BIO_printf(err, "can't use that engine\n"); - ERR_print_errors(err); + BIO_printf(bio_err, "can't use that engine\n"); + ERR_print_errors(bio_err); ENGINE_free(e); return NULL; } - BIO_printf(err, "engine \"%s\" set.\n", ENGINE_get_id(e)); + BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e)); } #endif return e; @@ -1584,46 +1322,6 @@ void release_engine(ENGINE *e) #endif } -int load_config(BIO *err, CONF *cnf) -{ - static int load_config_called = 0; - if (load_config_called) - return 1; - load_config_called = 1; - if (!cnf) - cnf = config; - if (!cnf) - return 1; - - OPENSSL_load_builtin_modules(); - - if (CONF_modules_load(cnf, NULL, 0) <= 0) { - BIO_printf(err, "Error configuring OpenSSL\n"); - ERR_print_errors(err); - return 0; - } - return 1; -} - -char *make_config_name() -{ - const char *t = X509_get_default_cert_area(); - size_t len; - char *p; - - len = strlen(t) + strlen(OPENSSL_CONF) + 2; - p = OPENSSL_malloc(len); - if (p == NULL) - return NULL; - BUF_strlcpy(p, t, len); -#ifndef OPENSSL_SYS_VMS - BUF_strlcat(p, "/", len); -#endif - BUF_strlcat(p, OPENSSL_CONF, len); - - return p; -} - static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) { const char *n; @@ -1631,7 +1329,7 @@ static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) n = a[DB_serial]; while (*n == '0') n++; - return (lh_strhash(n)); + return OPENSSL_LH_strhash(n); } static int index_serial_cmp(const OPENSSL_CSTRING *a, @@ -1641,7 +1339,7 @@ static int index_serial_cmp(const OPENSSL_CSTRING *a, for (aa = a[DB_serial]; *aa == '0'; aa++) ; for (bb = b[DB_serial]; *bb == '0'; bb++) ; - return (strcmp(aa, bb)); + return strcmp(aa, bb); } static int index_name_qual(char **a) @@ -1651,12 +1349,12 @@ static int index_name_qual(char **a) static unsigned long index_name_hash(const OPENSSL_CSTRING *a) { - return (lh_strhash(a[DB_name])); + return OPENSSL_LH_strhash(a[DB_name]); } int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) { - return (strcmp(a[DB_name], b[DB_name])); + return strcmp(a[DB_name], b[DB_name]); } static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) @@ -1665,31 +1363,27 @@ static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) #undef BSIZE #define BSIZE 256 -BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai) +BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai) { BIO *in = NULL; BIGNUM *ret = NULL; - MS_STATIC char buf[1024]; + char buf[1024]; ASN1_INTEGER *ai = NULL; ai = ASN1_INTEGER_new(); if (ai == NULL) goto err; - if ((in = BIO_new(BIO_s_file())) == NULL) { - ERR_print_errors(bio_err); - goto err; - } - - if (BIO_read_filename(in, serialfile) <= 0) { + in = BIO_new_file(serialfile, "r"); + if (in == NULL) { if (!create) { perror(serialfile); goto err; - } else { - ret = BN_new(); - if (ret == NULL || !rand_serial(ret, ai)) - BIO_printf(bio_err, "Out of memory\n"); } + ERR_clear_error(); + ret = BN_new(); + if (ret == NULL || !rand_serial(ret, ai)) + BIO_printf(bio_err, "Out of memory\n"); } else { if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { BIO_printf(bio_err, "unable to load number from %s\n", @@ -1709,14 +1403,12 @@ BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai) ai = NULL; } err: - if (in != NULL) - BIO_free(in); - if (ai != NULL) - ASN1_INTEGER_free(ai); - return (ret); + BIO_free(in); + ASN1_INTEGER_free(ai); + return ret; } -int save_serial(char *serialfile, char *suffix, BIGNUM *serial, +int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, ASN1_INTEGER **retai) { char buf[1][BSIZE]; @@ -1735,7 +1427,7 @@ int save_serial(char *serialfile, char *suffix, BIGNUM *serial, } if (suffix == NULL) - BUF_strlcpy(buf[0], serialfile, BSIZE); + OPENSSL_strlcpy(buf[0], serialfile, BSIZE); else { #ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); @@ -1743,18 +1435,11 @@ int save_serial(char *serialfile, char *suffix, BIGNUM *serial, j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); #endif } -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]); -#endif - out = BIO_new(BIO_s_file()); + out = BIO_new_file(buf[0], "w"); if (out == NULL) { ERR_print_errors(bio_err); goto err; } - if (BIO_write_filename(out, buf[0]) <= 0) { - perror(serialfile); - goto err; - } if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { BIO_printf(bio_err, "error converting serial to ASN.1 format\n"); @@ -1768,16 +1453,15 @@ int save_serial(char *serialfile, char *suffix, BIGNUM *serial, ai = NULL; } err: - if (out != NULL) - BIO_free_all(out); - if (ai != NULL) - ASN1_INTEGER_free(ai); - return (ret); + BIO_free_all(out); + ASN1_INTEGER_free(ai); + return ret; } -int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix) +int rotate_serial(const char *serialfile, const char *new_suffix, + const char *old_suffix) { - char buf[5][BSIZE]; + char buf[2][BSIZE]; int i, j; i = strlen(serialfile) + strlen(old_suffix); @@ -1790,18 +1474,11 @@ int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix) } #ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix); -#else - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); -#endif -#ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix); #else + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix); #endif -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", - serialfile, buf[1]); -#endif if (rename(serialfile, buf[1]) < 0 && errno != ENOENT #ifdef ENOTDIR && errno != ENOTDIR @@ -1812,10 +1489,6 @@ int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix) perror("reason"); goto err; } -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", - buf[0], serialfile); -#endif if (rename(buf[0], serialfile) < 0) { BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], serialfile); @@ -1832,15 +1505,12 @@ int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) { BIGNUM *btmp; int ret = 0; - if (b) - btmp = b; - else - btmp = BN_new(); - if (!btmp) + btmp = b == NULL ? BN_new() : b; + if (btmp == NULL) return 0; - if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) goto error; if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) goto error; @@ -1849,56 +1519,51 @@ int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) error: - if (!b) + if (btmp != b) BN_free(btmp); return ret; } -CA_DB *load_index(char *dbfile, DB_ATTR *db_attr) +CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) { CA_DB *retdb = NULL; TXT_DB *tmpdb = NULL; - BIO *in = BIO_new(BIO_s_file()); + BIO *in; CONF *dbattr_conf = NULL; - char buf[1][BSIZE]; - long errorline = -1; + char buf[BSIZE]; +#ifndef OPENSSL_NO_POSIX_IO + FILE *dbfp; + struct stat dbst; +#endif + in = BIO_new_file(dbfile, "r"); if (in == NULL) { ERR_print_errors(bio_err); goto err; } - if (BIO_read_filename(in, dbfile) <= 0) { - perror(dbfile); - BIO_printf(bio_err, "unable to open '%s'\n", dbfile); + +#ifndef OPENSSL_NO_POSIX_IO + BIO_get_fp(in, &dbfp); + if (fstat(fileno(dbfp), &dbst) == -1) { + SYSerr(SYS_F_FSTAT, errno); + ERR_add_error_data(3, "fstat('", dbfile, "')"); + ERR_print_errors(bio_err); goto err; } +#endif + if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) goto err; #ifndef OPENSSL_SYS_VMS - BIO_snprintf(buf[0], sizeof(buf[0]), "%s.attr", dbfile); + BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile); #else - BIO_snprintf(buf[0], sizeof(buf[0]), "%s-attr", dbfile); + BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile); #endif - dbattr_conf = NCONF_new(NULL); - if (NCONF_load(dbattr_conf, buf[0], &errorline) <= 0) { - if (errorline > 0) { - BIO_printf(bio_err, - "error on line %ld of db attribute file '%s'\n", - errorline, buf[0]); - goto err; - } else { - NCONF_free(dbattr_conf); - dbattr_conf = NULL; - } - } - - if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL) { - fprintf(stderr, "Out of memory\n"); - goto err; - } + dbattr_conf = app_load_config(buf); + retdb = app_malloc(sizeof(*retdb), "new DB"); retdb->db = tmpdb; tmpdb = NULL; if (db_attr) @@ -1910,24 +1575,25 @@ CA_DB *load_index(char *dbfile, DB_ATTR *db_attr) if (dbattr_conf) { char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); if (p) { -#ifdef RL_DEBUG - BIO_printf(bio_err, - "DEBUG[load_index]: unique_subject = \"%s\"\n", p); -#endif retdb->attributes.unique_subject = parse_yesno(p, 1); } } + retdb->dbfname = OPENSSL_strdup(dbfile); +#ifndef OPENSSL_NO_POSIX_IO + retdb->dbst = dbst; +#endif + err: - if (dbattr_conf) - NCONF_free(dbattr_conf); - if (tmpdb) - TXT_DB_free(tmpdb); - if (in) - BIO_free_all(in); + NCONF_free(dbattr_conf); + TXT_DB_free(tmpdb); + BIO_free_all(in); return retdb; } +/* + * Returns > 0 on success, <= 0 on error + */ int index_index(CA_DB *db) { if (!TXT_DB_create_index(db->db, DB_serial, NULL, @@ -1953,14 +1619,9 @@ int index_index(CA_DB *db) int save_index(const char *dbfile, const char *suffix, CA_DB *db) { char buf[3][BSIZE]; - BIO *out = BIO_new(BIO_s_file()); + BIO *out; int j; - if (out == NULL) { - ERR_print_errors(bio_err); - goto err; - } - j = strlen(dbfile) + strlen(suffix); if (j + 6 >= BSIZE) { BIO_printf(bio_err, "file name too long\n"); @@ -1968,38 +1629,26 @@ int save_index(const char *dbfile, const char *suffix, CA_DB *db) } #ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile); -#else - j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); -#endif -#ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix); -#else - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); -#endif -#ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix); #else + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix); #endif -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]); -#endif - if (BIO_write_filename(out, buf[0]) <= 0) { + out = BIO_new_file(buf[0], "w"); + if (out == NULL) { perror(dbfile); BIO_printf(bio_err, "unable to open '%s'\n", dbfile); goto err; } j = TXT_DB_write(out, db->db); + BIO_free(out); if (j <= 0) goto err; - BIO_free(out); - - out = BIO_new(BIO_s_file()); -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]); -#endif - if (BIO_write_filename(out, buf[1]) <= 0) { + out = BIO_new_file(buf[1], "w"); + if (out == NULL) { perror(buf[2]); BIO_printf(bio_err, "unable to open '%s'\n", buf[2]); goto err; @@ -2029,31 +1678,16 @@ int rotate_index(const char *dbfile, const char *new_suffix, } #ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile); -#else - j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); -#endif -#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix); -#else - j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); -#endif -#ifndef OPENSSL_SYS_VMS - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix); -#else - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); -#endif -#ifndef OPENSSL_SYS_VMS j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix); #else - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); -#endif -#ifndef OPENSSL_SYS_VMS - j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); -#else + j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix); -#endif -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", dbfile, buf[1]); + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); #endif if (rename(dbfile, buf[1]) < 0 && errno != ENOENT #ifdef ENOTDIR @@ -2064,18 +1698,12 @@ int rotate_index(const char *dbfile, const char *new_suffix, perror("reason"); goto err; } -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[0], dbfile); -#endif if (rename(buf[0], dbfile) < 0) { BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile); perror("reason"); rename(buf[1], dbfile); goto err; } -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[4], buf[3]); -#endif if (rename(buf[4], buf[3]) < 0 && errno != ENOENT #ifdef ENOTDIR && errno != ENOTDIR @@ -2087,9 +1715,6 @@ int rotate_index(const char *dbfile, const char *new_suffix, rename(buf[1], dbfile); goto err; } -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", buf[2], buf[4]); -#endif if (rename(buf[2], buf[4]) < 0) { BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]); perror("reason"); @@ -2106,15 +1731,14 @@ int rotate_index(const char *dbfile, const char *new_suffix, void free_index(CA_DB *db) { if (db) { - if (db->db) - TXT_DB_free(db->db); + TXT_DB_free(db->db); + OPENSSL_free(db->dbfname); OPENSSL_free(db); } } int parse_yesno(const char *str, int def) { - int ret = def; if (str) { switch (*str) { case 'f': /* false */ @@ -2122,325 +1746,106 @@ int parse_yesno(const char *str, int def) case 'n': /* no */ case 'N': /* NO */ case '0': /* 0 */ - ret = 0; - break; + return 0; case 't': /* true */ case 'T': /* TRUE */ case 'y': /* yes */ case 'Y': /* YES */ case '1': /* 1 */ - ret = 1; - break; - default: - ret = def; - break; + return 1; } } - return ret; + return def; } /* - * subject is expected to be in the format /type0=value0/type1=value1/type2=... + * name is expected to be in the format /type0=value0/type1=value1/type2=... * where characters may be escaped by \ */ -X509_NAME *parse_name(char *subject, long chtype, int multirdn) +X509_NAME *parse_name(const char *cp, long chtype, int canmulti) { - size_t buflen = strlen(subject) + 1; /* to copy the types and values - * into. due to escaping, the copy - * can only become shorter */ - char *buf = OPENSSL_malloc(buflen); - size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ - char **ne_types = OPENSSL_malloc(max_ne * sizeof(char *)); - char **ne_values = OPENSSL_malloc(max_ne * sizeof(char *)); - int *mval = OPENSSL_malloc(max_ne * sizeof(int)); - - char *sp = subject, *bp = buf; - int i, ne_num = 0; + int nextismulti = 0; + char *work; + X509_NAME *n; - X509_NAME *n = NULL; - int nid; - - if (!buf || !ne_types || !ne_values || !mval) { - BIO_printf(bio_err, "malloc error\n"); - goto error; + if (*cp++ != '/') { + BIO_printf(bio_err, + "name is expected to be in the format " + "/type0=value0/type1=value1/type2=... where characters may " + "be escaped by \\. This name is not in that format: '%s'\n", + --cp); + return NULL; } - if (*subject != '/') { - BIO_printf(bio_err, "Subject does not start with '/'.\n"); - goto error; - } - sp++; /* skip leading / */ + n = X509_NAME_new(); + if (n == NULL) + return NULL; + work = OPENSSL_strdup(cp); + if (work == NULL) + goto err; - /* no multivalued RDN by default */ - mval[ne_num] = 0; + while (*cp) { + char *bp = work; + char *typestr = bp; + unsigned char *valstr; + int nid; + int ismulti = nextismulti; + nextismulti = 0; - while (*sp) { - /* collect type */ - ne_types[ne_num] = bp; - while (*sp) { - if (*sp == '\\') { /* is there anything to escape in the - * type...? */ - if (*++sp) - *bp++ = *sp++; - else { - BIO_printf(bio_err, - "escape character at end of string\n"); - goto error; - } - } else if (*sp == '=') { - sp++; - *bp++ = '\0'; - break; - } else - *bp++ = *sp++; - } - if (!*sp) { + /* Collect the type */ + while (*cp && *cp != '=') + *bp++ = *cp++; + if (*cp == '\0') { BIO_printf(bio_err, - "end of string encountered while processing type of subject name element #%d\n", - ne_num); - goto error; + "%s: Hit end of string before finding the equals.\n", + opt_getprog()); + goto err; } - ne_values[ne_num] = bp; - while (*sp) { - if (*sp == '\\') { - if (*++sp) - *bp++ = *sp++; - else { - BIO_printf(bio_err, - "escape character at end of string\n"); - goto error; - } - } else if (*sp == '/') { - sp++; - /* no multivalued RDN by default */ - mval[ne_num + 1] = 0; - break; - } else if (*sp == '+' && multirdn) { - /* - * a not escaped + signals a mutlivalued RDN - */ - sp++; - mval[ne_num + 1] = -1; + *bp++ = '\0'; + ++cp; + + /* Collect the value. */ + valstr = (unsigned char *)bp; + for (; *cp && *cp != '/'; *bp++ = *cp++) { + if (canmulti && *cp == '+') { + nextismulti = 1; break; - } else - *bp++ = *sp++; + } + if (*cp == '\\' && *++cp == '\0') { + BIO_printf(bio_err, + "%s: escape character at end of string\n", + opt_getprog()); + goto err; + } } *bp++ = '\0'; - ne_num++; - } - if (!(n = X509_NAME_new())) - goto error; + /* If not at EOS (must be + or /), move forward. */ + if (*cp) + ++cp; - for (i = 0; i < ne_num; i++) { - if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) { - BIO_printf(bio_err, - "Subject Attribute %s has no known NID, skipped\n", - ne_types[i]); + /* Parse */ + nid = OBJ_txt2nid(typestr); + if (nid == NID_undef) { + BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n", + opt_getprog(), typestr); continue; } - - if (!*ne_values[i]) { - BIO_printf(bio_err, - "No value provided for Subject Attribute %s, skipped\n", - ne_types[i]); - continue; - } - - if (!X509_NAME_add_entry_by_NID - (n, nid, chtype, (unsigned char *)ne_values[i], -1, -1, mval[i])) - goto error; + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, + valstr, strlen((char *)valstr), + -1, ismulti ? -1 : 0)) + goto err; } - OPENSSL_free(ne_values); - OPENSSL_free(ne_types); - OPENSSL_free(buf); - OPENSSL_free(mval); + OPENSSL_free(work); return n; - error: + err: X509_NAME_free(n); - if (ne_values) - OPENSSL_free(ne_values); - if (ne_types) - OPENSSL_free(ne_types); - if (mval) - OPENSSL_free(mval); - if (buf) - OPENSSL_free(buf); + OPENSSL_free(work); return NULL; } -int args_verify(char ***pargs, int *pargc, - int *badarg, BIO *err, X509_VERIFY_PARAM **pm) -{ - ASN1_OBJECT *otmp = NULL; - unsigned long flags = 0; - int i; - int purpose = 0, depth = -1; - char **oldargs = *pargs; - char *arg = **pargs, *argn = (*pargs)[1]; - time_t at_time = 0; - char *hostname = NULL; - char *email = NULL; - char *ipasc = NULL; - if (!strcmp(arg, "-policy")) { - if (!argn) - *badarg = 1; - else { - otmp = OBJ_txt2obj(argn, 0); - if (!otmp) { - BIO_printf(err, "Invalid Policy \"%s\"\n", argn); - *badarg = 1; - } - } - (*pargs)++; - } else if (strcmp(arg, "-purpose") == 0) { - X509_PURPOSE *xptmp; - if (!argn) - *badarg = 1; - else { - i = X509_PURPOSE_get_by_sname(argn); - if (i < 0) { - BIO_printf(err, "unrecognized purpose\n"); - *badarg = 1; - } else { - xptmp = X509_PURPOSE_get0(i); - purpose = X509_PURPOSE_get_id(xptmp); - } - } - (*pargs)++; - } else if (strcmp(arg, "-verify_depth") == 0) { - if (!argn) - *badarg = 1; - else { - depth = atoi(argn); - if (depth < 0) { - BIO_printf(err, "invalid depth\n"); - *badarg = 1; - } - } - (*pargs)++; - } else if (strcmp(arg, "-attime") == 0) { - if (!argn) - *badarg = 1; - else { - long timestamp; - /* - * interpret the -attime argument as seconds since Epoch - */ - if (sscanf(argn, "%li", ×tamp) != 1) { - BIO_printf(bio_err, "Error parsing timestamp %s\n", argn); - *badarg = 1; - } - /* on some platforms time_t may be a float */ - at_time = (time_t)timestamp; - } - (*pargs)++; - } else if (strcmp(arg, "-verify_hostname") == 0) { - if (!argn) - *badarg = 1; - hostname = argn; - (*pargs)++; - } else if (strcmp(arg, "-verify_email") == 0) { - if (!argn) - *badarg = 1; - email = argn; - (*pargs)++; - } else if (strcmp(arg, "-verify_ip") == 0) { - if (!argn) - *badarg = 1; - ipasc = argn; - (*pargs)++; - } else if (!strcmp(arg, "-ignore_critical")) - flags |= X509_V_FLAG_IGNORE_CRITICAL; - else if (!strcmp(arg, "-issuer_checks")) - flags |= X509_V_FLAG_CB_ISSUER_CHECK; - else if (!strcmp(arg, "-crl_check")) - flags |= X509_V_FLAG_CRL_CHECK; - else if (!strcmp(arg, "-crl_check_all")) - flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; - else if (!strcmp(arg, "-policy_check")) - flags |= X509_V_FLAG_POLICY_CHECK; - else if (!strcmp(arg, "-explicit_policy")) - flags |= X509_V_FLAG_EXPLICIT_POLICY; - else if (!strcmp(arg, "-inhibit_any")) - flags |= X509_V_FLAG_INHIBIT_ANY; - else if (!strcmp(arg, "-inhibit_map")) - flags |= X509_V_FLAG_INHIBIT_MAP; - else if (!strcmp(arg, "-x509_strict")) - flags |= X509_V_FLAG_X509_STRICT; - else if (!strcmp(arg, "-extended_crl")) - flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT; - else if (!strcmp(arg, "-use_deltas")) - flags |= X509_V_FLAG_USE_DELTAS; - else if (!strcmp(arg, "-policy_print")) - flags |= X509_V_FLAG_NOTIFY_POLICY; - else if (!strcmp(arg, "-check_ss_sig")) - flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; - else if (!strcmp(arg, "-trusted_first")) - flags |= X509_V_FLAG_TRUSTED_FIRST; - else if (!strcmp(arg, "-suiteB_128_only")) - flags |= X509_V_FLAG_SUITEB_128_LOS_ONLY; - else if (!strcmp(arg, "-suiteB_128")) - flags |= X509_V_FLAG_SUITEB_128_LOS; - else if (!strcmp(arg, "-suiteB_192")) - flags |= X509_V_FLAG_SUITEB_192_LOS; - else if (!strcmp(arg, "-partial_chain")) - flags |= X509_V_FLAG_PARTIAL_CHAIN; - else if (!strcmp(arg, "-no_alt_chains")) - flags |= X509_V_FLAG_NO_ALT_CHAINS; - else if (!strcmp(arg, "-allow_proxy_certs")) - flags |= X509_V_FLAG_ALLOW_PROXY_CERTS; - else - return 0; - - if (*badarg) { - if (*pm) - X509_VERIFY_PARAM_free(*pm); - *pm = NULL; - goto end; - } - - if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) { - *badarg = 1; - goto end; - } - - if (otmp) - X509_VERIFY_PARAM_add0_policy(*pm, otmp); - if (flags) - X509_VERIFY_PARAM_set_flags(*pm, flags); - - if (purpose) - X509_VERIFY_PARAM_set_purpose(*pm, purpose); - - if (depth >= 0) - X509_VERIFY_PARAM_set_depth(*pm, depth); - - if (at_time) - X509_VERIFY_PARAM_set_time(*pm, at_time); - - if (hostname && !X509_VERIFY_PARAM_set1_host(*pm, hostname, 0)) - *badarg = 1; - - if (email && !X509_VERIFY_PARAM_set1_email(*pm, email, 0)) - *badarg = 1; - - if (ipasc && !X509_VERIFY_PARAM_set1_ip_asc(*pm, ipasc)) - *badarg = 1; - - end: - - (*pargs)++; - - if (pargc) - *pargc -= *pargs - oldargs; - - return 1; - -} - /* * Read whole contents of a BIO into an allocated memory buffer and return * it. @@ -2451,8 +1856,9 @@ int bio_to_mem(unsigned char **out, int maxlen, BIO *in) BIO *mem; int len, ret; unsigned char tbuf[1024]; + mem = BIO_new(BIO_s_mem()); - if (!mem) + if (mem == NULL) return -1; for (;;) { if ((maxlen != -1) && maxlen < 1024) @@ -2485,7 +1891,7 @@ int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) { int rv; char *stmp, *vtmp = NULL; - stmp = BUF_strdup(value); + stmp = OPENSSL_strdup(value); if (!stmp) return -1; vtmp = strchr(stmp, ':'); @@ -2498,281 +1904,47 @@ int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) return rv; } -static void nodes_print(BIO *out, const char *name, - STACK_OF(X509_POLICY_NODE) *nodes) +static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes) { X509_POLICY_NODE *node; int i; - BIO_printf(out, "%s Policies:", name); + + BIO_printf(bio_err, "%s Policies:", name); if (nodes) { - BIO_puts(out, "\n"); + BIO_puts(bio_err, "\n"); for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { node = sk_X509_POLICY_NODE_value(nodes, i); - X509_POLICY_NODE_print(out, node, 2); + X509_POLICY_NODE_print(bio_err, node, 2); } - } else - BIO_puts(out, " <empty>\n"); + } else { + BIO_puts(bio_err, " <empty>\n"); + } } -void policies_print(BIO *out, X509_STORE_CTX *ctx) +void policies_print(X509_STORE_CTX *ctx) { X509_POLICY_TREE *tree; int explicit_policy; - int free_out = 0; - if (out == NULL) { - out = BIO_new_fp(stderr, BIO_NOCLOSE); - free_out = 1; - } tree = X509_STORE_CTX_get0_policy_tree(ctx); explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); - BIO_printf(out, "Require explicit Policy: %s\n", + BIO_printf(bio_err, "Require explicit Policy: %s\n", explicit_policy ? "True" : "False"); - nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree)); - nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree)); - if (free_out) - BIO_free(out); -} - -#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) - -static JPAKE_CTX *jpake_init(const char *us, const char *them, - const char *secret) -{ - BIGNUM *p = NULL; - BIGNUM *g = NULL; - BIGNUM *q = NULL; - BIGNUM *bnsecret = BN_new(); - JPAKE_CTX *ctx; - - /* Use a safe prime for p (that we found earlier) */ - BN_hex2bn(&p, - "F9E5B365665EA7A05A9C534502780FEE6F1AB5BD4F49947FD036DBD7E905269AF46EF28B0FC07487EE4F5D20FB3C0AF8E700F3A2FA3414970CBED44FEDFF80CE78D800F184BB82435D137AADA2C6C16523247930A63B85661D1FC817A51ACD96168E95898A1F83A79FFB529368AA7833ABD1B0C3AEDDB14D2E1A2F71D99F763F"); - g = BN_new(); - BN_set_word(g, 2); - q = BN_new(); - BN_rshift1(q, p); - - BN_bin2bn((const unsigned char *)secret, strlen(secret), bnsecret); - - ctx = JPAKE_CTX_new(us, them, p, g, q, bnsecret); - BN_free(bnsecret); - BN_free(q); - BN_free(g); - BN_free(p); - - return ctx; -} - -static void jpake_send_part(BIO *conn, const JPAKE_STEP_PART *p) -{ - BN_print(conn, p->gx); - BIO_puts(conn, "\n"); - BN_print(conn, p->zkpx.gr); - BIO_puts(conn, "\n"); - BN_print(conn, p->zkpx.b); - BIO_puts(conn, "\n"); -} - -static void jpake_send_step1(BIO *bconn, JPAKE_CTX *ctx) -{ - JPAKE_STEP1 s1; - - JPAKE_STEP1_init(&s1); - JPAKE_STEP1_generate(&s1, ctx); - jpake_send_part(bconn, &s1.p1); - jpake_send_part(bconn, &s1.p2); - (void)BIO_flush(bconn); - JPAKE_STEP1_release(&s1); -} - -static void jpake_send_step2(BIO *bconn, JPAKE_CTX *ctx) -{ - JPAKE_STEP2 s2; - - JPAKE_STEP2_init(&s2); - JPAKE_STEP2_generate(&s2, ctx); - jpake_send_part(bconn, &s2); - (void)BIO_flush(bconn); - JPAKE_STEP2_release(&s2); -} - -static void jpake_send_step3a(BIO *bconn, JPAKE_CTX *ctx) -{ - JPAKE_STEP3A s3a; - - JPAKE_STEP3A_init(&s3a); - JPAKE_STEP3A_generate(&s3a, ctx); - BIO_write(bconn, s3a.hhk, sizeof(s3a.hhk)); - (void)BIO_flush(bconn); - JPAKE_STEP3A_release(&s3a); -} - -static void jpake_send_step3b(BIO *bconn, JPAKE_CTX *ctx) -{ - JPAKE_STEP3B s3b; - - JPAKE_STEP3B_init(&s3b); - JPAKE_STEP3B_generate(&s3b, ctx); - BIO_write(bconn, s3b.hk, sizeof(s3b.hk)); - (void)BIO_flush(bconn); - JPAKE_STEP3B_release(&s3b); -} - -static void readbn(BIGNUM **bn, BIO *bconn) -{ - char buf[10240]; - int l; - - l = BIO_gets(bconn, buf, sizeof(buf)); - assert(l > 0); - assert(buf[l - 1] == '\n'); - buf[l - 1] = '\0'; - BN_hex2bn(bn, buf); -} - -static void jpake_receive_part(JPAKE_STEP_PART *p, BIO *bconn) -{ - readbn(&p->gx, bconn); - readbn(&p->zkpx.gr, bconn); - readbn(&p->zkpx.b, bconn); -} - -static void jpake_receive_step1(JPAKE_CTX *ctx, BIO *bconn) -{ - JPAKE_STEP1 s1; - - JPAKE_STEP1_init(&s1); - jpake_receive_part(&s1.p1, bconn); - jpake_receive_part(&s1.p2, bconn); - if (!JPAKE_STEP1_process(ctx, &s1)) { - ERR_print_errors(bio_err); - exit(1); - } - JPAKE_STEP1_release(&s1); -} - -static void jpake_receive_step2(JPAKE_CTX *ctx, BIO *bconn) -{ - JPAKE_STEP2 s2; - - JPAKE_STEP2_init(&s2); - jpake_receive_part(&s2, bconn); - if (!JPAKE_STEP2_process(ctx, &s2)) { - ERR_print_errors(bio_err); - exit(1); - } - JPAKE_STEP2_release(&s2); + nodes_print("Authority", X509_policy_tree_get0_policies(tree)); + nodes_print("User", X509_policy_tree_get0_user_policies(tree)); } -static void jpake_receive_step3a(JPAKE_CTX *ctx, BIO *bconn) -{ - JPAKE_STEP3A s3a; - int l; - - JPAKE_STEP3A_init(&s3a); - l = BIO_read(bconn, s3a.hhk, sizeof(s3a.hhk)); - assert(l == sizeof(s3a.hhk)); - if (!JPAKE_STEP3A_process(ctx, &s3a)) { - ERR_print_errors(bio_err); - exit(1); - } - JPAKE_STEP3A_release(&s3a); -} - -static void jpake_receive_step3b(JPAKE_CTX *ctx, BIO *bconn) -{ - JPAKE_STEP3B s3b; - int l; - - JPAKE_STEP3B_init(&s3b); - l = BIO_read(bconn, s3b.hk, sizeof(s3b.hk)); - assert(l == sizeof(s3b.hk)); - if (!JPAKE_STEP3B_process(ctx, &s3b)) { - ERR_print_errors(bio_err); - exit(1); - } - JPAKE_STEP3B_release(&s3b); -} - -void jpake_client_auth(BIO *out, BIO *conn, const char *secret) -{ - JPAKE_CTX *ctx; - BIO *bconn; - - BIO_puts(out, "Authenticating with JPAKE\n"); - - ctx = jpake_init("client", "server", secret); - - bconn = BIO_new(BIO_f_buffer()); - BIO_push(bconn, conn); - - jpake_send_step1(bconn, ctx); - jpake_receive_step1(ctx, bconn); - jpake_send_step2(bconn, ctx); - jpake_receive_step2(ctx, bconn); - jpake_send_step3a(bconn, ctx); - jpake_receive_step3b(ctx, bconn); - - BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); - - if (psk_key) - OPENSSL_free(psk_key); - - psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); - - BIO_pop(bconn); - BIO_free(bconn); - - JPAKE_CTX_free(ctx); -} - -void jpake_server_auth(BIO *out, BIO *conn, const char *secret) -{ - JPAKE_CTX *ctx; - BIO *bconn; - - BIO_puts(out, "Authenticating with JPAKE\n"); - - ctx = jpake_init("server", "client", secret); - - bconn = BIO_new(BIO_f_buffer()); - BIO_push(bconn, conn); - - jpake_receive_step1(ctx, bconn); - jpake_send_step1(bconn, ctx); - jpake_receive_step2(ctx, bconn); - jpake_send_step2(bconn, ctx); - jpake_receive_step3a(ctx, bconn); - jpake_send_step3b(bconn, ctx); - - BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); - - if (psk_key) - OPENSSL_free(psk_key); - - psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); - - BIO_pop(bconn); - BIO_free(bconn); - - JPAKE_CTX_free(ctx); -} - -#endif - -#ifndef OPENSSL_NO_TLSEXT /*- * next_protos_parse parses a comma separated list of strings into a string * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. * outlen: (output) set to the length of the resulting buffer on success. * err: (maybe NULL) on failure, an error message line is written to this BIO. - * in: a NUL termianted string like "abc,def,ghi" + * in: a NUL terminated string like "abc,def,ghi" * - * returns: a malloced buffer or NULL on failure. + * returns: a malloc'd buffer or NULL on failure. */ -unsigned char *next_protos_parse(unsigned short *outlen, const char *in) +unsigned char *next_protos_parse(size_t *outlen, const char *in) { size_t len; unsigned char *out; @@ -2782,10 +1954,7 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in) if (len >= 65535) return NULL; - out = OPENSSL_malloc(strlen(in) + 1); - if (!out) - return NULL; - + out = app_malloc(strlen(in) + 1, "NPN buffer"); for (i = 0; i <= len; ++i) { if (i == len || in[i] == ',') { if (i - start > 255) { @@ -2794,14 +1963,14 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in) } out[start] = (unsigned char)(i - start); start = i + 1; - } else + } else { out[i + 1] = in[i]; + } } - *outlen = (unsigned char)(len + 1); + *outlen = len + 1; return out; } -#endif /* ndef OPENSSL_NO_TLSEXT */ void print_cert_checks(BIO *bio, X509 *x, const char *checkhost, @@ -2811,14 +1980,15 @@ void print_cert_checks(BIO *bio, X509 *x, return; if (checkhost) { BIO_printf(bio, "Hostname %s does%s match certificate\n", - checkhost, X509_check_host(x, checkhost, 0, 0, NULL) == 1 - ? "" : " NOT"); + checkhost, + X509_check_host(x, checkhost, 0, 0, NULL) == 1 + ? "" : " NOT"); } if (checkemail) { BIO_printf(bio, "Email %s does%s match certificate\n", - checkemail, X509_check_email(x, checkemail, 0, - 0) ? "" : " NOT"); + checkemail, X509_check_email(x, checkemail, 0, 0) + ? "" : " NOT"); } if (checkip) { @@ -2842,8 +2012,8 @@ static const char *get_dp_url(DIST_POINT *dp) gen = sk_GENERAL_NAME_value(gens, i); uri = GENERAL_NAME_get0_value(gen, >ype); if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) { - char *uptr = (char *)ASN1_STRING_data(uri); - if (!strncmp(uptr, "http://", 7)) + const char *uptr = (const char *)ASN1_STRING_get0_data(uri); + if (strncmp(uptr, "http://", 7) == 0) return uptr; } } @@ -2880,13 +2050,18 @@ static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm) STACK_OF(X509_CRL) *crls = NULL; X509_CRL *crl; STACK_OF(DIST_POINT) *crldp; + + crls = sk_X509_CRL_new_null(); + if (!crls) + return NULL; x = X509_STORE_CTX_get_current_cert(ctx); crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); crl = load_crl_crldp(crldp); sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); - if (!crl) + if (!crl) { + sk_X509_CRL_free(crls); return NULL; - crls = sk_X509_CRL_new_null(); + } sk_X509_CRL_push(crls, crl); /* Try to download delta CRL */ crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL); @@ -2926,7 +2101,7 @@ static int WIN32_rename(const char *from, const char *to) } else { /* UNICODE path */ size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; - tfrom = (TCHAR *)malloc(sizeof(TCHAR) * (flen + tlen)); + tfrom = malloc(sizeof(*tfrom) * (flen + tlen)); if (tfrom == NULL) goto err; tto = tfrom + flen; @@ -3013,32 +2188,8 @@ double app_tminterval(int stop, int usertime) ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7; } - return (ret); -} - -#elif defined(OPENSSL_SYS_NETWARE) -# include <time.h> - -double app_tminterval(int stop, int usertime) -{ - double ret = 0; - static clock_t tmstart; - static int warning = 1; - - if (usertime && warning) { - BIO_printf(bio_err, "To get meaningful results, run " - "this program on idle system.\n"); - warning = 0; - } - - if (stop == TM_START) - tmstart = clock(); - else - ret = (clock() - tmstart) / (double)CLOCKS_PER_SEC; - - return (ret); + return ret; } - #elif defined(OPENSSL_SYSTEM_VXWORKS) # include <time.h> @@ -3073,7 +2224,7 @@ double app_tminterval(int stop, int usertime) else ret = (now - tmstart) / (double)sysClkRateGet(); # endif - return (ret); + return ret; } #elif defined(OPENSSL_SYSTEM_VMS) @@ -3107,7 +2258,7 @@ double app_tminterval(int stop, int usertime) else ret = (now - tmstart) / (double)(CLK_TCK); - return (ret); + return ret; } #elif defined(_SC_CLK_TCK) /* by means of unistd.h */ @@ -3123,14 +2274,14 @@ double app_tminterval(int stop, int usertime) if (usertime) now = rus.tms_utime; - if (stop == TM_START) + if (stop == TM_START) { tmstart = now; - else { + } else { long int tck = sysconf(_SC_CLK_TCK); ret = (now - tmstart) / (double)tck; } - return (ret); + return ret; } #else @@ -3159,33 +2310,40 @@ double app_tminterval(int stop, int usertime) } #endif +int app_access(const char* name, int flag) +{ +#ifdef _WIN32 + return _access(name, flag); +#else + return access(name, flag); +#endif +} + /* app_isdir section */ #ifdef _WIN32 int app_isdir(const char *name) { - HANDLE hList; - WIN32_FIND_DATA FileData; + DWORD attr; # if defined(UNICODE) || defined(_UNICODE) size_t i, len_0 = strlen(name) + 1; + WCHAR tempname[MAX_PATH]; - if (len_0 > sizeof(FileData.cFileName) / sizeof(FileData.cFileName[0])) + if (len_0 > MAX_PATH) return -1; # if !defined(_WIN32_WCE) || _WIN32_WCE>=101 - if (!MultiByteToWideChar - (CP_ACP, 0, name, len_0, FileData.cFileName, len_0)) + if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) # endif for (i = 0; i < len_0; i++) - FileData.cFileName[i] = (WCHAR)name[i]; + tempname[i] = (WCHAR)name[i]; - hList = FindFirstFile(FileData.cFileName, &FileData); + attr = GetFileAttributes(tempname); # else - hList = FindFirstFile(name, &FileData); + attr = GetFileAttributes(name); # endif - if (hList == INVALID_HANDLE_VALUE) + if (attr == INVALID_FILE_ATTRIBUTES) return -1; - FindClose(hList); - return ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); } #else # include <sys/stat.h> @@ -3248,12 +2406,12 @@ int raw_read_stdin(void *buf, int siz) { DWORD n; if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) - return (n); + return n; else - return (-1); + return -1; } #elif defined(__VMS) -#include <sys/socket.h> +# include <sys/socket.h> int raw_read_stdin(void *buf, int siz) { @@ -3271,9 +2429,9 @@ int raw_write_stdout(const void *buf, int siz) { DWORD n; if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL)) - return (n); + return n; else - return (-1); + return -1; } #else int raw_write_stdout(const void *buf, int siz) @@ -3281,3 +2439,308 @@ int raw_write_stdout(const void *buf, int siz) return write(fileno_stdout(), buf, siz); } #endif + +/* + * Centralized handling if input and output files with format specification + * The format is meant to show what the input and output is supposed to be, + * and is therefore a show of intent more than anything else. However, it + * does impact behavior on some platform, such as differentiating between + * text and binary input/output on non-Unix platforms + */ +static int istext(int format) +{ + return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; +} + +BIO *dup_bio_in(int format) +{ + return BIO_new_fp(stdin, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); +} + +static BIO_METHOD *prefix_method = NULL; + +BIO *dup_bio_out(int format) +{ + BIO *b = BIO_new_fp(stdout, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); + void *prefix = NULL; + +#ifdef OPENSSL_SYS_VMS + if (istext(format)) + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + + if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { + if (prefix_method == NULL) + prefix_method = apps_bf_prefix(); + b = BIO_push(BIO_new(prefix_method), b); + BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix); + } + + return b; +} + +BIO *dup_bio_err(int format) +{ + BIO *b = BIO_new_fp(stderr, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); +#ifdef OPENSSL_SYS_VMS + if (istext(format)) + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + return b; +} + +void destroy_prefix_method(void) +{ + BIO_meth_free(prefix_method); + prefix_method = NULL; +} + +void unbuffer(FILE *fp) +{ +/* + * On VMS, setbuf() will only take 32-bit pointers, and a compilation + * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here. + * However, we trust that the C RTL will never give us a FILE pointer + * above the first 4 GB of memory, so we simply turn off the warning + * temporarily. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment save +# pragma message disable maylosedata2 +#endif + setbuf(fp, NULL); +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment restore +#endif +} + +static const char *modestr(char mode, int format) +{ + OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); + + switch (mode) { + case 'a': + return istext(format) ? "a" : "ab"; + case 'r': + return istext(format) ? "r" : "rb"; + case 'w': + return istext(format) ? "w" : "wb"; + } + /* The assert above should make sure we never reach this point */ + return NULL; +} + +static const char *modeverb(char mode) +{ + switch (mode) { + case 'a': + return "appending"; + case 'r': + return "reading"; + case 'w': + return "writing"; + } + return "(doing something)"; +} + +/* + * Open a file for writing, owner-read-only. + */ +BIO *bio_open_owner(const char *filename, int format, int private) +{ + FILE *fp = NULL; + BIO *b = NULL; + int fd = -1, bflags, mode, textmode; + + if (!private || filename == NULL || strcmp(filename, "-") == 0) + return bio_open_default(filename, 'w', format); + + mode = O_WRONLY; +#ifdef O_CREAT + mode |= O_CREAT; +#endif +#ifdef O_TRUNC + mode |= O_TRUNC; +#endif + textmode = istext(format); + if (!textmode) { +#ifdef O_BINARY + mode |= O_BINARY; +#elif defined(_O_BINARY) + mode |= _O_BINARY; +#endif + } + +#ifdef OPENSSL_SYS_VMS + /* VMS doesn't have O_BINARY, it just doesn't make sense. But, + * it still needs to know that we're going binary, or fdopen() + * will fail with "invalid argument"... so we tell VMS what the + * context is. + */ + if (!textmode) + fd = open(filename, mode, 0600, "ctx=bin"); + else +#endif + fd = open(filename, mode, 0600); + if (fd < 0) + goto err; + fp = fdopen(fd, modestr('w', format)); + if (fp == NULL) + goto err; + bflags = BIO_CLOSE; + if (textmode) + bflags |= BIO_FP_TEXT; + b = BIO_new_fp(fp, bflags); + if (b) + return b; + + err: + BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", + opt_getprog(), filename, strerror(errno)); + ERR_print_errors(bio_err); + /* If we have fp, then fdopen took over fd, so don't close both. */ + if (fp) + fclose(fp); + else if (fd >= 0) + close(fd); + return NULL; +} + +static BIO *bio_open_default_(const char *filename, char mode, int format, + int quiet) +{ + BIO *ret; + + if (filename == NULL || strcmp(filename, "-") == 0) { + ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s, %s\n", + mode == 'r' ? "stdin" : "stdout", strerror(errno)); + } else { + ret = BIO_new_file(filename, modestr(mode, format)); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s for %s, %s\n", + filename, modeverb(mode), strerror(errno)); + } + ERR_print_errors(bio_err); + return NULL; +} + +BIO *bio_open_default(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 0); +} + +BIO *bio_open_default_quiet(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 1); +} + +void wait_for_async(SSL *s) +{ + /* On Windows select only works for sockets, so we simply don't wait */ +#ifndef OPENSSL_SYS_WINDOWS + int width = 0; + fd_set asyncfds; + OSSL_ASYNC_FD *fds; + size_t numfds; + size_t i; + + if (!SSL_get_all_async_fds(s, NULL, &numfds)) + return; + if (numfds == 0) + return; + fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds"); + if (!SSL_get_all_async_fds(s, fds, &numfds)) { + OPENSSL_free(fds); + return; + } + + FD_ZERO(&asyncfds); + for (i = 0; i < numfds; i++) { + if (width <= (int)fds[i]) + width = (int)fds[i] + 1; + openssl_fdset((int)fds[i], &asyncfds); + } + select(width, (void *)&asyncfds, NULL, NULL, NULL); + OPENSSL_free(fds); +#endif +} + +/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */ +#if defined(OPENSSL_SYS_MSDOS) +int has_stdin_waiting(void) +{ +# if defined(OPENSSL_SYS_WINDOWS) + HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE); + DWORD events = 0; + INPUT_RECORD inputrec; + DWORD insize = 1; + BOOL peeked; + + if (inhand == INVALID_HANDLE_VALUE) { + return 0; + } + + peeked = PeekConsoleInput(inhand, &inputrec, insize, &events); + if (!peeked) { + /* Probably redirected input? _kbhit() does not work in this case */ + if (!feof(stdin)) { + return 1; + } + return 0; + } +# endif + return _kbhit(); +} +#endif + +/* Corrupt a signature by modifying final byte */ +void corrupt_signature(const ASN1_STRING *signature) +{ + unsigned char *s = signature->data; + s[signature->length - 1] ^= 0x1; +} + +int set_cert_times(X509 *x, const char *startdate, const char *enddate, + int days) +{ + if (startdate == NULL || strcmp(startdate, "today") == 0) { + if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) + return 0; + } else { + if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) + return 0; + } + if (enddate == NULL) { + if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) + == NULL) + return 0; + } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) { + return 0; + } + return 1; +} + +void make_uppercase(char *string) +{ + int i; + + for (i = 0; string[i] != '\0'; i++) + string[i] = toupper((unsigned char)string[i]); +} diff --git a/apps/apps.h b/apps/apps.h index 268863c336a4..5b98d27500ce 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -1,221 +1,436 @@ -/* apps/apps.h */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #ifndef HEADER_APPS_H # define HEADER_APPS_H -# include "e_os.h" +# include "e_os.h" /* struct timeval for DTLS */ +# include "internal/nelem.h" +# include <assert.h> + +# include <sys/types.h> +# ifndef OPENSSL_NO_POSIX_IO +# include <sys/stat.h> +# include <fcntl.h> +# endif +# include <openssl/e_os2.h> +# include <openssl/ossl_typ.h> # include <openssl/bio.h> # include <openssl/x509.h> -# include <openssl/lhash.h> # include <openssl/conf.h> # include <openssl/txt_db.h> -# ifndef OPENSSL_NO_ENGINE -# include <openssl/engine.h> +# include <openssl/engine.h> +# include <openssl/ocsp.h> +# include <signal.h> + +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE) +# define openssl_fdset(a,b) FD_SET((unsigned int)a, b) +# else +# define openssl_fdset(a,b) FD_SET(a, b) # endif -# ifndef OPENSSL_NO_OCSP -# include <openssl/ocsp.h> + +/* + * quick macro when you need to pass an unsigned char instead of a char. + * this is true for some implementations of the is*() functions, for + * example. + */ +#define _UC(c) ((unsigned char)(c)) + +void app_RAND_load_conf(CONF *c, const char *section); +void app_RAND_write(void); + +extern char *default_config_file; +extern BIO *bio_in; +extern BIO *bio_out; +extern BIO *bio_err; +extern const unsigned char tls13_aes128gcmsha256_id[]; +extern const unsigned char tls13_aes256gcmsha384_id[]; +extern BIO_ADDR *ourpeer; + +BIO_METHOD *apps_bf_prefix(void); +/* + * The control used to set the prefix with BIO_ctrl() + * We make it high enough so the chance of ever clashing with the BIO library + * remains unlikely for the foreseeable future and beyond. + */ +#define PREFIX_CTRL_SET_PREFIX (1 << 15) +/* + * apps_bf_prefix() returns a dynamically created BIO_METHOD, which we + * need to destroy at some point. When created internally, it's stored + * in an internal pointer which can be freed with the following function + */ +void destroy_prefix_method(void); + +BIO *dup_bio_in(int format); +BIO *dup_bio_out(int format); +BIO *dup_bio_err(int format); +BIO *bio_open_owner(const char *filename, int format, int private); +BIO *bio_open_default(const char *filename, char mode, int format); +BIO *bio_open_default_quiet(const char *filename, char mode, int format); +CONF *app_load_config_bio(BIO *in, const char *filename); +CONF *app_load_config(const char *filename); +CONF *app_load_config_quiet(const char *filename); +int app_load_modules(const CONF *config); +void unbuffer(FILE *fp); +void wait_for_async(SSL *s); +# if defined(OPENSSL_SYS_MSDOS) +int has_stdin_waiting(void); # endif -# include <openssl/ossl_typ.h> -int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn); -int app_RAND_write_file(const char *file, BIO *bio_e); +void corrupt_signature(const ASN1_STRING *signature); +int set_cert_times(X509 *x, const char *startdate, const char *enddate, + int days); + /* - * When `file' is NULL, use defaults. `bio_e' is for error messages. + * Common verification options. */ -void app_RAND_allow_write_file(void); -long app_RAND_load_files(char *file); /* `file' is a list of files to read, - * separated by LIST_SEPARATOR_CHAR - * (see e_os.h). The string is - * destroyed! */ +# define OPT_V_ENUM \ + OPT_V__FIRST=2000, \ + OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \ + OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \ + OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \ + OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \ + OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \ + OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \ + OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \ + OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \ + OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \ + OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \ + OPT_V__LAST -# ifndef MONOLITH +# define OPT_V_OPTIONS \ + { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \ + { "purpose", OPT_V_PURPOSE, 's', \ + "certificate chain purpose"}, \ + { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \ + { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \ + "chain depth limit" }, \ + { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \ + "chain authentication security level" }, \ + { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \ + { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \ + "expected peer hostname" }, \ + { "verify_email", OPT_V_VERIFY_EMAIL, 's', \ + "expected peer email" }, \ + { "verify_ip", OPT_V_VERIFY_IP, 's', \ + "expected peer IP address" }, \ + { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \ + "permit unhandled critical extensions"}, \ + { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \ + { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \ + { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \ + { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \ + { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \ + "set policy variable require-explicit-policy"}, \ + { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \ + "set policy variable inhibit-any-policy"}, \ + { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \ + "set policy variable inhibit-policy-mapping"}, \ + { "x509_strict", OPT_V_X509_STRICT, '-', \ + "disable certificate compatibility work-arounds"}, \ + { "extended_crl", OPT_V_EXTENDED_CRL, '-', \ + "enable extended CRL features"}, \ + { "use_deltas", OPT_V_USE_DELTAS, '-', \ + "use delta CRLs"}, \ + { "policy_print", OPT_V_POLICY_PRINT, '-', \ + "print policy processing diagnostics"}, \ + { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \ + "check root CA self-signatures"}, \ + { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \ + "search trust store first (default)" }, \ + { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \ + { "suiteB_128", OPT_V_SUITEB_128, '-', \ + "Suite B 128-bit mode allowing 192-bit algorithms"}, \ + { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \ + { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \ + "accept chains anchored by intermediate trust-store CAs"}, \ + { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \ + { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \ + { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" } -# define MAIN(a,v) main(a,v) +# define OPT_V_CASES \ + OPT_V__FIRST: case OPT_V__LAST: break; \ + case OPT_V_POLICY: \ + case OPT_V_PURPOSE: \ + case OPT_V_VERIFY_NAME: \ + case OPT_V_VERIFY_DEPTH: \ + case OPT_V_VERIFY_AUTH_LEVEL: \ + case OPT_V_ATTIME: \ + case OPT_V_VERIFY_HOSTNAME: \ + case OPT_V_VERIFY_EMAIL: \ + case OPT_V_VERIFY_IP: \ + case OPT_V_IGNORE_CRITICAL: \ + case OPT_V_ISSUER_CHECKS: \ + case OPT_V_CRL_CHECK: \ + case OPT_V_CRL_CHECK_ALL: \ + case OPT_V_POLICY_CHECK: \ + case OPT_V_EXPLICIT_POLICY: \ + case OPT_V_INHIBIT_ANY: \ + case OPT_V_INHIBIT_MAP: \ + case OPT_V_X509_STRICT: \ + case OPT_V_EXTENDED_CRL: \ + case OPT_V_USE_DELTAS: \ + case OPT_V_POLICY_PRINT: \ + case OPT_V_CHECK_SS_SIG: \ + case OPT_V_TRUSTED_FIRST: \ + case OPT_V_SUITEB_128_ONLY: \ + case OPT_V_SUITEB_128: \ + case OPT_V_SUITEB_192: \ + case OPT_V_PARTIAL_CHAIN: \ + case OPT_V_NO_ALT_CHAINS: \ + case OPT_V_NO_CHECK_TIME: \ + case OPT_V_ALLOW_PROXY_CERTS -# ifndef NON_MAIN -CONF *config = NULL; -BIO *bio_err = NULL; -# else -extern CONF *config; -extern BIO *bio_err; -# endif +/* + * Common "extended validation" options. + */ +# define OPT_X_ENUM \ + OPT_X__FIRST=1000, \ + OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \ + OPT_X_CERTFORM, OPT_X_KEYFORM, \ + OPT_X__LAST -# else +# define OPT_X_OPTIONS \ + { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \ + { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \ + { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \ + { "xchain_build", OPT_X_CHAIN_BUILD, '-', \ + "build certificate chain for the extended certificates"}, \ + { "xcertform", OPT_X_CERTFORM, 'F', \ + "format of Extended certificate (PEM or DER) PEM default " }, \ + { "xkeyform", OPT_X_KEYFORM, 'F', \ + "format of Extended certificate's key (PEM or DER) PEM default"} -# define MAIN(a,v) PROG(a,v) -extern CONF *config; -extern char *default_config_file; -extern BIO *bio_err; +# define OPT_X_CASES \ + OPT_X__FIRST: case OPT_X__LAST: break; \ + case OPT_X_KEY: \ + case OPT_X_CERT: \ + case OPT_X_CHAIN: \ + case OPT_X_CHAIN_BUILD: \ + case OPT_X_CERTFORM: \ + case OPT_X_KEYFORM -# endif +/* + * Common SSL options. + * Any changes here must be coordinated with ../ssl/ssl_conf.c + */ +# define OPT_S_ENUM \ + OPT_S__FIRST=3000, \ + OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \ + OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \ + OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \ + OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ + OPT_S_PRIORITIZE_CHACHA, \ + OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ + OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ + OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ + OPT_S_MINPROTO, OPT_S_MAXPROTO, \ + OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST -# ifndef OPENSSL_SYS_NETWARE -# include <signal.h> -# endif +# define OPT_S_OPTIONS \ + {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \ + {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \ + {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \ + {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \ + {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \ + {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \ + {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \ + {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \ + {"no_ticket", OPT_S_NOTICKET, '-', \ + "Disable use of TLS session tickets"}, \ + {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \ + {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \ + "Enable use of legacy renegotiation (dangerous)"}, \ + {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \ + "Disable all renegotiation."}, \ + {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \ + "Allow initial connection to servers that don't support RI"}, \ + {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \ + "Disallow session resumption on renegotiation"}, \ + {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \ + "Disallow initial connection to servers that don't support RI"}, \ + {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \ + "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \ + {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \ + "Prioritize ChaCha ciphers when preferred by clients"}, \ + {"strict", OPT_S_STRICT, '-', \ + "Enforce strict certificate checks as per TLS standard"}, \ + {"sigalgs", OPT_S_SIGALGS, 's', \ + "Signature algorithms to support (colon-separated list)" }, \ + {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \ + "Signature algorithms to support for client certificate" \ + " authentication (colon-separated list)" }, \ + {"groups", OPT_S_GROUPS, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"curves", OPT_S_CURVES, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"named_curve", OPT_S_NAMEDCURVE, 's', \ + "Elliptic curve used for ECDHE (server-side only)" }, \ + {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \ + {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \ + {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \ + {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \ + {"record_padding", OPT_S_RECORD_PADDING, 's', \ + "Block size to pad TLS 1.3 records to."}, \ + {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \ + "Perform all sorts of protocol violations for testing purposes"}, \ + {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \ + "Disable TLSv1.3 middlebox compat mode" } -# ifdef SIGPIPE -# define do_pipe_sig() signal(SIGPIPE,SIG_IGN) -# else -# define do_pipe_sig() -# endif +# define OPT_S_CASES \ + OPT_S__FIRST: case OPT_S__LAST: break; \ + case OPT_S_NOSSL3: \ + case OPT_S_NOTLS1: \ + case OPT_S_NOTLS1_1: \ + case OPT_S_NOTLS1_2: \ + case OPT_S_NOTLS1_3: \ + case OPT_S_BUGS: \ + case OPT_S_NO_COMP: \ + case OPT_S_COMP: \ + case OPT_S_NOTICKET: \ + case OPT_S_SERVERPREF: \ + case OPT_S_LEGACYRENEG: \ + case OPT_S_LEGACYCONN: \ + case OPT_S_ONRESUMP: \ + case OPT_S_NOLEGACYCONN: \ + case OPT_S_ALLOW_NO_DHE_KEX: \ + case OPT_S_PRIORITIZE_CHACHA: \ + case OPT_S_STRICT: \ + case OPT_S_SIGALGS: \ + case OPT_S_CLIENTSIGALGS: \ + case OPT_S_GROUPS: \ + case OPT_S_CURVES: \ + case OPT_S_NAMEDCURVE: \ + case OPT_S_CIPHER: \ + case OPT_S_CIPHERSUITES: \ + case OPT_S_RECORD_PADDING: \ + case OPT_S_NO_RENEGOTIATION: \ + case OPT_S_MINPROTO: \ + case OPT_S_MAXPROTO: \ + case OPT_S_DEBUGBROKE: \ + case OPT_S_NO_MIDDLEBOX -# ifdef OPENSSL_NO_COMP -# define zlib_cleanup() -# else -# define zlib_cleanup() COMP_zlib_cleanup() -# endif +#define IS_NO_PROT_FLAG(o) \ + (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \ + || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3) -# if defined(MONOLITH) && !defined(OPENSSL_C) -# define apps_startup() \ - do_pipe_sig() -# define apps_shutdown() -# else -# ifndef OPENSSL_NO_ENGINE -# define apps_startup() \ - do { do_pipe_sig(); CRYPTO_malloc_init(); \ - ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); \ - ENGINE_load_builtin_engines(); setup_ui_method(); } while(0) -# define apps_shutdown() \ - do { CONF_modules_unload(1); destroy_ui_method(); \ - OBJ_cleanup(); EVP_cleanup(); ENGINE_cleanup(); \ - CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); \ - RAND_cleanup(); \ - ERR_free_strings(); zlib_cleanup();} while(0) -# else -# define apps_startup() \ - do { do_pipe_sig(); CRYPTO_malloc_init(); \ - ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); \ - setup_ui_method(); } while(0) -# define apps_shutdown() \ - do { CONF_modules_unload(1); destroy_ui_method(); \ - OBJ_cleanup(); EVP_cleanup(); \ - CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); \ - RAND_cleanup(); \ - ERR_free_strings(); zlib_cleanup(); } while(0) -# endif -# endif +/* + * Random state options. + */ +# define OPT_R_ENUM \ + OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST -# if defined(OPENSSL_SYSNAME_WIN32) || defined(OPENSSL_SYSNAME_WINCE) -# define openssl_fdset(a,b) FD_SET((unsigned int)a, b) -# else -# define openssl_fdset(a,b) FD_SET(a, b) -# endif +# define OPT_R_OPTIONS \ + {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \ + {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"} + +# define OPT_R_CASES \ + OPT_R__FIRST: case OPT_R__LAST: break; \ + case OPT_R_RAND: case OPT_R_WRITERAND + +/* + * Option parsing. + */ +extern const char OPT_HELP_STR[]; +extern const char OPT_MORE_STR[]; +typedef struct options_st { + const char *name; + int retval; + /* + * value type: - no value (also the value zero), n number, p positive + * number, u unsigned, l long, s string, < input file, > output file, + * f any format, F der/pem format, E der/pem/engine format identifier. + * l, n and u include zero; p does not. + */ + int valtype; + const char *helpstr; +} OPTIONS; + +/* + * A string/int pairing; widely use for option value lookup, hence the + * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use + * the "generic" name STRINT_PAIR. + */ +typedef struct string_int_pair_st { + const char *name; + int retval; +} OPT_PAIR, STRINT_PAIR; + +/* Flags to pass into opt_format; see FORMAT_xxx, below. */ +# define OPT_FMT_PEMDER (1L << 1) +# define OPT_FMT_PKCS12 (1L << 2) +# define OPT_FMT_SMIME (1L << 3) +# define OPT_FMT_ENGINE (1L << 4) +# define OPT_FMT_MSBLOB (1L << 5) +# define OPT_FMT_NETSCAPE (1L << 6) +# define OPT_FMT_NSS (1L << 7) +# define OPT_FMT_TEXT (1L << 8) +# define OPT_FMT_HTTP (1L << 9) +# define OPT_FMT_PVK (1L << 10) +# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE) +# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME) +# define OPT_FMT_ANY ( \ + OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ + OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NETSCAPE | \ + OPT_FMT_NSS | OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) + +char *opt_progname(const char *argv0); +char *opt_getprog(void); +char *opt_init(int ac, char **av, const OPTIONS * o); +int opt_next(void); +int opt_format(const char *s, unsigned long flags, int *result); +int opt_int(const char *arg, int *result); +int opt_ulong(const char *arg, unsigned long *result); +int opt_long(const char *arg, long *result); +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) +int opt_imax(const char *arg, intmax_t *result); +int opt_umax(const char *arg, uintmax_t *result); +#else +# define opt_imax opt_long +# define opt_umax opt_ulong +# define intmax_t long +# define uintmax_t unsigned long +#endif +int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); +int opt_cipher(const char *name, const EVP_CIPHER **cipherp); +int opt_md(const char *name, const EVP_MD **mdp); +char *opt_arg(void); +char *opt_flag(void); +char *opt_unknown(void); +char **opt_rest(void); +int opt_num_rest(void); +int opt_verify(int i, X509_VERIFY_PARAM *vpm); +int opt_rand(int i); +void opt_help(const OPTIONS * list); +int opt_format_error(const char *s, unsigned long flags); typedef struct args_st { - char **data; - int count; + int size; + int argc; + char **argv; } ARGS; +/* + * VMS C only for now, implemented in vms_decc_init.c + * If other C compilers forget to terminate argv with NULL, this function + * can be re-used. + */ +char **copy_argv(int *argc, char *argv[]); +/* + * Win32-specific argv initialization that splits OS-supplied UNICODE + * command line string to array of UTF8-encoded strings. + */ +void win32_utf8argv(int *argc, char **argv[]); + + # define PW_MIN_LENGTH 4 typedef struct pw_cb_data { const void *password; @@ -226,54 +441,63 @@ int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data); int setup_ui_method(void); void destroy_ui_method(void); +const UI_METHOD *get_ui_method(void); -int should_retry(int i); -int args_from_file(char *file, int *argc, char **argv[]); -int str2fmt(char *s); -void program_name(char *in, char *out, int size); -int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]); +int chopup_args(ARGS *arg, char *buf); # ifdef HEADER_X509_H int dump_cert_text(BIO *out, X509 *x); void print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags); # endif +void print_bignum_var(BIO *, const BIGNUM *, const char*, + int, unsigned char *); +void print_array(BIO *, const char *, int, const unsigned char *); +int set_nameopt(const char *arg); +unsigned long get_nameopt(void); int set_cert_ex(unsigned long *flags, const char *arg); int set_name_ex(unsigned long *flags, const char *arg); int set_ext_copy(int *copy_type, const char *arg); int copy_extensions(X509 *x, X509_REQ *req, int copy_type); -int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2); -int add_oid_section(BIO *err, CONF *conf); -X509 *load_cert(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, const char *cert_descrip); +int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2); +int add_oid_section(CONF *conf); +X509 *load_cert(const char *file, int format, const char *cert_descrip); X509_CRL *load_crl(const char *infile, int format); -int load_cert_crl_http(const char *url, BIO *err, - X509 **pcert, X509_CRL **pcrl); -EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, +EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *key_descrip); -EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, +EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *key_descrip); -STACK_OF(X509) *load_certs(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, - const char *cert_descrip); -STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format, - const char *pass, ENGINE *e, - const char *cert_descrip); -X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath); +int load_certs(const char *file, STACK_OF(X509) **certs, int format, + const char *pass, const char *cert_descrip); +int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, + const char *pass, const char *cert_descrip); +X509_STORE *setup_verify(const char *CAfile, const char *CApath, + int noCAfile, int noCApath); +__owur int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath, int noCAfile, + int noCApath); + +#ifndef OPENSSL_NO_CT + +/* + * Sets the file to load the Certificate Transparency log list from. + * If path is NULL, loads from the default file path. + * Returns 1 on success, 0 otherwise. + */ +__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path); + +#endif -ENGINE *setup_engine(BIO *err, const char *engine, int debug); +ENGINE *setup_engine(const char *engine, int debug); void release_engine(ENGINE *e); # ifndef OPENSSL_NO_OCSP -OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req, +OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host, const char *path, const char *port, int use_ssl, - const STACK_OF(CONF_VALUE) *headers, + STACK_OF(CONF_VALUE) *headers, int req_timeout); # endif -int load_config(BIO *err, CONF *cnf); -char *make_config_name(void); - /* Functions defined in ca.c and also used in ocsp.c */ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str); @@ -287,9 +511,10 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, * disabled */ # define DB_NUMBER 6 -# define DB_TYPE_REV 'R' -# define DB_TYPE_EXP 'E' -# define DB_TYPE_VAL 'V' +# define DB_TYPE_REV 'R' /* Revoked */ +# define DB_TYPE_EXP 'E' /* Expired */ +# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */ +# define DB_TYPE_SUSP 'S' /* Suspended */ typedef struct db_attr_st { int unique_subject; @@ -297,14 +522,20 @@ typedef struct db_attr_st { typedef struct ca_db_st { DB_ATTR attributes; TXT_DB *db; + char *dbfname; +# ifndef OPENSSL_NO_POSIX_IO + struct stat dbst; +# endif } CA_DB; -BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai); -int save_serial(char *serialfile, char *suffix, BIGNUM *serial, +void* app_malloc(int sz, const char *what); +BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai); +int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, ASN1_INTEGER **retai); -int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix); +int rotate_serial(const char *serialfile, const char *new_suffix, + const char *old_suffix); int rand_serial(BIGNUM *b, ASN1_INTEGER *ai); -CA_DB *load_index(char *dbfile, DB_ATTR *dbattr); +CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr); int index_index(CA_DB *db); int save_index(const char *dbfile, const char *suffix, CA_DB *db); int rotate_index(const char *dbfile, const char *new_suffix, @@ -316,31 +547,23 @@ void free_index(CA_DB *db); int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b); int parse_yesno(const char *str, int def); -X509_NAME *parse_name(char *str, long chtype, int multirdn); -int args_verify(char ***pargs, int *pargc, - int *badarg, BIO *err, X509_VERIFY_PARAM **pm); -void policies_print(BIO *out, X509_STORE_CTX *ctx); +X509_NAME *parse_name(const char *str, long chtype, int multirdn); +void policies_print(X509_STORE_CTX *ctx); int bio_to_mem(unsigned char **out, int maxlen, BIO *in); int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value); -int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx, +int init_gen_str(EVP_PKEY_CTX **pctx, const char *algname, ENGINE *e, int do_param); -int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md, +int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts); -int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, +int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts); -int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, +int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts); -# ifndef OPENSSL_NO_PSK + extern char *psk_key; -# endif -# ifndef OPENSSL_NO_JPAKE -void jpake_client_auth(BIO *out, BIO *conn, const char *secret); -void jpake_server_auth(BIO *out, BIO *conn, const char *secret); -# endif -# ifndef OPENSSL_NO_TLSEXT -unsigned char *next_protos_parse(unsigned short *outlen, const char *in); -# endif /* ndef OPENSSL_NO_TLSEXT */ + +unsigned char *next_protos_parse(size_t *outlen, const char *in); void print_cert_checks(BIO *bio, X509 *x, const char *checkhost, @@ -348,21 +571,28 @@ void print_cert_checks(BIO *bio, X509 *x, void store_setup_crl_download(X509_STORE *st); +/* See OPT_FMT_xxx, above. */ +/* On some platforms, it's important to distinguish between text and binary + * files. On some, there might even be specific file formats for different + * contents. The FORMAT_xxx macros are meant to express an intent with the + * file being read or created. + */ +# define B_FORMAT_TEXT 0x8000 # define FORMAT_UNDEF 0 -# define FORMAT_ASN1 1 -# define FORMAT_TEXT 2 -# define FORMAT_PEM 3 -# define FORMAT_NETSCAPE 4 -# define FORMAT_PKCS12 5 -# define FORMAT_SMIME 6 -# define FORMAT_ENGINE 7 -# define FORMAT_IISSGC 8 /* XXX this stupid macro helps us to avoid - * adding yet another param to load_*key() */ -# define FORMAT_PEMRSA 9 /* PEM RSAPubicKey format */ -# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */ -# define FORMAT_MSBLOB 11 /* MS Key blob format */ -# define FORMAT_PVK 12 /* MS PVK file format */ -# define FORMAT_HTTP 13 /* Download using HTTP */ +# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */ +# define FORMAT_BINARY 2 /* Generic binary */ +# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */ +# define FORMAT_ASN1 4 /* ASN.1/DER */ +# define FORMAT_PEM (5 | B_FORMAT_TEXT) +# define FORMAT_PKCS12 6 +# define FORMAT_SMIME (7 | B_FORMAT_TEXT) +# define FORMAT_ENGINE 8 /* Not really a file format */ +# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */ +# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */ +# define FORMAT_MSBLOB 11 /* MS Key blob format */ +# define FORMAT_PVK 12 /* MS PVK file format */ +# define FORMAT_HTTP 13 /* Download using HTTP */ +# define FORMAT_NSS 14 /* NSS keylog format */ # define EXT_COPY_NONE 0 # define EXT_COPY_ADD 1 @@ -372,9 +602,15 @@ void store_setup_crl_download(X509_STORE *st); # define APP_PASS_LEN 1024 -# define SERIAL_RAND_BITS 64 +/* + * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits + * so that the first bit will never be one, so that the DER encoding + * rules won't force a leading octet. + */ +# define SERIAL_RAND_BITS 159 int app_isdir(const char *); +int app_access(const char *, int flag); int fileno_stdin(void); int fileno_stdout(void); int raw_read_stdin(void *, int); @@ -384,6 +620,15 @@ int raw_write_stdout(const void *, int); # define TM_STOP 1 double app_tminterval(int stop, int usertime); -# define OPENSSL_NO_SSL_INTERN +void make_uppercase(char *string); + +typedef struct verify_options_st { + int depth; + int quiet; + int error; + int return_error; +} VERIFY_CB_ARGS; + +extern VERIFY_CB_ARGS verify_args; #endif diff --git a/apps/asn1pars.c b/apps/asn1pars.c index 0a6b990b503d..62c70b9cc440 100644 --- a/apps/asn1pars.c +++ b/apps/asn1pars.c @@ -1,302 +1,233 @@ -/* apps/asn1pars.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - /* - * A nice addition from Dr Stephen Henson <steve@openssl.org> to add the - * -strparse option which parses nested binary structures + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/x509.h> #include <openssl/pem.h> +#include <openssl/asn1t.h> -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -in arg - input file - default stdin - * -i - indent the details by depth - * -offset - where in the file to start - * -length - how many bytes to use - * -oid file - extra oid description file - */ - -#undef PROG -#define PROG asn1parse_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT, + OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT, + OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM, + OPT_ITEM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS asn1parse_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"}, + {"in", OPT_IN, '<', "input file"}, + {"out", OPT_OUT, '>', "output file (output format is always DER)"}, + {"i", OPT_INDENT, 0, "indents the output"}, + {"noout", OPT_NOOUT, 0, "do not produce any output"}, + {"offset", OPT_OFFSET, 'p', "offset into file"}, + {"length", OPT_LENGTH, 'p', "length of section in file"}, + {"oid", OPT_OID, '<', "file of extra oid definitions"}, + {"dump", OPT_DUMP, 0, "unknown data in hex form"}, + {"dlimit", OPT_DLIMIT, 'p', + "dump the first arg bytes of unknown data in hex form"}, + {"strparse", OPT_STRPARSE, 'p', + "offset; a series of these can be used to 'dig'"}, + {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"}, + {"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"}, + {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"}, + {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"}, + {"strictpem", OPT_STRICTPEM, 0, + "do not attempt base64 decode outside PEM markers"}, + {"item", OPT_ITEM, 's', "item to parse and print"}, + {NULL} +}; -static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf); +static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf); -int MAIN(int argc, char **argv) +int asn1parse_main(int argc, char **argv) { - int i, badops = 0, offset = 0, ret = 1, j; - unsigned int length = 0; - long num, tmplen; - BIO *in = NULL, *out = NULL, *b64 = NULL, *derout = NULL; - int informat, indent = 0, noout = 0, dump = 0; - char *infile = NULL, *str = NULL, *prog, *oidfile = NULL, *derfile = NULL; - char *genstr = NULL, *genconf = NULL; - unsigned char *tmpbuf; - const unsigned char *ctmpbuf; + ASN1_TYPE *at = NULL; + BIO *in = NULL, *b64 = NULL, *derout = NULL; BUF_MEM *buf = NULL; STACK_OF(OPENSSL_STRING) *osk = NULL; - ASN1_TYPE *at = NULL; - - informat = FORMAT_PEM; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); + char *genstr = NULL, *genconf = NULL; + char *infile = NULL, *oidfile = NULL, *derfile = NULL; + unsigned char *str = NULL; + char *name = NULL, *header = NULL, *prog; + const unsigned char *ctmpbuf; + int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM; + int offset = 0, ret = 1, i, j; + long num, tmplen; + unsigned char *tmpbuf; + unsigned int length = 0; + OPTION_CHOICE o; + const ASN1_ITEM *it = NULL; - if (!load_config(bio_err, NULL)) - goto end; + prog = opt_init(argc, argv, asn1parse_options); - prog = argv[0]; - argc--; - argv++; if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) { - BIO_printf(bio_err, "Memory allocation failure\n"); + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); goto end; } - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - derfile = *(++argv); - } else if (strcmp(*argv, "-i") == 0) { + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(asn1parse_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + derfile = opt_arg(); + break; + case OPT_INDENT: indent = 1; - } else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-oid") == 0) { - if (--argc < 1) - goto bad; - oidfile = *(++argv); - } else if (strcmp(*argv, "-offset") == 0) { - if (--argc < 1) - goto bad; - offset = atoi(*(++argv)); - } else if (strcmp(*argv, "-length") == 0) { - if (--argc < 1) - goto bad; - length = atoi(*(++argv)); - if (length == 0) - goto bad; - } else if (strcmp(*argv, "-dump") == 0) { + break; + case OPT_OID: + oidfile = opt_arg(); + break; + case OPT_OFFSET: + offset = strtol(opt_arg(), NULL, 0); + break; + case OPT_LENGTH: + length = strtol(opt_arg(), NULL, 0); + break; + case OPT_DUMP: dump = -1; - } else if (strcmp(*argv, "-dlimit") == 0) { - if (--argc < 1) - goto bad; - dump = atoi(*(++argv)); - if (dump <= 0) - goto bad; - } else if (strcmp(*argv, "-strparse") == 0) { - if (--argc < 1) - goto bad; - sk_OPENSSL_STRING_push(osk, *(++argv)); - } else if (strcmp(*argv, "-genstr") == 0) { - if (--argc < 1) - goto bad; - genstr = *(++argv); - } else if (strcmp(*argv, "-genconf") == 0) { - if (--argc < 1) - goto bad; - genconf = *(++argv); - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; break; - } - argc--; - argv++; - } - - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - one of DER PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, - " -out arg output file (output format is always DER\n"); - BIO_printf(bio_err, " -noout arg don't produce any output\n"); - BIO_printf(bio_err, " -offset arg offset into file\n"); - BIO_printf(bio_err, " -length arg length of section in file\n"); - BIO_printf(bio_err, " -i indent entries\n"); - BIO_printf(bio_err, " -dump dump unknown data in hex form\n"); - BIO_printf(bio_err, - " -dlimit arg dump the first arg bytes of unknown data in hex form\n"); - BIO_printf(bio_err, " -oid file file of extra oid definitions\n"); - BIO_printf(bio_err, " -strparse offset\n"); - BIO_printf(bio_err, - " a series of these can be used to 'dig' into multiple\n"); - BIO_printf(bio_err, " ASN1 blob wrappings\n"); - BIO_printf(bio_err, - " -genstr str string to generate ASN1 structure from\n"); - BIO_printf(bio_err, - " -genconf file file to generate ASN1 structure from\n"); - goto end; - } - - ERR_load_crypto_strings(); + case OPT_DLIMIT: + dump = strtol(opt_arg(), NULL, 0); + break; + case OPT_STRPARSE: + sk_OPENSSL_STRING_push(osk, opt_arg()); + break; + case OPT_GENSTR: + genstr = opt_arg(); + break; + case OPT_GENCONF: + genconf = opt_arg(); + break; + case OPT_STRICTPEM: + strictpem = 1; + informat = FORMAT_PEM; + break; + case OPT_ITEM: + it = ASN1_ITEM_lookup(opt_arg()); + if (it == NULL) { + size_t tmp; - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); - goto end; - } - BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); + BIO_printf(bio_err, "Unknown item name %s\n", opt_arg()); + BIO_puts(bio_err, "Supported types:\n"); + for (tmp = 0;; tmp++) { + it = ASN1_ITEM_get(tmp); + if (it == NULL) + break; + BIO_printf(bio_err, " %s\n", it->sname); + } + goto end; + } + break; + } } -#endif + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; if (oidfile != NULL) { - if (BIO_read_filename(in, oidfile) <= 0) { - BIO_printf(bio_err, "problems opening %s\n", oidfile); - ERR_print_errors(bio_err); + in = bio_open_default(oidfile, 'r', FORMAT_TEXT); + if (in == NULL) goto end; - } OBJ_create_objects(in); + BIO_free(in); } - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } - - if (derfile) { - if (!(derout = BIO_new_file(derfile, "wb"))) { - BIO_printf(bio_err, "problems opening %s\n", derfile); - ERR_print_errors(bio_err); - goto end; - } - } + if ((in = bio_open_default(infile, 'r', informat)) == NULL) + goto end; - if ((buf = BUF_MEM_new()) == NULL) + if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL) goto end; - if (!BUF_MEM_grow(buf, BUFSIZ * 8)) - goto end; /* Pre-allocate :-) */ - if (genstr || genconf) { - num = do_generate(bio_err, genstr, genconf, buf); - if (num < 0) { + if (strictpem) { + if (PEM_read_bio(in, &name, &header, &str, &num) != + 1) { + BIO_printf(bio_err, "Error reading PEM file\n"); ERR_print_errors(bio_err); goto end; } - } - - else { + } else { - if (informat == FORMAT_PEM) { - BIO *tmp; + if ((buf = BUF_MEM_new()) == NULL) + goto end; + if (!BUF_MEM_grow(buf, BUFSIZ * 8)) + goto end; /* Pre-allocate :-) */ - if ((b64 = BIO_new(BIO_f_base64())) == NULL) + if (genstr || genconf) { + num = do_generate(genstr, genconf, buf); + if (num < 0) { + ERR_print_errors(bio_err); goto end; - BIO_push(b64, in); - tmp = in; - in = b64; - b64 = tmp; - } + } + } else { - num = 0; - for (;;) { - if (!BUF_MEM_grow(buf, (int)num + BUFSIZ)) - goto end; - i = BIO_read(in, &(buf->data[num]), BUFSIZ); - if (i <= 0) - break; - num += i; + if (informat == FORMAT_PEM) { + BIO *tmp; + + if ((b64 = BIO_new(BIO_f_base64())) == NULL) + goto end; + BIO_push(b64, in); + tmp = in; + in = b64; + b64 = tmp; + } + + num = 0; + for (;;) { + if (!BUF_MEM_grow(buf, num + BUFSIZ)) + goto end; + i = BIO_read(in, &(buf->data[num]), BUFSIZ); + if (i <= 0) + break; + num += i; + } } + str = (unsigned char *)buf->data; + } - str = buf->data; /* If any structs to parse go through in sequence */ if (sk_OPENSSL_STRING_num(osk)) { - tmpbuf = (unsigned char *)str; + tmpbuf = str; tmplen = num; for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) { ASN1_TYPE *atmp; int typ; - j = atoi(sk_OPENSSL_STRING_value(osk, i)); - if (j == 0) { - BIO_printf(bio_err, "'%s' is an invalid number\n", + j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0); + if (j <= 0 || j >= tmplen) { + BIO_printf(bio_err, "'%s' is out of range\n", sk_OPENSSL_STRING_value(osk, i)); continue; } @@ -323,70 +254,76 @@ int MAIN(int argc, char **argv) tmpbuf = at->value.asn1_string->data; tmplen = at->value.asn1_string->length; } - str = (char *)tmpbuf; + str = tmpbuf; num = tmplen; } - if (offset >= num) { - BIO_printf(bio_err, "Error: offset too large\n"); + if (offset < 0 || offset >= num) { + BIO_printf(bio_err, "Error: offset out of range\n"); goto end; } num -= offset; - if ((length == 0) || ((long)length > num)) + if (length == 0 || length > (unsigned int)num) length = (unsigned int)num; - if (derout) { + if (derout != NULL) { if (BIO_write(derout, str + offset, length) != (int)length) { BIO_printf(bio_err, "Error writing output\n"); ERR_print_errors(bio_err); goto end; } } - if (!noout && - !ASN1_parse_dump(out, (unsigned char *)&(str[offset]), length, - indent, dump)) { - ERR_print_errors(bio_err); - goto end; + if (!noout) { + const unsigned char *p = str + offset; + + if (it != NULL) { + ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it); + if (value == NULL) { + BIO_printf(bio_err, "Error parsing item %s\n", it->sname); + ERR_print_errors(bio_err); + goto end; + } + ASN1_item_print(bio_out, value, 0, it, NULL); + ASN1_item_free(value, it); + } else { + if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) { + ERR_print_errors(bio_err); + goto end; + } + } } ret = 0; end: BIO_free(derout); - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (b64 != NULL) - BIO_free(b64); + BIO_free(in); + BIO_free(b64); if (ret != 0) ERR_print_errors(bio_err); - if (buf != NULL) - BUF_MEM_free(buf); - if (at != NULL) - ASN1_TYPE_free(at); - if (osk != NULL) - sk_OPENSSL_STRING_free(osk); - OBJ_cleanup(); - apps_shutdown(); - OPENSSL_EXIT(ret); + BUF_MEM_free(buf); + OPENSSL_free(name); + OPENSSL_free(header); + if (strictpem) + OPENSSL_free(str); + ASN1_TYPE_free(at); + sk_OPENSSL_STRING_free(osk); + return ret; } -static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf) +static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf) { CONF *cnf = NULL; int len; - long errline = 0; unsigned char *p; ASN1_TYPE *atyp = NULL; - if (genconf) { - cnf = NCONF_new(NULL); - if (!NCONF_load(cnf, genconf, &errline)) - goto conferr; - if (!genstr) + if (genconf != NULL) { + if ((cnf = app_load_config(genconf)) == NULL) + goto err; + if (genstr == NULL) genstr = NCONF_get_string(cnf, "default", "asn1"); - if (!genstr) { - BIO_printf(bio, "Can't find 'asn1' in '%s'\n", genconf); + if (genstr == NULL) { + BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf); goto err; } } @@ -395,7 +332,7 @@ static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf) NCONF_free(cnf); cnf = NULL; - if (!atyp) + if (atyp == NULL) return -1; len = i2d_ASN1_TYPE(atyp, NULL); @@ -413,18 +350,8 @@ static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf) ASN1_TYPE_free(atyp); return len; - conferr: - - if (errline > 0) - BIO_printf(bio, "Error on line %ld of config file '%s'\n", - errline, genconf); - else - BIO_printf(bio, "Error loading config file '%s'\n", genconf); - err: NCONF_free(cnf); ASN1_TYPE_free(atyp); - return -1; - } diff --git a/apps/bf_prefix.c b/apps/bf_prefix.c new file mode 100644 index 000000000000..bae3c91bf8b3 --- /dev/null +++ b/apps/bf_prefix.c @@ -0,0 +1,177 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <openssl/bio.h> +#include "apps.h" + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten); +static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); +static int prefix_puts(BIO *b, const char *str); +static int prefix_gets(BIO *b, char *str, int size); +static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); +static int prefix_create(BIO *b); +static int prefix_destroy(BIO *b); +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); + +static BIO_METHOD *prefix_meth = NULL; + +BIO_METHOD *apps_bf_prefix(void) +{ + if (prefix_meth == NULL) { + if ((prefix_meth = + BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL + || !BIO_meth_set_create(prefix_meth, prefix_create) + || !BIO_meth_set_destroy(prefix_meth, prefix_destroy) + || !BIO_meth_set_write_ex(prefix_meth, prefix_write) + || !BIO_meth_set_read_ex(prefix_meth, prefix_read) + || !BIO_meth_set_puts(prefix_meth, prefix_puts) + || !BIO_meth_set_gets(prefix_meth, prefix_gets) + || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl) + || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) { + BIO_meth_free(prefix_meth); + prefix_meth = NULL; + } + } + return prefix_meth; +} + +typedef struct prefix_ctx_st { + char *prefix; + int linestart; /* flag to indicate we're at the line start */ +} PREFIX_CTX; + +static int prefix_create(BIO *b) +{ + PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + + ctx->prefix = NULL; + ctx->linestart = 1; + BIO_set_data(b, ctx); + BIO_set_init(b, 1); + return 1; +} + +static int prefix_destroy(BIO *b) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + OPENSSL_free(ctx->prefix); + OPENSSL_free(ctx); + return 1; +} + +static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) +{ + return BIO_read_ex(BIO_next(b), in, size, numread); +} + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + return 0; + + /* If no prefix is set or if it's empty, we've got nothing to do here */ + if (ctx->prefix == NULL || *ctx->prefix == '\0') { + /* We do note if what comes next will be a new line, though */ + if (outl > 0) + ctx->linestart = (out[outl-1] == '\n'); + return BIO_write_ex(BIO_next(b), out, outl, numwritten); + } + + *numwritten = 0; + + while (outl > 0) { + size_t i; + char c; + + /* If we know that we're at the start of the line, output the prefix */ + if (ctx->linestart) { + size_t dontcare; + + if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), + &dontcare)) + return 0; + ctx->linestart = 0; + } + + /* Now, go look for the next LF, or the end of the string */ + for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) + continue; + if (c == '\n') + i++; + + /* Output what we found so far */ + while (i > 0) { + size_t num = 0; + + if (!BIO_write_ex(BIO_next(b), out, i, &num)) + return 0; + out += num; + outl -= num; + *numwritten += num; + i -= num; + } + + /* If we found a LF, what follows is a new line, so take note */ + if (c == '\n') + ctx->linestart = 1; + } + + return 1; +} + +static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 0; + + switch (cmd) { + case PREFIX_CTRL_SET_PREFIX: + { + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + break; + + OPENSSL_free(ctx->prefix); + ctx->prefix = OPENSSL_strdup((const char *)ptr); + ret = ctx->prefix != NULL; + } + break; + default: + if (BIO_next(b) != NULL) + ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); + break; + } + return ret; +} + +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + return BIO_callback_ctrl(BIO_next(b), cmd, fp); +} + +static int prefix_gets(BIO *b, char *buf, int size) +{ + return BIO_gets(BIO_next(b), buf, size); +} + +static int prefix_puts(BIO *b, const char *str) +{ + return BIO_write(b, str, strlen(str)); +} diff --git a/apps/build.info b/apps/build.info new file mode 100644 index 000000000000..751d8da82818 --- /dev/null +++ b/apps/build.info @@ -0,0 +1,38 @@ +{- our @apps_openssl_src = + qw(openssl.c + asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c dhparam.c + dsa.c dsaparam.c ec.c ecparam.c enc.c engine.c errstr.c gendsa.c + genpkey.c genrsa.c nseq.c ocsp.c passwd.c pkcs12.c pkcs7.c pkcs8.c + pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c rsa.c rsautl.c + s_client.c s_server.c s_time.c sess_id.c smime.c speed.c spkac.c + srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c); + our @apps_lib_src = + ( qw(apps.c opt.c s_cb.c s_socket.c app_rand.c bf_prefix.c), + split(/\s+/, $target{apps_aux_src}) ); + our @apps_init_src = split(/\s+/, $target{apps_init_src}); + "" -} +IF[{- !$disabled{apps} -}] + LIBS_NO_INST=libapps.a + SOURCE[libapps.a]={- join(" ", @apps_lib_src) -} + INCLUDE[libapps.a]=.. ../include + + PROGRAMS=openssl + SOURCE[openssl]={- join(" ", @apps_init_src) -} + SOURCE[openssl]={- join(" ", @apps_openssl_src) -} + INCLUDE[openssl]=.. ../include + DEPEND[openssl]=libapps.a ../libssl + +IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}] + GENERATE[openssl.rc]=../util/mkrc.pl openssl + SOURCE[openssl]=openssl.rc +ENDIF + + {- join("\n ", map { (my $x = $_) =~ s|\.c$|.o|; "DEPEND[$x]=progs.h" } + @apps_openssl_src) -} + GENERATE[progs.h]=progs.pl $(APPS_OPENSSL) + DEPEND[progs.h]=../configdata.pm + + SCRIPTS=CA.pl tsget.pl + SOURCE[CA.pl]=CA.pl.in + SOURCE[tsget.pl]=tsget.in +ENDIF diff --git a/apps/ca-key.pem b/apps/ca-key.pem index 3a520b238f5b..4e742490637b 100644 --- a/apps/ca-key.pem +++ b/apps/ca-key.pem @@ -1,15 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQCju6PLddelT+nIMm07GQwmYa/eZ2JWbsmt2gotSCqM7asFp425 -gxSK4jqhhT62UPpqDBEwvQ+fYkVv3RV0r9ReuZGv12NoS4fXsQgqO17lHA7Od0Kd -2yNwJjKh44MxPKDt2o8iQMyZE0zlHnEFNpsP4COLTDNC6ljEEu5bk8uPsQIDAQAB -AoGAVZmpFZsDZfr0l2S9tLLwpjRWNOlKATQkno6q2WesT0eGLQufTciY+c8ypfU6 -hyio8r5iUl/VhhdjhAtKx1mRpiotftHo/eYf8rtsrnprOnWG0bWjLjtIoMbcxGn2 -J3bN6LJmbJMjDs0eJ3KnTu646F3nDUw2oGAwmpzKXA1KAP0CQQDRvQhxk2D3Pehs -HvG665u2pB5ipYQngEFlZO7RHJZzJOZEWSLuuMqaF/7pTfA5jiBvWqCgJeCRRInL -21ru4dlPAkEAx9jj7BgKn5TYnMoBSSe0afjsV9oApVpN1Nacb1YDtCwy+scp3++s -nFxlv98wxIlSdpwMUn+AUWfjiWR7Tu/G/wJBAJ/KjwZIrFVxewP0x2ILYsTRYLzz -MS4PDsO7FB+I0i7DbBOifXS2oNSpd3I0CNMwrxFnUHzynpbOStVfN3ZL5w0CQQCa -pwFahxBRhkJKsxhjoFJBX9yl75JoY4Wvm5Tbo9ih6UJaRx3kqfkN14L2BKYcsZgb -KY9vmDOYy6iNfjDeWTfJAkBkfPUb8oTJ/nSP5zN6sqGxSY4krc4xLxpRmxoJ8HL2 -XfhqXkTzbU13RX9JJ/NZ8vQN9Vm2NhxRGJocQkmcdVtJ ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL4tQNyKy4U2zX6l +IZvORB1edmwMwIgSB4cgoFECrG5pixzYxKauZkAwKG9/+L4DB8qXRjfXWcvafcOU +DlYpRROykJ7wGkiqmqbZyrxY8DWjk5ZZQXiSuhYOAJB+Fyfb11JZV6+CvBQX/1g+ +vhJr39Gmp6oAesoYrj90ecozClmnAgMBAAECgYA3j6sSg+5f9hnldUMzbPjTh8Sb +XsJlPrc6UFrmMBzGiUleXSpe9Dbla+x0XvQCN4pwMvAN4nnWp/f0Su5BV/9Y93nb +im5ijGNrfN9i6QrnqGCr+MMute+4E8HR2pCScX0mBLDDf40SmDvMzCaxtd21keyr +9DqHgInQZNEi6NKlkQJBAPCbUTFg6iQ6VTCQ8CsEf5q2xHhuTK23fJ999lvWVxN7 +QsvWb9RP9Ng34HVtvB7Pl6P7FyHLQYiDJhhvYR0L0+kCQQDKV/09Kt6Wjf5Omp1I +wd3A+tFnipdqnPw+qNHGjevv0hYiEIWQOYbx00zXgaX+WN/pzV9eeNN2XAxlNJ++ +dxcPAkBrzeuPKFFAcjKBVC+H1rgl5gYZv7Hzk+buv02G0H6rZ+sB0c7BXiHiTwbv +Fn/XfkP/YR14Ms3mEH0dLaphjU8hAkEAh3Ar/rRiN04mCcEuRFQXtaNtZSv8PA2G +Pf7MI2Y9pdHupLCAZlBLRjTUO2/5hu1AO4QPMPIZQSFN3rRBtMCL+wJAMp/m2hvI +TmtbMp/IrKGfma09e3yFiCmoNn7cHLJ7jLvXcacV2XNzpr9YHfBxiZo0g9FqZKvv +PZoQ5B2XJ7bhTQ== +-----END PRIVATE KEY----- diff --git a/apps/ca-req.pem b/apps/ca-req.pem index 77bf7ec308b5..84c6dbb68662 100644 --- a/apps/ca-req.pem +++ b/apps/ca-req.pem @@ -1,11 +1,11 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBmTCCAQICAQAwWzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQx -GjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYDVQQDExJUZXN0IENBICgx -MDI0IGJpdCkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKO7o8t116VP6cgy -bTsZDCZhr95nYlZuya3aCi1IKoztqwWnjbmDFIriOqGFPrZQ+moMETC9D59iRW/d -FXSv1F65ka/XY2hLh9exCCo7XuUcDs53Qp3bI3AmMqHjgzE8oO3ajyJAzJkTTOUe -cQU2mw/gI4tMM0LqWMQS7luTy4+xAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAKlk7 -cxu9gCJN3/iQFyJXQ6YphaiQAT5VBXTx9ftRrQIjA3vxlDzPWGDy+V5Tqa7h8PtR -5Bn00JShII2zf0hjyjKils6x/UkWmjEiwSiFp4hR70iE8XwSNEHY2P6j6nQEIpgW -kbfgmmUqk7dl2V+ossTJ80B8SBpEhrn81V/cHxA= +MIIBmzCCAQQCAQAwWzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClF1ZWVuc2xhbmQx +GjAYBgNVBAoMEUNyeXB0U29mdCBQdHkgTHRkMRswGQYDVQQDDBJUZXN0IENBICgx +MDI0IGJpdCkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL4tQNyKy4U2zX6l +IZvORB1edmwMwIgSB4cgoFECrG5pixzYxKauZkAwKG9/+L4DB8qXRjfXWcvafcOU +DlYpRROykJ7wGkiqmqbZyrxY8DWjk5ZZQXiSuhYOAJB+Fyfb11JZV6+CvBQX/1g+ +vhJr39Gmp6oAesoYrj90ecozClmnAgMBAAGgADANBgkqhkiG9w0BAQsFAAOBgQCo +2jE7J1SNV7kyRm9m8CoPw8xYsuVcVFxPheBymYp8BlO0/rSdYygRjobpYnLVRUPZ +pV792wzT1Rp4sXfZWO10lkFY4yi0pH2cdK2RX7qedibV1Xu9vt/yYANFBKVpA4dy +PRyTQwi3In1N8hdfddpYR8f5MIUYRe5poFMIJcf8JA== -----END CERTIFICATE REQUEST----- diff --git a/apps/ca.c b/apps/ca.c index 4f9de5492148..48f7cd197387 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1,63 +1,11 @@ -/* apps/ca.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ - -/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */ - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -77,30 +25,26 @@ #ifndef W_OK # ifdef OPENSSL_SYS_VMS -# if defined(__DECC) -# include <unistd.h> -# else -# include <unixlib.h> -# endif -# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) +# include <unistd.h> +# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) # include <sys/file.h> # endif #endif #include "apps.h" +#include "progs.h" #ifndef W_OK # define F_OK 0 -# define X_OK 1 # define W_OK 2 # define R_OK 4 #endif -#undef PROG -#define PROG ca_main +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif #define BASE_SECTION "ca" -#define CONFIG_FILE "openssl.cnf" #define ENV_DEFAULT_CA "default_ca" @@ -110,6 +54,7 @@ #define ENV_NEW_CERTS_DIR "new_certs_dir" #define ENV_CERTIFICATE "certificate" #define ENV_SERIAL "serial" +#define ENV_RAND_SERIAL "rand_serial" #define ENV_CRLNUMBER "crlnumber" #define ENV_PRIVATE_KEY "private_key" #define ENV_DEFAULT_DAYS "default_days" @@ -132,615 +77,471 @@ #define ENV_DATABASE "database" /* Additional revocation information types */ +typedef enum { + REV_VALID = -1, /* Valid (not-revoked) status */ + REV_NONE = 0, /* No additional information */ + REV_CRL_REASON = 1, /* Value is CRL reason code */ + REV_HOLD = 2, /* Value is hold instruction */ + REV_KEY_COMPROMISE = 3, /* Value is cert key compromise time */ + REV_CA_COMPROMISE = 4 /* Value is CA key compromise time */ +} REVINFO_TYPE; -#define REV_NONE 0 /* No addditional information */ -#define REV_CRL_REASON 1 /* Value is CRL reason code */ -#define REV_HOLD 2 /* Value is hold instruction */ -#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ -#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ +static char *lookup_conf(const CONF *conf, const char *group, const char *tag); -static const char *ca_usage[] = { - "usage: ca args\n", - "\n", - " -verbose - Talk alot while doing things\n", - " -config file - A config file\n", - " -name arg - The particular CA definition to use\n", - " -gencrl - Generate a new CRL\n", - " -crldays days - Days is when the next CRL is due\n", - " -crlhours hours - Hours is when the next CRL is due\n", - " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n", - " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n", - " -days arg - number of days to certify the certificate for\n", - " -md arg - md to use, one of md2, md5, sha or sha1\n", - " -policy arg - The CA 'policy' to support\n", - " -keyfile arg - private key file\n", - " -keyform arg - private key file format (PEM or ENGINE)\n", - " -key arg - key to decode the private key if it is encrypted\n", - " -cert file - The CA certificate\n", - " -selfsign - sign a certificate with the key associated with it\n", - " -in file - The input PEM encoded certificate request(s)\n", - " -out file - Where to put the output file(s)\n", - " -outdir dir - Where to put output certificates\n", - " -infiles .... - The last argument, requests to process\n", - " -spkac file - File contains DN and signed public key and challenge\n", - " -ss_cert file - File contains a self signed cert to sign\n", - " -preserveDN - Don't re-order the DN\n", - " -noemailDN - Don't add the EMAIL field into certificate' subject\n", - " -batch - Don't ask questions\n", - " -msie_hack - msie modifications to handle all those universal strings\n", - " -revoke file - Revoke a certificate (given in file)\n", - " -subj arg - Use arg instead of request's subject\n", - " -utf8 - input characters are UTF8 (default ASCII)\n", - " -multivalue-rdn - enable support for multivalued RDNs\n", - " -extensions .. - Extension section (override value in config file)\n", - " -extfile file - Configuration file with X509v3 extentions to add\n", - " -crlexts .. - CRL extension section (override value in config file)\n", -#ifndef OPENSSL_NO_ENGINE - " -engine e - use engine e, possibly a hardware device.\n", -#endif - " -status serial - Shows certificate status given the serial number\n", - " -updatedb - Updates db for expired certificates\n", - NULL -}; - -#ifdef EFENCE -extern int EF_PROTECT_FREE; -extern int EF_PROTECT_BELOW; -extern int EF_ALIGNMENT; -#endif - -static void lookup_fail(const char *name, const char *tag); -static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, char *enddate, - long days, int batch, char *ext_sect, CONF *conf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign); -static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, int batch, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy, - ENGINE *e); -static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, + unsigned long nameopt, int default_op, int ext_copy); +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, char *ext_sect, CONF *conf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy); -static void write_new_certificate(BIO *bp, X509 *x, int output_der, - int notext); static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, - char *subj, unsigned long chtype, int multirdn, - int email_dn, char *startdate, char *enddate, long days, - int batch, int verbose, X509_REQ *req, char *ext_sect, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *conf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign); -static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); static int get_certificate_status(const char *ser_status, CA_DB *db); static int do_updatedb(CA_DB *db); static int check_time_format(const char *str); -char *make_revocation_str(int rev_type, char *rev_arg); -int make_revoked(X509_REVOKED *rev, const char *str); -int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); -static CONF *conf = NULL; -static CONF *extconf = NULL; -static char *section = NULL; +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *extval); +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg); +static int make_revoked(X509_REVOKED *rev, const char *str); +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str); +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); +static CONF *extconf = NULL; static int preserve = 0; static int msie_hack = 0; -int MAIN(int, char **); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8, + OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE, + OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN, + OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR, + OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN, + OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, + OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, + OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, + OPT_RAND_SERIAL, + OPT_R_ENUM, + /* Do not change the order here; see related case statements below */ + OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE +} OPTION_CHOICE; -int MAIN(int argc, char **argv) +const OPTIONS ca_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output during processing"}, + {"config", OPT_CONFIG, 's', "A config file"}, + {"name", OPT_NAME, 's', "The particular CA definition to use"}, + {"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"}, + {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, + {"create_serial", OPT_CREATE_SERIAL, '-', + "If reading serial fails, create a new random serial"}, + {"rand_serial", OPT_RAND_SERIAL, '-', + "Always create a random serial; do not store it"}, + {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', + "Enable support for multivalued RDNs"}, + {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"}, + {"enddate", OPT_ENDDATE, 's', + "YYMMDDHHMMSSZ cert notAfter (overrides -days)"}, + {"days", OPT_DAYS, 'p', "Number of days to certify the cert for"}, + {"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"}, + {"policy", OPT_POLICY, 's', "The CA 'policy' to support"}, + {"keyfile", OPT_KEYFILE, 's', "Private key"}, + {"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"}, + {"cert", OPT_CERT, '<', "The CA cert"}, + {"selfsign", OPT_SELFSIGN, '-', + "Sign a cert with the key associated with it"}, + {"in", OPT_IN, '<', "The input PEM encoded cert request(s)"}, + {"out", OPT_OUT, '>', "Where to put the output file(s)"}, + {"outdir", OPT_OUTDIR, '/', "Where to put output cert"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"}, + {"batch", OPT_BATCH, '-', "Don't ask questions"}, + {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"}, + {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"}, + {"gencrl", OPT_GENCRL, '-', "Generate a new CRL"}, + {"msie_hack", OPT_MSIE_HACK, '-', + "msie modifications to handle all those universal strings"}, + {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"}, + {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"}, + {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"}, + {"infiles", OPT_INFILES, '-', "The last argument, requests to process"}, + {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"}, + {"spkac", OPT_SPKAC, '<', + "File contains DN and signed public key and challenge"}, + {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"}, + {"valid", OPT_VALID, 's', + "Add a Valid(not-revoked) DB entry about a cert (given in file)"}, + {"extensions", OPT_EXTENSIONS, 's', + "Extension section (override value in config file)"}, + {"extfile", OPT_EXTFILE, '<', + "Configuration file with X509v3 extensions to add"}, + {"status", OPT_STATUS, 's', "Shows cert status given the serial number"}, + {"updatedb", OPT_UPDATEDB, '-', "Updates db for expired cert"}, + {"crlexts", OPT_CRLEXTS, 's', + "CRL extension section (override value in config file)"}, + {"crl_reason", OPT_CRL_REASON, 's', "revocation reason"}, + {"crl_hold", OPT_CRL_HOLD, 's', + "the hold instruction, an OID. Sets revocation reason to certificateHold"}, + {"crl_compromise", OPT_CRL_COMPROMISE, 's', + "sets compromise time to val and the revocation reason to keyCompromise"}, + {"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's', + "sets compromise time to val and the revocation reason to CACompromise"}, + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int ca_main(int argc, char **argv) { + CONF *conf = NULL; ENGINE *e = NULL; - char *key = NULL, *passargin = NULL; - int create_ser = 0; - int free_key = 0; - int total = 0; - int total_done = 0; - int badops = 0; - int ret = 1; - int email_dn = 1; - int req = 0; - int verbose = 0; - int gencrl = 0; - int dorevoke = 0; - int doupdatedb = 0; - long crldays = 0; - long crlhours = 0; - long crlsec = 0; - long errorline = -1; - char *configfile = NULL; - char *md = NULL; - char *policy = NULL; - char *keyfile = NULL; - char *certfile = NULL; - int keyform = FORMAT_PEM; - char *infile = NULL; - char *spkac_file = NULL; - char *ss_cert_file = NULL; - char *ser_status = NULL; + BIGNUM *crlnumber = NULL, *serial = NULL; EVP_PKEY *pkey = NULL; - int output_der = 0; - char *outfile = NULL; - char *outdir = NULL; - char *serialfile = NULL; - char *crlnumberfile = NULL; - char *extensions = NULL; - char *extfile = NULL; - char *subj = NULL; - unsigned long chtype = MBSTRING_ASC; - int multirdn = 0; - char *tmp_email_dn = NULL; - char *crl_ext = NULL; - int rev_type = REV_NONE; - char *rev_arg = NULL; - BIGNUM *serial = NULL; - BIGNUM *crlnumber = NULL; - char *startdate = NULL; - char *enddate = NULL; - long days = 0; - int batch = 0; - int notext = 0; - unsigned long nameopt = 0, certopt = 0; - int default_op = 1; - int ext_copy = EXT_COPY_NONE; - int selfsign = 0; - X509 *x509 = NULL, *x509p = NULL; - X509 *x = NULL; - BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL; - char *dbfile = NULL; - CA_DB *db = NULL; - X509_CRL *crl = NULL; - X509_REVOKED *r = NULL; - ASN1_TIME *tmptm; + BIO *in = NULL, *out = NULL, *Sout = NULL; ASN1_INTEGER *tmpser; - char *f; - const char *p; - char *const *pp; - int i, j; - const EVP_MD *dgst = NULL; + ASN1_TIME *tmptm; + CA_DB *db = NULL; + DB_ATTR db_attr; STACK_OF(CONF_VALUE) *attribs = NULL; - STACK_OF(X509) *cert_sk = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL; -#undef BSIZE -#define BSIZE 256 - MS_STATIC char buf[3][BSIZE]; - char *randfile = NULL; - char *engine = NULL; - char *tofree = NULL; - DB_ATTR db_attr; - -#ifdef EFENCE - EF_PROTECT_FREE = 1; - EF_PROTECT_BELOW = 1; - EF_ALIGNMENT = 0; -#endif - - apps_startup(); - - conf = NULL; - key = NULL; - section = NULL; - - preserve = 0; - msie_hack = 0; - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); + STACK_OF(X509) *cert_sk = NULL; + X509_CRL *crl = NULL; + const EVP_MD *dgst = NULL; + char *configfile = default_config_file, *section = NULL; + char *md = NULL, *policy = NULL, *keyfile = NULL; + char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL; + const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL; + const char *extensions = NULL, *extfile = NULL, *passinarg = NULL; + char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL; + const char *serialfile = NULL, *subj = NULL; + char *prog, *startdate = NULL, *enddate = NULL; + char *dbfile = NULL, *f; + char new_cert[PATH_MAX]; + char tmp[10 + 1] = "\0"; + char *const *pp; + const char *p; + size_t outdirlen = 0; + int create_ser = 0, free_key = 0, total = 0, total_done = 0; + int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE; + int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0; + int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0; + int rand_ser = 0, i, j, selfsign = 0, def_nid, def_ret; + long crldays = 0, crlhours = 0, crlsec = 0, days = 0; + unsigned long chtype = MBSTRING_ASC, certopt = 0; + X509 *x509 = NULL, *x509p = NULL, *x = NULL; + REVINFO_TYPE rev_type = REV_NONE; + X509_REVOKED *r = NULL; + OPTION_CHOICE o; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-verbose") == 0) + prog = opt_init(argc, argv, ca_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ca_options); + ret = 0; + goto end; + case OPT_IN: + req = 1; + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_VERBOSE: verbose = 1; - else if (strcmp(*argv, "-config") == 0) { - if (--argc < 1) - goto bad; - configfile = *(++argv); - } else if (strcmp(*argv, "-name") == 0) { - if (--argc < 1) - goto bad; - section = *(++argv); - } else if (strcmp(*argv, "-subj") == 0) { - if (--argc < 1) - goto bad; - subj = *(++argv); + break; + case OPT_CONFIG: + configfile = opt_arg(); + break; + case OPT_NAME: + section = opt_arg(); + break; + case OPT_SUBJ: + subj = opt_arg(); /* preserve=1; */ - } else if (strcmp(*argv, "-utf8") == 0) + break; + case OPT_UTF8: chtype = MBSTRING_UTF8; - else if (strcmp(*argv, "-create_serial") == 0) + break; + case OPT_RAND_SERIAL: + rand_ser = 1; + break; + case OPT_CREATE_SERIAL: create_ser = 1; - else if (strcmp(*argv, "-multivalue-rdn") == 0) + break; + case OPT_MULTIVALUE_RDN: multirdn = 1; - else if (strcmp(*argv, "-startdate") == 0) { - if (--argc < 1) - goto bad; - startdate = *(++argv); - } else if (strcmp(*argv, "-enddate") == 0) { - if (--argc < 1) - goto bad; - enddate = *(++argv); - } else if (strcmp(*argv, "-days") == 0) { - if (--argc < 1) - goto bad; - days = atoi(*(++argv)); - } else if (strcmp(*argv, "-md") == 0) { - if (--argc < 1) - goto bad; - md = *(++argv); - } else if (strcmp(*argv, "-policy") == 0) { - if (--argc < 1) - goto bad; - policy = *(++argv); - } else if (strcmp(*argv, "-keyfile") == 0) { - if (--argc < 1) - goto bad; - keyfile = *(++argv); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - goto bad; - keyform = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-key") == 0) { - if (--argc < 1) - goto bad; - key = *(++argv); - } else if (strcmp(*argv, "-cert") == 0) { - if (--argc < 1) - goto bad; - certfile = *(++argv); - } else if (strcmp(*argv, "-selfsign") == 0) + break; + case OPT_STARTDATE: + startdate = opt_arg(); + break; + case OPT_ENDDATE: + enddate = opt_arg(); + break; + case OPT_DAYS: + days = atoi(opt_arg()); + break; + case OPT_MD: + md = opt_arg(); + break; + case OPT_POLICY: + policy = opt_arg(); + break; + case OPT_KEYFILE: + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) + goto opthelp; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_KEY: + key = opt_arg(); + break; + case OPT_CERT: + certfile = opt_arg(); + break; + case OPT_SELFSIGN: selfsign = 1; - else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - req = 1; - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-outdir") == 0) { - if (--argc < 1) - goto bad; - outdir = *(++argv); - } else if (strcmp(*argv, "-sigopt") == 0) { - if (--argc < 1) - goto bad; - if (!sigopts) + break; + case OPT_OUTDIR: + outdir = opt_arg(); + break; + case OPT_SIGOPT: + if (sigopts == NULL) sigopts = sk_OPENSSL_STRING_new_null(); - if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-notext") == 0) + if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto end; + break; + case OPT_NOTEXT: notext = 1; - else if (strcmp(*argv, "-batch") == 0) + break; + case OPT_BATCH: batch = 1; - else if (strcmp(*argv, "-preserveDN") == 0) + break; + case OPT_PRESERVEDN: preserve = 1; - else if (strcmp(*argv, "-noemailDN") == 0) + break; + case OPT_NOEMAILDN: email_dn = 0; - else if (strcmp(*argv, "-gencrl") == 0) + break; + case OPT_GENCRL: gencrl = 1; - else if (strcmp(*argv, "-msie_hack") == 0) + break; + case OPT_MSIE_HACK: msie_hack = 1; - else if (strcmp(*argv, "-crldays") == 0) { - if (--argc < 1) - goto bad; - crldays = atol(*(++argv)); - } else if (strcmp(*argv, "-crlhours") == 0) { - if (--argc < 1) - goto bad; - crlhours = atol(*(++argv)); - } else if (strcmp(*argv, "-crlsec") == 0) { - if (--argc < 1) - goto bad; - crlsec = atol(*(++argv)); - } else if (strcmp(*argv, "-infiles") == 0) { - argc--; - argv++; - req = 1; break; - } else if (strcmp(*argv, "-ss_cert") == 0) { - if (--argc < 1) - goto bad; - ss_cert_file = *(++argv); + case OPT_CRLDAYS: + crldays = atol(opt_arg()); + break; + case OPT_CRLHOURS: + crlhours = atol(opt_arg()); + break; + case OPT_CRLSEC: + crlsec = atol(opt_arg()); + break; + case OPT_INFILES: + req = 1; + goto end_of_options; + case OPT_SS_CERT: + ss_cert_file = opt_arg(); req = 1; - } else if (strcmp(*argv, "-spkac") == 0) { - if (--argc < 1) - goto bad; - spkac_file = *(++argv); + break; + case OPT_SPKAC: + spkac_file = opt_arg(); req = 1; - } else if (strcmp(*argv, "-revoke") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); + break; + case OPT_REVOKE: + infile = opt_arg(); dorevoke = 1; - } else if (strcmp(*argv, "-valid") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); + break; + case OPT_VALID: + infile = opt_arg(); dorevoke = 2; - } else if (strcmp(*argv, "-extensions") == 0) { - if (--argc < 1) - goto bad; - extensions = *(++argv); - } else if (strcmp(*argv, "-extfile") == 0) { - if (--argc < 1) - goto bad; - extfile = *(++argv); - } else if (strcmp(*argv, "-status") == 0) { - if (--argc < 1) - goto bad; - ser_status = *(++argv); - } else if (strcmp(*argv, "-updatedb") == 0) { + break; + case OPT_EXTENSIONS: + extensions = opt_arg(); + break; + case OPT_EXTFILE: + extfile = opt_arg(); + break; + case OPT_STATUS: + ser_status = opt_arg(); + break; + case OPT_UPDATEDB: doupdatedb = 1; - } else if (strcmp(*argv, "-crlexts") == 0) { - if (--argc < 1) - goto bad; - crl_ext = *(++argv); - } else if (strcmp(*argv, "-crl_reason") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_CRL_REASON; - } else if (strcmp(*argv, "-crl_hold") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_HOLD; - } else if (strcmp(*argv, "-crl_compromise") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_KEY_COMPROMISE; - } else if (strcmp(*argv, "-crl_CA_compromise") == 0) { - if (--argc < 1) - goto bad; - rev_arg = *(++argv); - rev_type = REV_CA_COMPROMISE; - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -#endif - else { - bad: - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_CRLEXTS: + crl_ext = opt_arg(); + break; + case OPT_CRL_REASON: /* := REV_CRL_REASON */ + case OPT_CRL_HOLD: + case OPT_CRL_COMPROMISE: + case OPT_CRL_CA_COMPROMISE: + rev_arg = opt_arg(); + rev_type = (o - OPT_CRL_REASON) + REV_CRL_REASON; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); break; } - argc--; - argv++; - } - - if (badops) { - const char **pp2; - - for (pp2 = ca_usage; (*pp2 != NULL); pp2++) - BIO_printf(bio_err, "%s", *pp2); - goto err; - } - - ERR_load_crypto_strings(); - - /*****************************************************************/ - tofree = NULL; - if (configfile == NULL) - configfile = getenv("OPENSSL_CONF"); - if (configfile == NULL) - configfile = getenv("SSLEAY_CONF"); - if (configfile == NULL) { - const char *s = X509_get_default_cert_area(); - size_t len; - -#ifdef OPENSSL_SYS_VMS - len = strlen(s) + sizeof(CONFIG_FILE); - tofree = OPENSSL_malloc(len); - if (!tofree) { - BIO_printf(bio_err, "Out of memory\n"); - goto err; - } - strcpy(tofree, s); -#else - len = strlen(s) + sizeof(CONFIG_FILE) + 1; - tofree = OPENSSL_malloc(len); - if (!tofree) { - BIO_printf(bio_err, "Out of memory\n"); - goto err; - } - BUF_strlcpy(tofree, s, len); - BUF_strlcat(tofree, "/", len); -#endif - BUF_strlcat(tofree, CONFIG_FILE, len); - configfile = tofree; } +end_of_options: + argc = opt_num_rest(); + argv = opt_rest(); BIO_printf(bio_err, "Using configuration from %s\n", configfile); - conf = NCONF_new(NULL); - if (NCONF_load(conf, configfile, &errorline) <= 0) { - if (errorline <= 0) - BIO_printf(bio_err, "error loading the config file '%s'\n", - configfile); - else - BIO_printf(bio_err, "error on line %ld of config file '%s'\n", - errorline, configfile); - goto err; - } - if (tofree) { - OPENSSL_free(tofree); - tofree = NULL; - } - - if (!load_config(bio_err, conf)) - goto err; - e = setup_engine(bio_err, engine, 0); + if ((conf = app_load_config(configfile)) == NULL) + goto end; + if (configfile != default_config_file && !app_load_modules(conf)) + goto end; /* Lets get the config section we are using */ - if (section == NULL) { - section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_CA); - if (section == NULL) { - lookup_fail(BASE_SECTION, ENV_DEFAULT_CA); - goto err; - } - } + if (section == NULL + && (section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_CA)) == NULL) + goto end; - if (conf != NULL) { - p = NCONF_get_string(conf, NULL, "oid_file"); - if (p == NULL) - ERR_clear_error(); - if (p != NULL) { - BIO *oid_bio; + p = NCONF_get_string(conf, NULL, "oid_file"); + if (p == NULL) + ERR_clear_error(); + if (p != NULL) { + BIO *oid_bio = BIO_new_file(p, "r"); - oid_bio = BIO_new_file(p, "r"); - if (oid_bio == NULL) { - /*- - BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); - ERR_print_errors(bio_err); - */ - ERR_clear_error(); - } else { - OBJ_create_objects(oid_bio); - BIO_free(oid_bio); - } - } - if (!add_oid_section(bio_err, conf)) { - ERR_print_errors(bio_err); - goto err; + if (oid_bio == NULL) { + ERR_clear_error(); + } else { + OBJ_create_objects(oid_bio); + BIO_free(oid_bio); } } + if (!add_oid_section(conf)) { + ERR_print_errors(bio_err); + goto end; + } - randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); - if (randfile == NULL) - ERR_clear_error(); - app_RAND_load_file(randfile, bio_err, 0); + app_RAND_load_conf(conf, BASE_SECTION); f = NCONF_get_string(conf, section, STRING_MASK); - if (!f) + if (f == NULL) ERR_clear_error(); - if (f && !ASN1_STRING_set_default_mask_asc(f)) { + if (f != NULL && !ASN1_STRING_set_default_mask_asc(f)) { BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); - goto err; + goto end; } if (chtype != MBSTRING_UTF8) { f = NCONF_get_string(conf, section, UTF8_IN); - if (!f) + if (f == NULL) ERR_clear_error(); - else if (!strcmp(f, "yes")) + else if (strcmp(f, "yes") == 0) chtype = MBSTRING_UTF8; } db_attr.unique_subject = 1; p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); - if (p) { -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p); -#endif + if (p != NULL) db_attr.unique_subject = parse_yesno(p, 1); - } else + else ERR_clear_error(); -#ifdef RL_DEBUG - if (!p) - BIO_printf(bio_err, "DEBUG: unique_subject undefined\n"); -#endif -#ifdef RL_DEBUG - BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n", - db_attr.unique_subject); -#endif - - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - Sout = BIO_new(BIO_s_file()); - Cout = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) { - ERR_print_errors(bio_err); - goto err; - } - /*****************************************************************/ + /*****************************************************************/ /* report status of cert with serial number given on command line */ if (ser_status) { - if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { - lookup_fail(section, ENV_DATABASE); - goto err; - } + dbfile = lookup_conf(conf, section, ENV_DATABASE); + if (dbfile == NULL) + goto end; + db = load_index(dbfile, &db_attr); if (db == NULL) - goto err; + goto end; - if (!index_index(db)) - goto err; + if (index_index(db) <= 0) + goto end; if (get_certificate_status(ser_status, db) != 1) BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status); - goto err; + goto end; } - /*****************************************************************/ + /*****************************************************************/ /* we definitely need a private key, so let's get it */ - if ((keyfile == NULL) && ((keyfile = NCONF_get_string(conf, - section, - ENV_PRIVATE_KEY)) == - NULL)) { - lookup_fail(section, ENV_PRIVATE_KEY); - goto err; - } - if (!key) { + if (keyfile == NULL + && (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL) + goto end; + + if (key == NULL) { free_key = 1; - if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) { + if (!app_passwd(passinarg, NULL, &key, NULL)) { BIO_printf(bio_err, "Error getting password\n"); - goto err; + goto end; } } - pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key"); - if (key) + pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key"); + if (key != NULL) OPENSSL_cleanse(key, strlen(key)); - if (pkey == NULL) { + if (pkey == NULL) /* load_key() has already printed an appropriate message */ - goto err; - } + goto end; - /*****************************************************************/ + /*****************************************************************/ /* we need a certificate */ if (!selfsign || spkac_file || ss_cert_file || gencrl) { - if ((certfile == NULL) - && ((certfile = NCONF_get_string(conf, - section, - ENV_CERTIFICATE)) == NULL)) { - lookup_fail(section, ENV_CERTIFICATE); - goto err; - } - x509 = load_cert(bio_err, certfile, FORMAT_PEM, NULL, e, - "CA certificate"); + if (certfile == NULL + && (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL) + goto end; + + x509 = load_cert(certfile, FORMAT_PEM, "CA certificate"); if (x509 == NULL) - goto err; + goto end; if (!X509_check_private_key(x509, pkey)) { BIO_printf(bio_err, "CA certificate and CA private key do not match\n"); - goto err; + goto end; } } if (!selfsign) @@ -759,86 +560,72 @@ int MAIN(int argc, char **argv) f = NCONF_get_string(conf, section, ENV_NAMEOPT); - if (f) { - if (!set_name_ex(&nameopt, f)) { + if (f != NULL) { + if (!set_nameopt(f)) { BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); - goto err; + goto end; } default_op = 0; - } else - ERR_clear_error(); + } f = NCONF_get_string(conf, section, ENV_CERTOPT); - if (f) { + if (f != NULL) { if (!set_cert_ex(&certopt, f)) { BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); - goto err; + goto end; } default_op = 0; - } else + } else { ERR_clear_error(); + } f = NCONF_get_string(conf, section, ENV_EXTCOPY); - if (f) { + if (f != NULL) { if (!set_ext_copy(&ext_copy, f)) { BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); - goto err; + goto end; } - } else + } else { ERR_clear_error(); + } - /*****************************************************************/ + /*****************************************************************/ /* lookup where to write new certificates */ if ((outdir == NULL) && (req)) { - if ((outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR)) - == NULL) { + outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR); + if (outdir == NULL) { BIO_printf(bio_err, "there needs to be defined a directory for new certificate to be placed in\n"); - goto err; + goto end; } #ifndef OPENSSL_SYS_VMS /* * outdir is a directory spec, but access() for VMS demands a - * filename. In any case, stat(), below, will catch the problem if - * outdir is not a directory spec, and the fopen() or open() will - * catch an error if there is no write access. - * - * Presumably, this problem could also be solved by using the DEC C - * routines to convert the directory syntax to Unixly, and give that - * to access(). However, time's too short to do that just now. + * filename. We could use the DEC C routine to convert the + * directory syntax to Unixly, and give that to app_isdir, + * but for now the fopen will catch the error if it's not a + * directory */ -# ifndef _WIN32 - if (access(outdir, R_OK | W_OK | X_OK) != 0) -# else - if (_access(outdir, R_OK | W_OK | X_OK) != 0) -# endif - { - BIO_printf(bio_err, "I am unable to access the %s directory\n", - outdir); - perror(outdir); - goto err; - } - if (app_isdir(outdir) <= 0) { - BIO_printf(bio_err, "%s need to be a directory\n", outdir); + BIO_printf(bio_err, "%s: %s is not a directory\n", prog, outdir); perror(outdir); - goto err; + goto end; } #endif } - /*****************************************************************/ + /*****************************************************************/ /* we need to load the database file */ - if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { - lookup_fail(section, ENV_DATABASE); - goto err; - } + dbfile = lookup_conf(conf, section, ENV_DATABASE); + if (dbfile == NULL) + goto end; + db = load_index(dbfile, &db_attr); if (db == NULL) - goto err; + goto end; /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { @@ -847,16 +634,16 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "entry %d: not revoked yet, but has a revocation date\n", i + 1); - goto err; + goto end; } if ((pp[DB_type][0] == DB_TYPE_REV) && !make_revoked(NULL, pp[DB_rev_date])) { BIO_printf(bio_err, " in entry %d\n", i + 1); - goto err; + goto end; } if (!check_time_format((char *)pp[DB_exp_date])) { BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1); - goto err; + goto end; } p = pp[DB_serial]; j = strlen(p); @@ -867,38 +654,28 @@ int MAIN(int argc, char **argv) if ((j & 1) || (j < 2)) { BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n", i + 1, j); - goto err; + goto end; } - while (*p) { - if (!(((*p >= '0') && (*p <= '9')) || - ((*p >= 'A') && (*p <= 'F')) || - ((*p >= 'a') && (*p <= 'f')))) { + for ( ; *p; p++) { + if (!isxdigit(_UC(*p))) { BIO_printf(bio_err, - "entry %d: bad serial number characters, char pos %ld, char is '%c'\n", - i + 1, (long)(p - pp[DB_serial]), *p); - goto err; + "entry %d: bad char 0%o '%c' in serial number\n", + i + 1, *p, *p); + goto end; } - p++; } } if (verbose) { - BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); /* cannot fail */ -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - TXT_DB_write(out, db->db); + TXT_DB_write(bio_out, db->db); BIO_printf(bio_err, "%d entries loaded from the database\n", sk_OPENSSL_PSTRING_num(db->db->data)); BIO_printf(bio_err, "generating index\n"); } - if (!index_index(db)) - goto err; + if (index_index(db) <= 0) + goto end; - /*****************************************************************/ + /*****************************************************************/ /* Update the db file for expired certificates */ if (doupdatedb) { if (verbose) @@ -907,37 +684,28 @@ int MAIN(int argc, char **argv) i = do_updatedb(db); if (i == -1) { BIO_printf(bio_err, "Malloc failure\n"); - goto err; + goto end; } else if (i == 0) { if (verbose) BIO_printf(bio_err, "No entries found to mark expired\n"); } else { if (!save_index(dbfile, "new", db)) - goto err; + goto end; if (!rotate_index(dbfile, "new", "old")) - goto err; + goto end; if (verbose) - BIO_printf(bio_err, - "Done. %d entries marked as expired\n", i); + BIO_printf(bio_err, "Done. %d entries marked as expired\n", i); } } - /*****************************************************************/ - /* Read extentions config file */ + /*****************************************************************/ + /* Read extensions config file */ if (extfile) { - extconf = NCONF_new(NULL); - if (NCONF_load(extconf, extfile, &errorline) <= 0) { - if (errorline <= 0) - BIO_printf(bio_err, "ERROR: loading the config file '%s'\n", - extfile); - else - BIO_printf(bio_err, - "ERROR: on line %ld of config file '%s'\n", - errorline, extfile); + if ((extconf = app_load_config(extfile)) == NULL) { ret = 1; - goto err; + goto end; } if (verbose) @@ -945,89 +713,82 @@ int MAIN(int argc, char **argv) extfile); /* We can have sections in the ext file */ - if (!extensions - && !(extensions = - NCONF_get_string(extconf, "default", "extensions"))) - extensions = "default"; + if (extensions == NULL) { + extensions = NCONF_get_string(extconf, "default", "extensions"); + if (extensions == NULL) + extensions = "default"; + } } - /*****************************************************************/ + /*****************************************************************/ if (req || gencrl) { - if (outfile != NULL) { - if (BIO_write_filename(Sout, outfile) <= 0) { - perror(outfile); - goto err; - } - } else { - BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - Sout = BIO_push(tmpbio, Sout); - } -#endif + if (spkac_file != NULL) { + output_der = 1; + batch = 1; } } - if ((md == NULL) && ((md = NCONF_get_string(conf, - section, - ENV_DEFAULT_MD)) == NULL)) { - lookup_fail(section, ENV_DEFAULT_MD); - goto err; - } - - if (!strcmp(md, "default")) { - int def_nid; - if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) { - BIO_puts(bio_err, "no default digest\n"); - goto err; + def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid); + /* + * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is + * mandatory for this algorithm. + */ + if (def_ret == 2 && def_nid == NID_undef) { + /* The signing algorithm requires there to be no digest */ + dgst = EVP_md_null(); + } else if (md == NULL + && (md = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) { + goto end; + } else { + if (strcmp(md, "default") == 0) { + if (def_ret <= 0) { + BIO_puts(bio_err, "no default digest\n"); + goto end; + } + md = (char *)OBJ_nid2sn(def_nid); } - md = (char *)OBJ_nid2sn(def_nid); - } - if ((dgst = EVP_get_digestbyname(md)) == NULL) { - BIO_printf(bio_err, "%s is an unsupported message digest type\n", md); - goto err; + if (!opt_md(md, &dgst)) + goto end; } if (req) { - if ((email_dn == 1) && ((tmp_email_dn = NCONF_get_string(conf, - section, - ENV_DEFAULT_EMAIL_DN)) - != NULL)) { - if (strcmp(tmp_email_dn, "no") == 0) + if (email_dn == 1) { + char *tmp_email_dn = NULL; + + tmp_email_dn = NCONF_get_string(conf, section, ENV_DEFAULT_EMAIL_DN); + if (tmp_email_dn != NULL && strcmp(tmp_email_dn, "no") == 0) email_dn = 0; } if (verbose) BIO_printf(bio_err, "message digest is %s\n", - OBJ_nid2ln(dgst->type)); - if ((policy == NULL) && ((policy = NCONF_get_string(conf, - section, - ENV_POLICY)) == - NULL)) { - lookup_fail(section, ENV_POLICY); - goto err; - } + OBJ_nid2ln(EVP_MD_type(dgst))); + if (policy == NULL + && (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL) + goto end; + if (verbose) BIO_printf(bio_err, "policy is %s\n", policy); - if ((serialfile = NCONF_get_string(conf, section, ENV_SERIAL)) - == NULL) { - lookup_fail(section, ENV_SERIAL); - goto err; + if (NCONF_get_string(conf, section, ENV_RAND_SERIAL) != NULL) { + rand_ser = 1; + } else { + serialfile = lookup_conf(conf, section, ENV_SERIAL); + if (serialfile == NULL) + goto end; } - if (!extconf) { + if (extconf == NULL) { /* * no '-extfile' option, so we look for extensions in the main * configuration file */ - if (!extensions) { + if (extensions == NULL) { extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS); - if (!extensions) + if (extensions == NULL) ERR_clear_error(); } - if (extensions) { + if (extensions != NULL) { /* Check syntax of file */ X509V3_CTX ctx; X509V3_set_ctx_test(&ctx); @@ -1037,21 +798,20 @@ int MAIN(int argc, char **argv) "Error Loading extension section %s\n", extensions); ret = 1; - goto err; + goto end; } } } if (startdate == NULL) { - startdate = NCONF_get_string(conf, section, - ENV_DEFAULT_STARTDATE); + startdate = NCONF_get_string(conf, section, ENV_DEFAULT_STARTDATE); if (startdate == NULL) ERR_clear_error(); } - if (startdate && !ASN1_TIME_set_string(NULL, startdate)) { + if (startdate != NULL && !ASN1_TIME_set_string_X509(NULL, startdate)) { BIO_printf(bio_err, "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); - goto err; + goto end; } if (startdate == NULL) startdate = "today"; @@ -1061,67 +821,69 @@ int MAIN(int argc, char **argv) if (enddate == NULL) ERR_clear_error(); } - if (enddate && !ASN1_TIME_set_string(NULL, enddate)) { + if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) { BIO_printf(bio_err, "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); - goto err; + goto end; } if (days == 0) { if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days)) days = 0; } - if (!enddate && (days == 0)) { - BIO_printf(bio_err, - "cannot lookup how many days to certify for\n"); - goto err; + if (enddate == NULL && days == 0) { + BIO_printf(bio_err, "cannot lookup how many days to certify for\n"); + goto end; } - if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) { - BIO_printf(bio_err, "error while loading serial number\n"); - goto err; - } - if (verbose) { - if (BN_is_zero(serial)) - BIO_printf(bio_err, "next serial number is 00\n"); - else { - if ((f = BN_bn2hex(serial)) == NULL) - goto err; - BIO_printf(bio_err, "next serial number is %s\n", f); - OPENSSL_free(f); + if (rand_ser) { + if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) { + BIO_printf(bio_err, "error generating serial number\n"); + goto end; + } + } else { + if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) { + BIO_printf(bio_err, "error while loading serial number\n"); + goto end; + } + if (verbose) { + if (BN_is_zero(serial)) { + BIO_printf(bio_err, "next serial number is 00\n"); + } else { + if ((f = BN_bn2hex(serial)) == NULL) + goto end; + BIO_printf(bio_err, "next serial number is %s\n", f); + OPENSSL_free(f); + } } } if ((attribs = NCONF_get_section(conf, policy)) == NULL) { BIO_printf(bio_err, "unable to find 'section' for %s\n", policy); - goto err; + goto end; } if ((cert_sk = sk_X509_new_null()) == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } if (spkac_file != NULL) { total++; j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, extensions, - conf, verbose, certopt, nameopt, default_op, + conf, verbose, certopt, get_nameopt(), default_op, ext_copy); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); if (!BN_add_word(serial, 1)) - goto err; + goto end; if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; - } - if (outfile) { - output_der = 1; - batch = 1; + goto end; } } } @@ -1131,18 +893,18 @@ int MAIN(int argc, char **argv) attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, - conf, verbose, certopt, nameopt, default_op, - ext_copy, e); + conf, verbose, certopt, get_nameopt(), default_op, + ext_copy); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); if (!BN_add_word(serial, 1)) - goto err; + goto end; if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } } @@ -1151,17 +913,17 @@ int MAIN(int argc, char **argv) j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, nameopt, default_op, ext_copy, selfsign); + certopt, get_nameopt(), default_op, ext_copy, selfsign); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); if (!BN_add_word(serial, 1)) - goto err; + goto end; if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } } @@ -1170,17 +932,20 @@ int MAIN(int argc, char **argv) j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, nameopt, default_op, ext_copy, selfsign); + certopt, get_nameopt(), default_op, ext_copy, selfsign); if (j < 0) - goto err; + goto end; if (j > 0) { total_done++; BIO_printf(bio_err, "\n"); - if (!BN_add_word(serial, 1)) - goto err; + if (!BN_add_word(serial, 1)) { + X509_free(x); + goto end; + } if (!sk_X509_push(cert_sk, x)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + X509_free(x); + goto end; } } } @@ -1195,61 +960,58 @@ int MAIN(int argc, char **argv) "\n%d out of %d certificate requests certified, commit? [y/n]", total_done, total); (void)BIO_flush(bio_err); - buf[0][0] = '\0'; - if (!fgets(buf[0], 10, stdin)) { - BIO_printf(bio_err, - "CERTIFICATION CANCELED: I/O error\n"); + tmp[0] = '\0'; + if (fgets(tmp, sizeof(tmp), stdin) == NULL) { + BIO_printf(bio_err, "CERTIFICATION CANCELED: I/O error\n"); ret = 0; - goto err; + goto end; } - if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) { + if (tmp[0] != 'y' && tmp[0] != 'Y') { BIO_printf(bio_err, "CERTIFICATION CANCELED\n"); ret = 0; - goto err; + goto end; } } BIO_printf(bio_err, "Write out database with %d new entries\n", sk_X509_num(cert_sk)); - if (!save_serial(serialfile, "new", serial, NULL)) - goto err; + if (!rand_ser + && !save_serial(serialfile, "new", serial, NULL)) + goto end; if (!save_index(dbfile, "new", db)) - goto err; + goto end; } + outdirlen = OPENSSL_strlcpy(new_cert, outdir, sizeof(new_cert)); +#ifndef OPENSSL_SYS_VMS + outdirlen = OPENSSL_strlcat(new_cert, "/", sizeof(new_cert)); +#endif + if (verbose) BIO_printf(bio_err, "writing new certificates\n"); - for (i = 0; i < sk_X509_num(cert_sk); i++) { - int k; - char *n; - - x = sk_X509_value(cert_sk, i); - j = x->cert_info->serialNumber->length; - p = (const char *)x->cert_info->serialNumber->data; + for (i = 0; i < sk_X509_num(cert_sk); i++) { + BIO *Cout = NULL; + X509 *xi = sk_X509_value(cert_sk, i); + ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi); + const unsigned char *psn = ASN1_STRING_get0_data(serialNumber); + const int snl = ASN1_STRING_length(serialNumber); + const int filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem"); + char *n = new_cert + outdirlen; - if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) { + if (outdirlen + filen_len > PATH_MAX) { BIO_printf(bio_err, "certificate file name too long\n"); - goto err; + goto end; } - strcpy(buf[2], outdir); + if (snl > 0) { + static const char HEX_DIGITS[] = "0123456789ABCDEF"; -#ifndef OPENSSL_SYS_VMS - BUF_strlcat(buf[2], "/", sizeof(buf[2])); -#endif - - n = (char *)&(buf[2][strlen(buf[2])]); - if (j > 0) { - for (k = 0; k < j; k++) { - if (n >= &(buf[2][sizeof(buf[2])])) - break; - BIO_snprintf(n, - &buf[2][0] + sizeof(buf[2]) - n, - "%02X", (unsigned char)*(p++)); - n += 2; + for (j = 0; j < snl; j++, psn++) { + *n++ = HEX_DIGITS[*psn >> 4]; + *n++ = HEX_DIGITS[*psn & 0x0F]; } } else { *(n++) = '0'; @@ -1259,49 +1021,57 @@ int MAIN(int argc, char **argv) *(n++) = 'p'; *(n++) = 'e'; *(n++) = 'm'; - *n = '\0'; + *n = '\0'; /* closing new_cert */ if (verbose) - BIO_printf(bio_err, "writing %s\n", buf[2]); + BIO_printf(bio_err, "writing %s\n", new_cert); + + Sout = bio_open_default(outfile, 'w', + output_der ? FORMAT_ASN1 : FORMAT_TEXT); + if (Sout == NULL) + goto end; - if (BIO_write_filename(Cout, buf[2]) <= 0) { - perror(buf[2]); - goto err; + Cout = BIO_new_file(new_cert, "w"); + if (Cout == NULL) { + perror(new_cert); + goto end; } - write_new_certificate(Cout, x, 0, notext); - write_new_certificate(Sout, x, output_der, notext); + write_new_certificate(Cout, xi, 0, notext); + write_new_certificate(Sout, xi, output_der, notext); + BIO_free_all(Cout); + BIO_free_all(Sout); + Sout = NULL; } if (sk_X509_num(cert_sk)) { /* Rename the database and the serial file */ if (!rotate_serial(serialfile, "new", "old")) - goto err; + goto end; if (!rotate_index(dbfile, "new", "old")) - goto err; + goto end; BIO_printf(bio_err, "Data Base Updated\n"); } } - /*****************************************************************/ + /*****************************************************************/ if (gencrl) { int crl_v2 = 0; - if (!crl_ext) { + if (crl_ext == NULL) { crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT); - if (!crl_ext) + if (crl_ext == NULL) ERR_clear_error(); } - if (crl_ext) { + if (crl_ext != NULL) { /* Check syntax of file */ X509V3_CTX ctx; X509V3_set_ctx_test(&ctx); X509V3_set_nconf(&ctx, conf); if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) { BIO_printf(bio_err, - "Error Loading CRL extension section %s\n", - crl_ext); + "Error Loading CRL extension section %s\n", crl_ext); ret = 1; - goto err; + goto end; } } @@ -1309,7 +1079,7 @@ int MAIN(int argc, char **argv) != NULL) if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) { BIO_printf(bio_err, "error while loading CRL number\n"); - goto err; + goto end; } if (!crldays && !crlhours && !crlsec) { @@ -1324,27 +1094,27 @@ int MAIN(int argc, char **argv) if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) { BIO_printf(bio_err, "cannot lookup how long until the next CRL is issued\n"); - goto err; + goto end; } if (verbose) BIO_printf(bio_err, "making CRL\n"); if ((crl = X509_CRL_new()) == NULL) - goto err; + goto end; if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) - goto err; + goto end; tmptm = ASN1_TIME_new(); - if (!tmptm) - goto err; - X509_gmtime_adj(tmptm, 0); - X509_CRL_set_lastUpdate(crl, tmptm); - if (!X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec, - NULL)) { + if (tmptm == NULL + || X509_gmtime_adj(tmptm, 0) == NULL + || !X509_CRL_set1_lastUpdate(crl, tmptm) + || X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec, + NULL) == NULL) { BIO_puts(bio_err, "error setting CRL nextUpdate\n"); - goto err; + ASN1_TIME_free(tmptm); + goto end; } - X509_CRL_set_nextUpdate(crl, tmptm); + X509_CRL_set1_nextUpdate(crl, tmptm); ASN1_TIME_free(tmptm); @@ -1352,19 +1122,19 @@ int MAIN(int argc, char **argv) pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_type][0] == DB_TYPE_REV) { if ((r = X509_REVOKED_new()) == NULL) - goto err; + goto end; j = make_revoked(r, pp[DB_rev_date]); if (!j) - goto err; + goto end; if (j == 2) crl_v2 = 1; if (!BN_hex2bn(&serial, pp[DB_serial])) - goto err; + goto end; tmpser = BN_to_ASN1_INTEGER(serial, NULL); BN_free(serial); serial = NULL; if (!tmpser) - goto err; + goto end; X509_REVOKED_set_serialNumber(r, tmpser); ASN1_INTEGER_free(tmpser); X509_CRL_add0_revoked(crl, r); @@ -1382,122 +1152,120 @@ int MAIN(int argc, char **argv) /* Add any extensions asked for */ - if (crl_ext || crlnumberfile != NULL) { + if (crl_ext != NULL || crlnumberfile != NULL) { X509V3_CTX crlctx; X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); X509V3_set_nconf(&crlctx, conf); - if (crl_ext) + if (crl_ext != NULL) if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) - goto err; + goto end; if (crlnumberfile != NULL) { tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); if (!tmpser) - goto err; + goto end; X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0); ASN1_INTEGER_free(tmpser); crl_v2 = 1; if (!BN_add_word(crlnumber, 1)) - goto err; + goto end; } } - if (crl_ext || crl_v2) { + if (crl_ext != NULL || crl_v2) { if (!X509_CRL_set_version(crl, 1)) - goto err; /* version 2 CRL */ + goto end; /* version 2 CRL */ } /* we have a CRL number that need updating */ if (crlnumberfile != NULL) - if (!save_serial(crlnumberfile, "new", crlnumber, NULL)) - goto err; + if (!rand_ser + && !save_serial(crlnumberfile, "new", crlnumber, NULL)) + goto end; - if (crlnumber) { - BN_free(crlnumber); - crlnumber = NULL; - } + BN_free(crlnumber); + crlnumber = NULL; + + if (!do_X509_CRL_sign(crl, pkey, dgst, sigopts)) + goto end; - if (!do_X509_CRL_sign(bio_err, crl, pkey, dgst, sigopts)) - goto err; + Sout = bio_open_default(outfile, 'w', + output_der ? FORMAT_ASN1 : FORMAT_TEXT); + if (Sout == NULL) + goto end; PEM_write_bio_X509_CRL(Sout, crl); if (crlnumberfile != NULL) /* Rename the crlnumber file */ if (!rotate_serial(crlnumberfile, "new", "old")) - goto err; + goto end; } - /*****************************************************************/ + /*****************************************************************/ if (dorevoke) { if (infile == NULL) { BIO_printf(bio_err, "no input files\n"); - goto err; + goto end; } else { X509 *revcert; - revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile); + revcert = load_cert(infile, FORMAT_PEM, infile); if (revcert == NULL) - goto err; + goto end; if (dorevoke == 2) - rev_type = -1; + rev_type = REV_VALID; j = do_revoke(revcert, db, rev_type, rev_arg); if (j <= 0) - goto err; + goto end; X509_free(revcert); if (!save_index(dbfile, "new", db)) - goto err; + goto end; if (!rotate_index(dbfile, "new", "old")) - goto err; + goto end; BIO_printf(bio_err, "Data Base Updated\n"); } } - /*****************************************************************/ ret = 0; - err: - if (tofree) - OPENSSL_free(tofree); - BIO_free_all(Cout); + + end: + if (ret) + ERR_print_errors(bio_err); BIO_free_all(Sout); BIO_free_all(out); BIO_free_all(in); + sk_X509_pop_free(cert_sk, X509_free); - if (cert_sk) - sk_X509_pop_free(cert_sk, X509_free); - - if (ret) - ERR_print_errors(bio_err); - app_RAND_write_file(randfile, bio_err); - if (free_key && key) + if (free_key) OPENSSL_free(key); BN_free(serial); BN_free(crlnumber); free_index(db); - if (sigopts) - sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(sigopts); EVP_PKEY_free(pkey); - if (x509) - X509_free(x509); + X509_free(x509); X509_CRL_free(crl); NCONF_free(conf); NCONF_free(extconf); release_engine(e); - OBJ_cleanup(); - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } -static void lookup_fail(const char *name, const char *tag) +static char *lookup_conf(const CONF *conf, const char *section, const char *tag) { - BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag); + char *entry = NCONF_get_string(conf, section, tag); + if (entry == NULL) + BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag); + return entry; } -static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, char *enddate, - long days, int batch, char *ext_sect, CONF *lconf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) { @@ -1506,19 +1274,18 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, EVP_PKEY *pktmp = NULL; int ok = -1, i; - in = BIO_new(BIO_s_file()); - - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto err; + in = BIO_new_file(infile, "r"); + if (in == NULL) { + ERR_print_errors(bio_err); + goto end; } if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) { BIO_printf(bio_err, "Error reading certificate request in %s\n", infile); - goto err; + goto end; } if (verbose) - X509_REQ_print(bio_err, req); + X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT); BIO_printf(bio_err, "Check that the request matches the signature\n"); @@ -1526,116 +1293,109 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "Certificate request and CA private key do not match\n"); ok = 0; - goto err; + goto end; } - if ((pktmp = X509_REQ_get_pubkey(req)) == NULL) { + if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); - goto err; + goto end; } i = X509_REQ_verify(req, pktmp); - EVP_PKEY_free(pktmp); + pktmp = NULL; if (i < 0) { ok = 0; BIO_printf(bio_err, "Signature verification problems....\n"); ERR_print_errors(bio_err); - goto err; + goto end; } if (i == 0) { ok = 0; BIO_printf(bio_err, "Signature did not match the certificate request\n"); ERR_print_errors(bio_err); - goto err; - } else + goto end; + } else { BIO_printf(bio_err, "Signature ok\n"); + } ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, verbose, req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, selfsign); - err: - if (req != NULL) - X509_REQ_free(req); - if (in != NULL) - BIO_free(in); - return (ok); + end: + X509_REQ_free(req); + BIO_free(in); + return ok; } -static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, int batch, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy, - ENGINE *e) + unsigned long nameopt, int default_op, int ext_copy) { X509 *req = NULL; X509_REQ *rreq = NULL; EVP_PKEY *pktmp = NULL; int ok = -1, i; - if ((req = - load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL) - goto err; + if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL) + goto end; if (verbose) X509_print(bio_err, req); BIO_printf(bio_err, "Check that the request matches the signature\n"); - if ((pktmp = X509_get_pubkey(req)) == NULL) { + if ((pktmp = X509_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); - goto err; + goto end; } i = X509_verify(req, pktmp); - EVP_PKEY_free(pktmp); if (i < 0) { ok = 0; BIO_printf(bio_err, "Signature verification problems....\n"); - goto err; + goto end; } if (i == 0) { ok = 0; BIO_printf(bio_err, "Signature did not match the certificate\n"); - goto err; - } else + goto end; + } else { BIO_printf(bio_err, "Signature ok\n"); + } - if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL) - goto err; + if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL) + goto end; ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, 0); - err: - if (rreq != NULL) - X509_REQ_free(rreq); - if (req != NULL) - X509_free(req); - return (ok); + end: + X509_REQ_free(rreq); + X509_free(req); + return ok; } static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, - char *subj, unsigned long chtype, int multirdn, - int email_dn, char *startdate, char *enddate, long days, - int batch, int verbose, X509_REQ *req, char *ext_sect, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *lconf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) { X509_NAME *name = NULL, *CAname = NULL, *subject = NULL; - ASN1_UTCTIME *tm, *tmptm; + const ASN1_TIME *tm; ASN1_STRING *str, *str2; ASN1_OBJECT *obj; X509 *ret = NULL; - X509_CINF *ci; - X509_NAME_ENTRY *ne; - X509_NAME_ENTRY *tne, *push; + X509_NAME_ENTRY *ne, *tne; EVP_PKEY *pktmp; int ok = -1, i, j, last, nid; const char *p; @@ -1645,12 +1405,6 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, OPENSSL_STRING *rrow = NULL; char buf[25]; - tmptm = ASN1_UTCTIME_new(); - if (tmptm == NULL) { - BIO_printf(bio_err, "malloc error\n"); - return (0); - } - for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; @@ -1659,80 +1413,74 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (!n) { ERR_print_errors(bio_err); - goto err; + goto end; } X509_REQ_set_subject_name(req, n); - req->req_info->enc.modified = 1; X509_NAME_free(n); } if (default_op) - BIO_printf(bio_err, - "The Subject's Distinguished Name is as follows\n"); + BIO_printf(bio_err, "The Subject's Distinguished Name is as follows\n"); name = X509_REQ_get_subject_name(req); for (i = 0; i < X509_NAME_entry_count(name); i++) { ne = X509_NAME_get_entry(name, i); str = X509_NAME_ENTRY_get_data(ne); obj = X509_NAME_ENTRY_get_object(ne); + nid = OBJ_obj2nid(obj); if (msie_hack) { /* assume all type should be strings */ - nid = OBJ_obj2nid(ne->object); if (str->type == V_ASN1_UNIVERSALSTRING) ASN1_UNIVERSALSTRING_to_string(str); - if ((str->type == V_ASN1_IA5STRING) && - (nid != NID_pkcs9_emailAddress)) + if (str->type == V_ASN1_IA5STRING && nid != NID_pkcs9_emailAddress) str->type = V_ASN1_T61STRING; - if ((nid == NID_pkcs9_emailAddress) && - (str->type == V_ASN1_PRINTABLESTRING)) + if (nid == NID_pkcs9_emailAddress + && str->type == V_ASN1_PRINTABLESTRING) str->type = V_ASN1_IA5STRING; } /* If no EMAIL is wanted in the subject */ - if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) + if (nid == NID_pkcs9_emailAddress && !email_dn) continue; /* check some things */ - if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && - (str->type != V_ASN1_IA5STRING)) { + if (nid == NID_pkcs9_emailAddress && str->type != V_ASN1_IA5STRING) { BIO_printf(bio_err, "\nemailAddress type needs to be of type IA5STRING\n"); - goto err; + goto end; } - if ((str->type != V_ASN1_BMPSTRING) - && (str->type != V_ASN1_UTF8STRING)) { + if (str->type != V_ASN1_BMPSTRING && str->type != V_ASN1_UTF8STRING) { j = ASN1_PRINTABLE_type(str->data, str->length); - if (((j == V_ASN1_T61STRING) && - (str->type != V_ASN1_T61STRING)) || - ((j == V_ASN1_IA5STRING) && - (str->type == V_ASN1_PRINTABLESTRING))) { + if ((j == V_ASN1_T61STRING && str->type != V_ASN1_T61STRING) || + (j == V_ASN1_IA5STRING && str->type == V_ASN1_PRINTABLESTRING)) + { BIO_printf(bio_err, "\nThe string contains characters that are illegal for the ASN.1 type\n"); - goto err; + goto end; } } if (default_op) - old_entry_print(bio_err, obj, str); + old_entry_print(obj, str); } /* Ok, now we check the 'policy' stuff. */ if ((subject = X509_NAME_new()) == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } /* take a copy of the issuer name before we mess with it. */ if (selfsign) CAname = X509_NAME_dup(name); else - CAname = X509_NAME_dup(x509->cert_info->subject); + CAname = X509_NAME_dup(X509_get_subject_name(x509)); if (CAname == NULL) - goto err; + goto end; str = str2 = NULL; for (i = 0; i < sk_CONF_VALUE_num(policy); i++) { @@ -1741,12 +1489,14 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "%s:unknown object type in 'policy' configuration\n", cv->name); - goto err; + goto end; } obj = OBJ_nid2obj(j); last = -1; for (;;) { + X509_NAME_ENTRY *push = NULL; + /* lookup the object in the supplied name list */ j = X509_NAME_get_index_by_OBJ(name, obj, last); if (j < 0) { @@ -1759,7 +1509,6 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, last = j; /* depending on the 'policy', decide what to do. */ - push = NULL; if (strcmp(cv->value, "optional") == 0) { if (tne != NULL) push = tne; @@ -1768,9 +1517,10 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "The %s field needed to be supplied and was missing\n", cv->name); - goto err; - } else + goto end; + } else { push = tne; + } } else if (strcmp(cv->value, "match") == 0) { int last2; @@ -1778,7 +1528,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "The mandatory %s field was missing\n", cv->name); - goto err; + goto end; } last2 = -1; @@ -1787,9 +1537,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, j = X509_NAME_get_index_by_OBJ(CAname, obj, last2); if ((j < 0) && (last2 == -1)) { BIO_printf(bio_err, - "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n", - cv->name); - goto err; + "The %s field does not exist in the CA certificate,\n" + "the 'policy' is misconfigured\n", cv->name); + goto end; } if (j >= 0) { push = X509_NAME_get_entry(CAname, j); @@ -1801,23 +1551,24 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } if (j < 0) { BIO_printf(bio_err, - "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n", + "The %s field is different between\n" + "CA certificate (%s) and the request (%s)\n", cv->name, ((str2 == NULL) ? "NULL" : (char *)str2->data), ((str == NULL) ? "NULL" : (char *)str->data)); - goto err; + goto end; } } else { BIO_printf(bio_err, "%s:invalid type in 'policy' configuration\n", cv->value); - goto err; + goto end; } if (push != NULL) { if (!X509_NAME_add_entry(subject, push, -1, 0)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } if (j < 0) @@ -1830,7 +1581,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ subject = X509_NAME_dup(name); if (subject == NULL) - goto err; + goto end; } /* We are now totally happy, lets make and sign the certificate */ @@ -1839,67 +1590,54 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, "Everything appears to be ok, creating and signing the certificate\n"); if ((ret = X509_new()) == NULL) - goto err; - ci = ret->cert_info; + goto end; #ifdef X509_V3 /* Make it an X509 v3 certificate. */ if (!X509_set_version(ret, 2)) - goto err; + goto end; #endif - if (BN_to_ASN1_INTEGER(serial, ci->serialNumber) == NULL) - goto err; + if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) + goto end; if (selfsign) { if (!X509_set_issuer_name(ret, subject)) - goto err; + goto end; } else { if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) - goto err; + goto end; } - if (strcmp(startdate, "today") == 0) - X509_gmtime_adj(X509_get_notBefore(ret), 0); - else - ASN1_TIME_set_string(X509_get_notBefore(ret), startdate); + if (!set_cert_times(ret, startdate, enddate, days)) + goto end; - if (enddate == NULL) - X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL); - else { + if (enddate != NULL) { int tdays; - ASN1_TIME_set_string(X509_get_notAfter(ret), enddate); - ASN1_TIME_diff(&tdays, NULL, NULL, X509_get_notAfter(ret)); + + if (!ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret))) + goto end; days = tdays; } if (!X509_set_subject_name(ret, subject)) - goto err; + goto end; - pktmp = X509_REQ_get_pubkey(req); + pktmp = X509_REQ_get0_pubkey(req); i = X509_set_pubkey(ret, pktmp); - EVP_PKEY_free(pktmp); if (!i) - goto err; + goto end; /* Lets add the extensions, if there are any */ if (ext_sect) { X509V3_CTX ctx; - /* - * Free the current entries if any, there should not be any I believe - */ - if (ci->extensions != NULL) - sk_X509_EXTENSION_pop_free(ci->extensions, X509_EXTENSION_free); - - ci->extensions = NULL; - /* Initialize the context structure */ if (selfsign) X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); else X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); - if (extconf) { + if (extconf != NULL) { if (verbose) BIO_printf(bio_err, "Extra configuration file found\n"); @@ -1915,7 +1653,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, "ERROR: adding extensions in section %s\n", ext_sect); ERR_print_errors(bio_err); - goto err; + goto end; } if (verbose) BIO_printf(bio_err, @@ -1929,7 +1667,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, "ERROR: adding extensions in section %s\n", ext_sect); ERR_print_errors(bio_err); - goto err; + goto end; } if (verbose) @@ -1943,24 +1681,23 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (!copy_extensions(ret, req, ext_copy)) { BIO_printf(bio_err, "ERROR: adding extensions from request\n"); ERR_print_errors(bio_err); - goto err; + goto end; } { - STACK_OF(X509_EXTENSION) *exts = ci->extensions; + const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret); if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0) /* Make it an X509 v3 certificate. */ if (!X509_set_version(ret, 2)) - goto err; + goto end; } if (verbose) BIO_printf(bio_err, "The subject name appears to be ok, checking data base for clashes\n"); - /* Build the correct Subject if no e-mail is wanted in the subject */ - + /* Build the correct Subject if no e-mail is wanted in the subject. */ if (!email_dn) { X509_NAME_ENTRY *tmpne; X509_NAME *dn_subject; @@ -1969,21 +1706,21 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, * Its best to dup the subject DN and then delete any email addresses * because this retains its structure. */ - if (!(dn_subject = X509_NAME_dup(subject))) { + if ((dn_subject = X509_NAME_dup(subject)) == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } + i = -1; while ((i = X509_NAME_get_index_by_NID(dn_subject, NID_pkcs9_emailAddress, - -1)) >= 0) { - tmpne = X509_NAME_get_entry(dn_subject, i); - X509_NAME_delete_entry(dn_subject, i); + i)) >= 0) { + tmpne = X509_NAME_delete_entry(dn_subject, i--); X509_NAME_ENTRY_free(tmpne); } if (!X509_set_subject_name(ret, dn_subject)) { X509_NAME_free(dn_subject); - goto err; + goto end; } X509_NAME_free(dn_subject); } @@ -1991,16 +1728,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); if (row[DB_name] == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } if (BN_is_zero(serial)) - row[DB_serial] = BUF_strdup("00"); + row[DB_serial] = OPENSSL_strdup("00"); else row[DB_serial] = BN_bn2hex(serial); if (row[DB_serial] == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } if (row[DB_name][0] == '\0') { @@ -2013,7 +1750,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, row[DB_name] = OPENSSL_strdup(row[DB_serial]); if (row[DB_name] == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } } @@ -2040,16 +1777,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (rrow != NULL) { BIO_printf(bio_err, "The matching entry has the following details\n"); - if (rrow[DB_type][0] == 'E') + if (rrow[DB_type][0] == DB_TYPE_EXP) p = "Expired"; - else if (rrow[DB_type][0] == 'R') + else if (rrow[DB_type][0] == DB_TYPE_REV) p = "Revoked"; - else if (rrow[DB_type][0] == 'V') + else if (rrow[DB_type][0] == DB_TYPE_VAL) p = "Valid"; else p = "\ninvalid type, Data base error\n"; BIO_printf(bio_err, "Type :%s\n", p);; - if (rrow[DB_type][0] == 'R') { + if (rrow[DB_type][0] == DB_TYPE_REV) { p = rrow[DB_exp_date]; if (p == NULL) p = "undef"; @@ -2072,7 +1809,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, p = "undef"; BIO_printf(bio_err, "Subject Name :%s\n", p); ok = -1; /* This is now a 'bad' error. */ - goto err; + goto end; } if (!default_op) { @@ -2085,7 +1822,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } BIO_printf(bio_err, "Certificate is to be certified until "); - ASN1_TIME_print(bio_err, X509_get_notAfter(ret)); + ASN1_TIME_print(bio_err, X509_get0_notAfter(ret)); if (days) BIO_printf(bio_err, " (%ld days)", days); BIO_printf(bio_err, "\n"); @@ -2095,54 +1832,42 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "Sign the certificate? [y/n]:"); (void)BIO_flush(bio_err); buf[0] = '\0'; - if (!fgets(buf, sizeof(buf) - 1, stdin)) { + if (fgets(buf, sizeof(buf), stdin) == NULL) { BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); ok = 0; - goto err; + goto end; } - if (!((buf[0] == 'y') || (buf[0] == 'Y'))) { + if (!(buf[0] == 'y' || buf[0] == 'Y')) { BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n"); ok = 0; - goto err; + goto end; } } - pktmp = X509_get_pubkey(ret); + pktmp = X509_get0_pubkey(ret); if (EVP_PKEY_missing_parameters(pktmp) && !EVP_PKEY_missing_parameters(pkey)) EVP_PKEY_copy_parameters(pktmp, pkey); - EVP_PKEY_free(pktmp); - if (!do_X509_sign(bio_err, ret, pkey, dgst, sigopts)) - goto err; - - /* We now just add it to the database */ - tm = X509_get_notAfter(ret); - row[DB_type] = OPENSSL_malloc(2); - row[DB_exp_date] = OPENSSL_malloc(tm->length + 1); - row[DB_rev_date] = OPENSSL_malloc(1); - row[DB_file] = OPENSSL_malloc(8); - if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || - (row[DB_rev_date] == NULL) || - (row[DB_file] == NULL)) { - BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; - } + if (!do_X509_sign(ret, pkey, dgst, sigopts)) + goto end; + /* We now just add it to the database as DB_TYPE_VAL('V') */ + row[DB_type] = OPENSSL_strdup("V"); + tm = X509_get0_notAfter(ret); + row[DB_exp_date] = app_malloc(tm->length + 1, "row expdate"); memcpy(row[DB_exp_date], tm->data, tm->length); row[DB_exp_date][tm->length] = '\0'; - row[DB_rev_date][0] = '\0'; - strcpy(row[DB_file], "unknown"); - row[DB_type][0] = 'V'; - row[DB_type][1] = '\0'; - - if ((irow = - (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) { + row[DB_rev_date] = NULL; + row[DB_file] = OPENSSL_strdup("unknown"); + if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || + (row[DB_file] == NULL) || (row[DB_name] == NULL)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row space"); for (i = 0; i < DB_NUMBER; i++) irow[i] = row[i]; irow[DB_NUMBER] = NULL; @@ -2150,64 +1875,45 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (!TXT_DB_insert(db->db, irow)) { BIO_printf(bio_err, "failed to update database\n"); BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); - goto err; + goto end; } irow = NULL; ok = 1; - err: + end: if (ok != 1) { for (i = 0; i < DB_NUMBER; i++) OPENSSL_free(row[i]); } OPENSSL_free(irow); - if (CAname != NULL) - X509_NAME_free(CAname); - if (subject != NULL) - X509_NAME_free(subject); - if (tmptm != NULL) - ASN1_UTCTIME_free(tmptm); - if (ok <= 0) { - if (ret != NULL) - X509_free(ret); - ret = NULL; - } else + X509_NAME_free(CAname); + X509_NAME_free(subject); + if (ok <= 0) + X509_free(ret); + else *xret = ret; - return (ok); + return ok; } -static void write_new_certificate(BIO *bp, X509 *x, int output_der, - int notext) +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) { if (output_der) { (void)i2d_X509_bio(bp, x); return; } -#if 0 - /* ??? Not needed since X509_print prints all this stuff anyway */ - f = X509_NAME_oneline(X509_get_issuer_name(x), buf, 256); - BIO_printf(bp, "issuer :%s\n", f); - - f = X509_NAME_oneline(X509_get_subject_name(x), buf, 256); - BIO_printf(bp, "subject:%s\n", f); - - BIO_puts(bp, "serial :"); - i2a_ASN1_INTEGER(bp, x->cert_info->serialNumber); - BIO_puts(bp, "\n\n"); -#endif if (!notext) X509_print(bp, x); PEM_write_bio_X509(bp, x); } -static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy) { @@ -2216,7 +1922,6 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509_REQ *req = NULL; CONF_VALUE *cv = NULL; NETSCAPE_SPKI *spki = NULL; - X509_REQ_INFO *ri; char *type, *buf; EVP_PKEY *pktmp = NULL; X509_NAME *n = NULL; @@ -2234,13 +1939,13 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, if (parms == NULL) { BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile); ERR_print_errors(bio_err); - goto err; + goto end; } sk = CONF_get_section(parms, "default"); if (sk_CONF_VALUE_num(sk) == 0) { BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); - goto err; + goto end; } /* @@ -2253,14 +1958,13 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, req = X509_REQ_new(); if (req == NULL) { ERR_print_errors(bio_err); - goto err; + goto end; } /* * Build up the subject name set. */ - ri = req->req_info; - n = ri->subject; + n = X509_REQ_get_subject_name(req); for (i = 0;; i++) { if (sk_CONF_VALUE_num(sk) <= i) @@ -2287,7 +1991,7 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, BIO_printf(bio_err, "unable to load Netscape SPKAC structure\n"); ERR_print_errors(bio_err); - goto err; + goto end; } } continue; @@ -2295,24 +1999,23 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char *)buf, -1, -1, 0)) - goto err; + goto end; } if (spki == NULL) { BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n", infile); - goto err; + goto end; } /* * Now extract the key from the SPKI structure. */ - BIO_printf(bio_err, - "Check that the SPKAC request matches the signature\n"); + BIO_printf(bio_err, "Check that the SPKAC request matches the signature\n"); if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) { BIO_printf(bio_err, "error unpacking SPKAC public key\n"); - goto err; + goto end; } j = NETSCAPE_SPKI_verify(spki, pktmp); @@ -2320,7 +2023,7 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, EVP_PKEY_free(pktmp); BIO_printf(bio_err, "signature verification failed on SPKAC public key\n"); - goto err; + goto end; } BIO_printf(bio_err, "Signature ok\n"); @@ -2330,17 +2033,13 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, chtype, multirdn, email_dn, startdate, enddate, days, 1, verbose, req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy, 0); - err: - if (req != NULL) - X509_REQ_free(req); - if (parms != NULL) - CONF_free(parms); - if (spki != NULL) - NETSCAPE_SPKI_free(spki); - if (ne != NULL) - X509_NAME_ENTRY_free(ne); + end: + X509_REQ_free(req); + CONF_free(parms); + NETSCAPE_SPKI_free(spki); + X509_NAME_ENTRY_free(ne); - return (ok); + return ok; } static int check_time_format(const char *str) @@ -2348,9 +2047,10 @@ static int check_time_format(const char *str) return ASN1_TIME_set_string(NULL, str); } -static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *value) { - ASN1_UTCTIME *tm = NULL; + const ASN1_TIME *tm = NULL; char *row[DB_NUMBER], **rrow, **irow; char *rev_str = NULL; BIGNUM *bn = NULL; @@ -2361,9 +2061,9 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); if (!bn) - goto err; + goto end; if (BN_is_zero(bn)) - row[DB_serial] = BUF_strdup("00"); + row[DB_serial] = OPENSSL_strdup("00"); else row[DB_serial] = BN_bn2hex(bn); BN_free(bn); @@ -2374,7 +2074,7 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) } if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } /* * We have to lookup by serial number because name lookup skips revoked @@ -2386,37 +2086,21 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) "Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]); - /* We now just add it to the database */ - row[DB_type] = (char *)OPENSSL_malloc(2); - - tm = X509_get_notAfter(x509); - row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1); + /* We now just add it to the database as DB_TYPE_REV('V') */ + row[DB_type] = OPENSSL_strdup("V"); + tm = X509_get0_notAfter(x509); + row[DB_exp_date] = app_malloc(tm->length + 1, "row exp_data"); memcpy(row[DB_exp_date], tm->data, tm->length); row[DB_exp_date][tm->length] = '\0'; - row[DB_rev_date] = NULL; + row[DB_file] = OPENSSL_strdup("unknown"); - /* row[DB_serial] done already */ - row[DB_file] = (char *)OPENSSL_malloc(8); - - /* row[DB_name] done already */ - - if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || - (row[DB_file] == NULL)) { - BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; - } - BUF_strlcpy(row[DB_file], "unknown", 8); - row[DB_type][0] = 'V'; - row[DB_type][1] = '\0'; - - if ((irow = - (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == - NULL) { + if (row[DB_type] == NULL || row[DB_file] == NULL) { BIO_printf(bio_err, "Memory allocation failure\n"); - goto err; + goto end; } + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row ptr"); for (i = 0; i < DB_NUMBER; i++) irow[i] = row[i]; irow[DB_NUMBER] = NULL; @@ -2425,85 +2109,80 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) BIO_printf(bio_err, "failed to update database\n"); BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); OPENSSL_free(irow); - goto err; + goto end; } for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; /* Revoke Certificate */ - if (type == -1) + if (rev_type == REV_VALID) ok = 1; else - ok = do_revoke(x509, db, type, value); + /* Retry revocation after DB insertion */ + ok = do_revoke(x509, db, rev_type, value); - goto err; + goto end; } else if (index_name_cmp_noconst(row, rrow)) { BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]); - goto err; - } else if (type == -1) { + goto end; + } else if (rev_type == REV_VALID) { BIO_printf(bio_err, "ERROR:Already present, serial number %s\n", row[DB_serial]); - goto err; - } else if (rrow[DB_type][0] == 'R') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n", row[DB_serial]); - goto err; + goto end; } else { BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]); - rev_str = make_revocation_str(type, value); + rev_str = make_revocation_str(rev_type, value); if (!rev_str) { BIO_printf(bio_err, "Error in revocation arguments\n"); - goto err; + goto end; } - rrow[DB_type][0] = 'R'; + rrow[DB_type][0] = DB_TYPE_REV; rrow[DB_type][1] = '\0'; rrow[DB_rev_date] = rev_str; } ok = 1; - err: - for (i = 0; i < DB_NUMBER; i++) { - if (row[i] != NULL) - OPENSSL_free(row[i]); - } - return (ok); + end: + for (i = 0; i < DB_NUMBER; i++) + OPENSSL_free(row[i]); + return ok; } static int get_certificate_status(const char *serial, CA_DB *db) { char *row[DB_NUMBER], **rrow; int ok = -1, i; + size_t serial_len = strlen(serial); /* Free Resources */ for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; /* Malloc needed char spaces */ - row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2); - if (row[DB_serial] == NULL) { - BIO_printf(bio_err, "Malloc failure\n"); - goto err; - } + row[DB_serial] = app_malloc(serial_len + 2, "row serial#"); - if (strlen(serial) % 2) { + if (serial_len % 2) { /* * Set the first char to 0 - */ ; + */ row[DB_serial][0] = '0'; /* Copy String from serial to row[DB_serial] */ - memcpy(row[DB_serial] + 1, serial, strlen(serial)); - row[DB_serial][strlen(serial) + 1] = '\0'; + memcpy(row[DB_serial] + 1, serial, serial_len); + row[DB_serial][serial_len + 1] = '\0'; } else { /* Copy String from serial to row[DB_serial] */ - memcpy(row[DB_serial], serial, strlen(serial)); - row[DB_serial][strlen(serial)] = '\0'; + memcpy(row[DB_serial], serial, serial_len); + row[DB_serial][serial_len] = '\0'; } /* Make it Upper Case */ - for (i = 0; row[DB_serial][i] != '\0'; i++) - row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]); + make_uppercase(row[DB_serial]); ok = 1; @@ -2512,34 +2191,33 @@ static int get_certificate_status(const char *serial, CA_DB *db) if (rrow == NULL) { BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]); ok = -1; - goto err; - } else if (rrow[DB_type][0] == 'V') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_VAL) { BIO_printf(bio_err, "%s=Valid (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; - } else if (rrow[DB_type][0] == 'R') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { BIO_printf(bio_err, "%s=Revoked (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; - } else if (rrow[DB_type][0] == 'E') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_EXP) { BIO_printf(bio_err, "%s=Expired (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; - } else if (rrow[DB_type][0] == 'S') { + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_SUSP) { BIO_printf(bio_err, "%s=Suspended (%c)\n", row[DB_serial], rrow[DB_type][0]); - goto err; + goto end; } else { BIO_printf(bio_err, "%s=Unknown (%c).\n", row[DB_serial], rrow[DB_type][0]); ok = -1; } - err: + end: for (i = 0; i < DB_NUMBER; i++) { - if (row[i] != NULL) - OPENSSL_free(row[i]); + OPENSSL_free(row[i]); } - return (ok); + return ok; } static int do_updatedb(CA_DB *db) @@ -2554,12 +2232,11 @@ static int do_updatedb(CA_DB *db) return -1; /* get actual time and make a string */ - a_tm = X509_gmtime_adj(a_tm, 0); - a_tm_s = (char *)OPENSSL_malloc(a_tm->length + 1); - if (a_tm_s == NULL) { - cnt = -1; - goto err; + if (X509_gmtime_adj(a_tm, 0) == NULL) { + ASN1_UTCTIME_free(a_tm); + return -1; } + a_tm_s = app_malloc(a_tm->length + 1, "time string"); memcpy(a_tm_s, a_tm->data, a_tm->length); a_tm_s[a_tm->length] = '\0'; @@ -2572,7 +2249,7 @@ static int do_updatedb(CA_DB *db) for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); - if (rrow[DB_type][0] == 'V') { + if (rrow[DB_type][0] == DB_TYPE_VAL) { /* ignore entries that are not valid */ if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) db_y2k = 1; @@ -2582,14 +2259,14 @@ static int do_updatedb(CA_DB *db) if (db_y2k == a_y2k) { /* all on the same y2k side */ if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) { - rrow[DB_type][0] = 'E'; + rrow[DB_type][0] = DB_TYPE_EXP; rrow[DB_type][1] = '\0'; cnt++; BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); } } else if (db_y2k < a_y2k) { - rrow[DB_type][0] = 'E'; + rrow[DB_type][0] = DB_TYPE_EXP; rrow[DB_type][1] = '\0'; cnt++; @@ -2599,12 +2276,9 @@ static int do_updatedb(CA_DB *db) } } - err: - ASN1_UTCTIME_free(a_tm); OPENSSL_free(a_tm_s); - - return (cnt); + return cnt; } static const char *crl_reasons[] = { @@ -2623,7 +2297,7 @@ static const char *crl_reasons[] = { "CAkeyTime" }; -#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) +#define NUM_REASONS OSSL_NELEM(crl_reasons) /* * Given revocation information convert to a DB string. The format of the @@ -2632,20 +2306,22 @@ static const char *crl_reasons[] = { * additional argument */ -char *make_revocation_str(int rev_type, char *rev_arg) +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg) { - char *other = NULL, *str; - const char *reason = NULL; + char *str; + const char *reason = NULL, *other = NULL; ASN1_OBJECT *otmp; ASN1_UTCTIME *revtm = NULL; int i; + switch (rev_type) { case REV_NONE: + case REV_VALID: break; case REV_CRL_REASON: for (i = 0; i < 8; i++) { - if (!strcasecmp(rev_arg, crl_reasons[i])) { + if (strcasecmp(rev_arg, crl_reasons[i]) == 0) { reason = crl_reasons[i]; break; } @@ -2658,7 +2334,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) case REV_HOLD: /* Argument is an OID */ - otmp = OBJ_txt2obj(rev_arg, 0); ASN1_OBJECT_free(otmp); @@ -2673,7 +2348,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) case REV_KEY_COMPROMISE: case REV_CA_COMPROMISE: - /* Argument is the key compromise time */ if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) { BIO_printf(bio_err, @@ -2688,7 +2362,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) reason = "CAkeyTime"; break; - } revtm = X509_gmtime_adj(NULL, 0); @@ -2703,19 +2376,15 @@ char *make_revocation_str(int rev_type, char *rev_arg) if (other) i += strlen(other) + 1; - str = OPENSSL_malloc(i); - - if (!str) - return NULL; - - BUF_strlcpy(str, (char *)revtm->data, i); + str = app_malloc(i, "revocation reason"); + OPENSSL_strlcpy(str, (char *)revtm->data, i); if (reason) { - BUF_strlcat(str, ",", i); - BUF_strlcat(str, reason, i); + OPENSSL_strlcat(str, ",", i); + OPENSSL_strlcat(str, reason, i); } if (other) { - BUF_strlcat(str, ",", i); - BUF_strlcat(str, other, i); + OPENSSL_strlcat(str, ",", i); + OPENSSL_strlcat(str, other, i); } ASN1_UTCTIME_free(revtm); return str; @@ -2729,7 +2398,7 @@ char *make_revocation_str(int rev_type, char *rev_arg) * 2 OK and some extensions added (i.e. V2 CRL) */ -int make_revoked(X509_REVOKED *rev, const char *str) +static int make_revoked(X509_REVOKED *rev, const char *str) { char *tmp = NULL; int reason_code = -1; @@ -2743,28 +2412,28 @@ int make_revoked(X509_REVOKED *rev, const char *str) i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); if (i == 0) - goto err; + goto end; if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) - goto err; + goto end; if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) { rtmp = ASN1_ENUMERATED_new(); - if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) - goto err; + if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code)) + goto end; if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) - goto err; + goto end; } if (rev && comp_time) { if (!X509_REVOKED_add1_ext_i2d (rev, NID_invalidity_date, comp_time, 0, 0)) - goto err; + goto end; } if (rev && hold) { if (!X509_REVOKED_add1_ext_i2d (rev, NID_hold_instruction_code, hold, 0, 0)) - goto err; + goto end; } if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) @@ -2772,10 +2441,9 @@ int make_revoked(X509_REVOKED *rev, const char *str) else ret = 1; - err: + end: - if (tmp) - OPENSSL_free(tmp); + OPENSSL_free(tmp); ASN1_OBJECT_free(hold); ASN1_GENERALIZEDTIME_free(comp_time); ASN1_ENUMERATED_free(rtmp); @@ -2784,60 +2452,62 @@ int make_revoked(X509_REVOKED *rev, const char *str) return ret; } -int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str) { - char buf[25], *pbuf, *p; + char buf[25], *pbuf; + const char *p; int j; - j = i2a_ASN1_OBJECT(bp, obj); + + j = i2a_ASN1_OBJECT(bio_err, obj); pbuf = buf; for (j = 22 - j; j > 0; j--) *(pbuf++) = ' '; *(pbuf++) = ':'; *(pbuf++) = '\0'; - BIO_puts(bp, buf); + BIO_puts(bio_err, buf); if (str->type == V_ASN1_PRINTABLESTRING) - BIO_printf(bp, "PRINTABLE:'"); + BIO_printf(bio_err, "PRINTABLE:'"); else if (str->type == V_ASN1_T61STRING) - BIO_printf(bp, "T61STRING:'"); + BIO_printf(bio_err, "T61STRING:'"); else if (str->type == V_ASN1_IA5STRING) - BIO_printf(bp, "IA5STRING:'"); + BIO_printf(bio_err, "IA5STRING:'"); else if (str->type == V_ASN1_UNIVERSALSTRING) - BIO_printf(bp, "UNIVERSALSTRING:'"); + BIO_printf(bio_err, "UNIVERSALSTRING:'"); else - BIO_printf(bp, "ASN.1 %2d:'", str->type); + BIO_printf(bio_err, "ASN.1 %2d:'", str->type); - p = (char *)str->data; + p = (const char *)str->data; for (j = str->length; j > 0; j--) { if ((*p >= ' ') && (*p <= '~')) - BIO_printf(bp, "%c", *p); + BIO_printf(bio_err, "%c", *p); else if (*p & 0x80) - BIO_printf(bp, "\\0x%02X", *p); + BIO_printf(bio_err, "\\0x%02X", *p); else if ((unsigned char)*p == 0xf7) - BIO_printf(bp, "^?"); + BIO_printf(bio_err, "^?"); else - BIO_printf(bp, "^%c", *p + '@'); + BIO_printf(bio_err, "^%c", *p + '@'); p++; } - BIO_printf(bp, "'\n"); + BIO_printf(bio_err, "'\n"); return 1; } int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str) { - char *tmp = NULL; + char *tmp; char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; int reason_code = -1; int ret = 0; unsigned int i; ASN1_OBJECT *hold = NULL; ASN1_GENERALIZEDTIME *comp_time = NULL; - tmp = BUF_strdup(str); + tmp = OPENSSL_strdup(str); if (!tmp) { BIO_printf(bio_err, "memory allocation failure\n"); - goto err; + goto end; } p = strchr(tmp, ','); @@ -2857,57 +2527,58 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, if (prevtm) { *prevtm = ASN1_UTCTIME_new(); - if (!*prevtm) { + if (*prevtm == NULL) { BIO_printf(bio_err, "memory allocation failure\n"); - goto err; + goto end; } if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) { BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); - goto err; + goto end; } } if (reason_str) { for (i = 0; i < NUM_REASONS; i++) { - if (!strcasecmp(reason_str, crl_reasons[i])) { + if (strcasecmp(reason_str, crl_reasons[i]) == 0) { reason_code = i; break; } } if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) { BIO_printf(bio_err, "invalid reason code %s\n", reason_str); - goto err; + goto end; } - if (reason_code == 7) + if (reason_code == 7) { reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; - else if (reason_code == 8) { /* Hold instruction */ + } else if (reason_code == 8) { /* Hold instruction */ if (!arg_str) { BIO_printf(bio_err, "missing hold instruction\n"); - goto err; + goto end; } reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; hold = OBJ_txt2obj(arg_str, 0); if (!hold) { - BIO_printf(bio_err, "invalid object identifier %s\n", - arg_str); - goto err; + BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); + goto end; } if (phold) *phold = hold; + else + ASN1_OBJECT_free(hold); } else if ((reason_code == 9) || (reason_code == 10)) { if (!arg_str) { BIO_printf(bio_err, "missing compromised time\n"); - goto err; + goto end; } comp_time = ASN1_GENERALIZEDTIME_new(); - if (!comp_time) { + if (comp_time == NULL) { BIO_printf(bio_err, "memory allocation failure\n"); - goto err; + goto end; } if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) { BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); - goto err; + goto end; } if (reason_code == 9) reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; @@ -2918,21 +2589,17 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, if (preason) *preason = reason_code; - if (pinvtm) + if (pinvtm) { *pinvtm = comp_time; - else - ASN1_GENERALIZEDTIME_free(comp_time); + comp_time = NULL; + } ret = 1; - err: + end: - if (tmp) - OPENSSL_free(tmp); - if (!phold) - ASN1_OBJECT_free(hold); - if (!pinvtm) - ASN1_GENERALIZEDTIME_free(comp_time); + OPENSSL_free(tmp); + ASN1_GENERALIZEDTIME_free(comp_time); return ret; } diff --git a/apps/ciphers.c b/apps/ciphers.c index 4856141f6f2b..0bb33a4aca4b 100644 --- a/apps/ciphers.c +++ b/apps/ciphers.c @@ -1,164 +1,202 @@ -/* apps/ciphers.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> -#ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -#endif #include "apps.h" +#include "progs.h" #include <openssl/err.h> #include <openssl/ssl.h> -#undef PROG -#define PROG ciphers_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_STDNAME, + OPT_CONVERT, + OPT_SSL3, + OPT_TLS1, + OPT_TLS1_1, + OPT_TLS1_2, + OPT_TLS1_3, + OPT_PSK, + OPT_SRP, + OPT_CIPHERSUITES, + OPT_V, OPT_UPPER_V, OPT_S +} OPTION_CHOICE; -static const char *ciphers_usage[] = { - "usage: ciphers args\n", - " -v - verbose mode, a textual listing of the SSL/TLS ciphers in OpenSSL\n", - " -V - even more verbose\n", - " -ssl2 - SSL2 mode\n", - " -ssl3 - SSL3 mode\n", - " -tls1 - TLS1 mode\n", - NULL +const OPTIONS ciphers_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"v", OPT_V, '-', "Verbose listing of the SSL/TLS ciphers"}, + {"V", OPT_UPPER_V, '-', "Even more verbose"}, + {"s", OPT_S, '-', "Only supported ciphers"}, +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "SSL3 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "TLS1 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "TLS1.1 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "TLS1.2 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "TLS1.3 mode"}, +#endif + {"stdname", OPT_STDNAME, '-', "Show standard cipher names"}, +#ifndef OPENSSL_NO_PSK + {"psk", OPT_PSK, '-', "include ciphersuites requiring PSK"}, +#endif +#ifndef OPENSSL_NO_SRP + {"srp", OPT_SRP, '-', "include ciphersuites requiring SRP"}, +#endif + {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"}, + {"ciphersuites", OPT_CIPHERSUITES, 's', + "Configure the TLSv1.3 ciphersuites to use"}, + {NULL} }; -int MAIN(int, char **); +#ifndef OPENSSL_NO_PSK +static unsigned int dummy_psk(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len) +{ + return 0; +} +#endif +#ifndef OPENSSL_NO_SRP +static char *dummy_srp(SSL *ssl, void *arg) +{ + return ""; +} +#endif -int MAIN(int argc, char **argv) +int ciphers_main(int argc, char **argv) { - int ret = 1, i; - int verbose = 0, Verbose = 0; -#ifndef OPENSSL_NO_SSL_TRACE + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + STACK_OF(SSL_CIPHER) *sk = NULL; + const SSL_METHOD *meth = TLS_server_method(); + int ret = 1, i, verbose = 0, Verbose = 0, use_supported = 0; int stdname = 0; +#ifndef OPENSSL_NO_PSK + int psk = 0; +#endif +#ifndef OPENSSL_NO_SRP + int srp = 0; #endif - const char **pp; const char *p; - int badops = 0; - SSL_CTX *ctx = NULL; - SSL *ssl = NULL; - char *ciphers = NULL; - const SSL_METHOD *meth = NULL; - STACK_OF(SSL_CIPHER) *sk; + char *ciphers = NULL, *prog, *convert = NULL, *ciphersuites = NULL; char buf[512]; - BIO *STDout = NULL; - - meth = SSLv23_server_method(); - - apps_startup(); - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - STDout = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - STDout = BIO_push(tmpbio, STDout); - } -#endif - if (!load_config(bio_err, NULL)) - goto end; + OPTION_CHOICE o; + int min_version = 0, max_version = 0; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-v") == 0) + prog = opt_init(argc, argv, ciphers_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ciphers_options); + ret = 0; + goto end; + case OPT_V: verbose = 1; - else if (strcmp(*argv, "-V") == 0) + break; + case OPT_UPPER_V: verbose = Verbose = 1; -#ifndef OPENSSL_NO_SSL_TRACE - else if (strcmp(*argv, "-stdname") == 0) + break; + case OPT_S: + use_supported = 1; + break; + case OPT_STDNAME: stdname = verbose = 1; + break; + case OPT_CONVERT: + convert = opt_arg(); + break; + case OPT_SSL3: + min_version = SSL3_VERSION; + max_version = SSL3_VERSION; + break; + case OPT_TLS1: + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + break; + case OPT_TLS1_1: + min_version = TLS1_1_VERSION; + max_version = TLS1_1_VERSION; + break; + case OPT_TLS1_2: + min_version = TLS1_2_VERSION; + max_version = TLS1_2_VERSION; + break; + case OPT_TLS1_3: + min_version = TLS1_3_VERSION; + max_version = TLS1_3_VERSION; + break; + case OPT_PSK: +#ifndef OPENSSL_NO_PSK + psk = 1; #endif -#ifndef OPENSSL_NO_SSL2 - else if (strcmp(*argv, "-ssl2") == 0) - meth = SSLv2_client_method(); -#endif -#ifndef OPENSSL_NO_SSL3 - else if (strcmp(*argv, "-ssl3") == 0) - meth = SSLv3_client_method(); -#endif -#ifndef OPENSSL_NO_TLS1 - else if (strcmp(*argv, "-tls1") == 0) - meth = TLSv1_client_method(); + break; + case OPT_SRP: +#ifndef OPENSSL_NO_SRP + srp = 1; #endif - else if ((strncmp(*argv, "-h", 2) == 0) || (strcmp(*argv, "-?") == 0)) { - badops = 1; break; - } else { - ciphers = *argv; + case OPT_CIPHERSUITES: + ciphersuites = opt_arg(); + break; } - argc--; - argv++; } + argv = opt_rest(); + argc = opt_num_rest(); - if (badops) { - for (pp = ciphers_usage; (*pp != NULL); pp++) - BIO_printf(bio_err, "%s", *pp); + if (argc == 1) + ciphers = *argv; + else if (argc != 0) + goto opthelp; + + if (convert != NULL) { + BIO_printf(bio_out, "OpenSSL cipher name: %s\n", + OPENSSL_cipher_name(convert)); goto end; } - OpenSSL_add_ssl_algorithms(); - ctx = SSL_CTX_new(meth); if (ctx == NULL) goto err; + if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + goto err; + if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto err; + +#ifndef OPENSSL_NO_PSK + if (psk) + SSL_CTX_set_psk_client_callback(ctx, dummy_psk); +#endif +#ifndef OPENSSL_NO_SRP + if (srp) + SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); +#endif + + if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) { + BIO_printf(bio_err, "Error setting TLSv1.3 ciphersuites\n"); + goto err; + } + if (ciphers != NULL) { if (!SSL_CTX_set_cipher_list(ctx, ciphers)) { BIO_printf(bio_err, "Error in cipher list\n"); @@ -169,22 +207,26 @@ int MAIN(int argc, char **argv) if (ssl == NULL) goto err; + if (use_supported) + sk = SSL_get1_supported_ciphers(ssl); + else + sk = SSL_get_ciphers(ssl); + if (!verbose) { - for (i = 0;; i++) { - p = SSL_get_cipher_list(ssl, i); + for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i); + p = SSL_CIPHER_get_name(c); if (p == NULL) break; if (i != 0) - BIO_printf(STDout, ":"); - BIO_printf(STDout, "%s", p); + BIO_printf(bio_out, ":"); + BIO_printf(bio_out, "%s", p); } - BIO_printf(STDout, "\n"); - } else { /* verbose */ - - sk = SSL_get_ciphers(ssl); + BIO_printf(bio_out, "\n"); + } else { for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { - SSL_CIPHER *c; + const SSL_CIPHER *c; c = sk_SSL_CIPHER_value(sk, i); @@ -195,45 +237,30 @@ int MAIN(int argc, char **argv) int id2 = (int)((id >> 8) & 0xffL); int id3 = (int)(id & 0xffL); - if ((id & 0xff000000L) == 0x02000000L) { - /* SSL2 cipher */ - BIO_printf(STDout, " 0x%02X,0x%02X,0x%02X - ", id1, - id2, id3); - } else if ((id & 0xff000000L) == 0x03000000L) { - /* SSL3 cipher */ - BIO_printf(STDout, " 0x%02X,0x%02X - ", id2, - id3); - } else { - /* whatever */ - BIO_printf(STDout, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, - id1, id2, id3); - } + if ((id & 0xff000000L) == 0x03000000L) + BIO_printf(bio_out, " 0x%02X,0x%02X - ", id2, id3); /* SSL3 + * cipher */ + else + BIO_printf(bio_out, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); /* whatever */ } -#ifndef OPENSSL_NO_SSL_TRACE if (stdname) { const char *nm = SSL_CIPHER_standard_name(c); if (nm == NULL) nm = "UNKNOWN"; - BIO_printf(STDout, "%s - ", nm); + BIO_printf(bio_out, "%s - ", nm); } -#endif - BIO_puts(STDout, SSL_CIPHER_description(c, buf, sizeof(buf))); + BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof(buf))); } } ret = 0; - if (0) { + goto end; err: - SSL_load_error_strings(); - ERR_print_errors(bio_err); - } + ERR_print_errors(bio_err); end: - if (ctx != NULL) - SSL_CTX_free(ctx); - if (ssl != NULL) - SSL_free(ssl); - if (STDout != NULL) - BIO_free_all(STDout); - apps_shutdown(); - OPENSSL_EXIT(ret); + if (use_supported) + sk_SSL_CIPHER_free(sk); + SSL_CTX_free(ctx); + SSL_free(ssl); + return ret; } diff --git a/apps/cms.c b/apps/cms.c index de4ba136e8fa..e9d760c999b7 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -1,55 +1,10 @@ -/* apps/cms.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project. - */ -/* ==================================================================== - * Copyright (c) 2008-2018 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ /* CMS utility function */ @@ -57,6 +12,7 @@ #include <stdio.h> #include <string.h> #include "apps.h" +#include "progs.h" #ifndef OPENSSL_NO_CMS @@ -67,11 +23,9 @@ # include <openssl/x509v3.h> # include <openssl/cms.h> -# undef PROG -# define PROG cms_main static int save_certs(char *signerfile, STACK_OF(X509) *signers); static int cms_cb(int ok, X509_STORE_CTX *ctx); -static void receipt_request_print(BIO *out, CMS_ContentInfo *cms); +static void receipt_request_print(CMS_ContentInfo *cms); static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) *rr_from); @@ -98,7 +52,7 @@ static int cms_set_pkey_param(EVP_PKEY_CTX *pctx, # define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP) # define SMIME_VERIFY_RECEIPT (16 | SMIME_IP) -int verify_err = 0; +static int verify_err = 0; typedef struct cms_key_param_st cms_key_param; @@ -108,365 +62,492 @@ struct cms_key_param_st { cms_key_param *next; }; -int MAIN(int, char **); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT, + OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN, + OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT, + OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY, + OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS, + OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT, + OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS, + OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID, + OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF, + OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT, + OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE, + OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT, + OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE, + OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, + OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM, + OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP, + OPT_3DES_WRAP, OPT_ENGINE, + OPT_R_ENUM, + OPT_V_ENUM, + OPT_CIPHER +} OPTION_CHOICE; -int MAIN(int argc, char **argv) +const OPTIONS cms_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, + {OPT_HELP_STR, 1, '-', + " cert.pem... recipient certs for encryption\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, + {"outform", OPT_OUTFORM, 'c', + "Output format SMIME (default), PEM or DER"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, + {"sign", OPT_SIGN, '-', "Sign message"}, + {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"}, + {"resign", OPT_RESIGN, '-', "Resign a signed message"}, + {"verify", OPT_VERIFY, '-', "Verify signed message"}, + {"verify_retcode", OPT_VERIFY_RETCODE, '-'}, + {"verify_receipt", OPT_VERIFY_RECEIPT, '<'}, + {"cmsout", OPT_CMSOUT, '-', "Output CMS structure"}, + {"data_out", OPT_DATA_OUT, '-'}, + {"data_create", OPT_DATA_CREATE, '-'}, + {"digest_verify", OPT_DIGEST_VERIFY, '-'}, + {"digest_create", OPT_DIGEST_CREATE, '-'}, + {"compress", OPT_COMPRESS, '-'}, + {"uncompress", OPT_UNCOMPRESS, '-'}, + {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-'}, + {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-'}, + {"debug_decrypt", OPT_DEBUG_DECRYPT, '-'}, + {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, + {"asciicrlf", OPT_ASCIICRLF, '-'}, + {"nointern", OPT_NOINTERN, '-', + "Don't search certificates in message for signer"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, + {"nocerts", OPT_NOCERTS, '-', + "Don't include signers certificate when signing"}, + {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, + {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, + {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + {"binary", OPT_BINARY, '-', "Don't translate message to text"}, + {"keyid", OPT_KEYID, '-', "Use subject key identifier"}, + {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, + {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-'}, + {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-'}, + {"stream", OPT_INDEF, '-', "Enable CMS streaming"}, + {"indef", OPT_INDEF, '-', "Same as -stream"}, + {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, + {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only" }, + {"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"}, + {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" }, + {"receipt_request_all", OPT_RR_ALL, '-'}, + {"receipt_request_first", OPT_RR_FIRST, '-'}, + {"rctform", OPT_RCTFORM, 'F', "Receipt file format"}, + {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"CApath", OPT_CAPATH, '/', "trusted certificates directory"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"content", OPT_CONTENT, '<', + "Supply or override content for detached signature"}, + {"print", OPT_PRINT, '-', + "For the -cmsout operation print out all fields of the CMS structure"}, + {"secretkey", OPT_SECRETKEY, 's'}, + {"secretkeyid", OPT_SECRETKEYID, 's'}, + {"pwri_password", OPT_PWRI_PASSWORD, 's'}, + {"econtent_type", OPT_ECONTENT_TYPE, 's'}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"to", OPT_TO, 's', "To address"}, + {"from", OPT_FROM, 's', "From address"}, + {"subject", OPT_SUBJECT, 's', "Subject"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, + {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"}, + {"certsout", OPT_CERTSOUT, '>', "Certificate output file"}, + {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, + {"inkey", OPT_INKEY, 's', + "Input private key (if not signer or recipient)"}, + {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"}, + {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"}, + {"receipt_request_from", OPT_RR_FROM, 's'}, + {"receipt_request_to", OPT_RR_TO, 's'}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, + OPT_R_OPTIONS, + OPT_V_OPTIONS, + {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"}, + {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"}, + {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"}, +# ifndef OPENSSL_NO_DES + {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +# endif + {NULL} +}; + +int cms_main(int argc, char **argv) { + ASN1_OBJECT *econtent_type = NULL; + BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL; + CMS_ContentInfo *cms = NULL, *rcms = NULL; + CMS_ReceiptRequest *rr = NULL; ENGINE *e = NULL; - int operation = 0; - int ret = 0; - char **args; - const char *inmode = "r", *outmode = "w"; - char *infile = NULL, *outfile = NULL, *rctfile = NULL; - char *signerfile = NULL, *recipfile = NULL; + EVP_PKEY *key = NULL; + const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL; + const EVP_MD *sign_md = NULL; + STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL; STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; + STACK_OF(X509) *encerts = NULL, *other = NULL; + X509 *cert = NULL, *recip = NULL, *signer = NULL; + X509_STORE *store = NULL; + X509_VERIFY_PARAM *vpm = NULL; char *certfile = NULL, *keyfile = NULL, *contfile = NULL; + const char *CAfile = NULL, *CApath = NULL; char *certsoutfile = NULL; - const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL; - CMS_ContentInfo *cms = NULL, *rcms = NULL; - X509_STORE *store = NULL; - X509 *cert = NULL, *recip = NULL, *signer = NULL; - EVP_PKEY *key = NULL; - STACK_OF(X509) *encerts = NULL, *other = NULL; - BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL; - int badarg = 0; - int flags = CMS_DETACHED, noout = 0, print = 0; - int verify_retcode = 0; - int rr_print = 0, rr_allorfirst = -1; - STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL; - CMS_ReceiptRequest *rr = NULL; - char *to = NULL, *from = NULL, *subject = NULL; - char *CAfile = NULL, *CApath = NULL; - char *passargin = NULL, *passin = NULL; - char *inrand = NULL; - int need_rand = 0; - const EVP_MD *sign_md = NULL; + int noCAfile = 0, noCApath = 0; + char *infile = NULL, *outfile = NULL, *rctfile = NULL; + char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL; + char *to = NULL, *from = NULL, *subject = NULL, *prog; + cms_key_param *key_first = NULL, *key_param = NULL; + int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; - int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM; - char *engine = NULL; - unsigned char *secret_key = NULL, *secret_keyid = NULL; - unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; + int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1; + int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM; size_t secret_keylen = 0, secret_keyidlen = 0; + unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; + unsigned char *secret_key = NULL, *secret_keyid = NULL; + long ltmp; + const char *mime_eol = "\n"; + OPTION_CHOICE o; - cms_key_param *key_first = NULL, *key_param = NULL; - - ASN1_OBJECT *econtent_type = NULL; - - X509_VERIFY_PARAM *vpm = NULL; - - args = argv + 1; - ret = 1; - - apps_startup(); - - if (bio_err == NULL) { - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - } - - if (!load_config(bio_err, NULL)) - goto end; + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + return 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-encrypt")) + prog = opt_init(argc, argv, cms_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(cms_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENCRYPT: operation = SMIME_ENCRYPT; - else if (!strcmp(*args, "-decrypt")) + break; + case OPT_DECRYPT: operation = SMIME_DECRYPT; - else if (!strcmp(*args, "-sign")) + break; + case OPT_SIGN: operation = SMIME_SIGN; - else if (!strcmp(*args, "-sign_receipt")) + break; + case OPT_SIGN_RECEIPT: operation = SMIME_SIGN_RECEIPT; - else if (!strcmp(*args, "-resign")) + break; + case OPT_RESIGN: operation = SMIME_RESIGN; - else if (!strcmp(*args, "-verify")) + break; + case OPT_VERIFY: operation = SMIME_VERIFY; - else if (!strcmp(*args, "-verify_retcode")) + break; + case OPT_VERIFY_RETCODE: verify_retcode = 1; - else if (!strcmp(*args, "-verify_receipt")) { + break; + case OPT_VERIFY_RECEIPT: operation = SMIME_VERIFY_RECEIPT; - if (!args[1]) - goto argerr; - args++; - rctfile = *args; - } else if (!strcmp(*args, "-cmsout")) + rctfile = opt_arg(); + break; + case OPT_CMSOUT: operation = SMIME_CMSOUT; - else if (!strcmp(*args, "-data_out")) + break; + case OPT_DATA_OUT: operation = SMIME_DATAOUT; - else if (!strcmp(*args, "-data_create")) + break; + case OPT_DATA_CREATE: operation = SMIME_DATA_CREATE; - else if (!strcmp(*args, "-digest_verify")) + break; + case OPT_DIGEST_VERIFY: operation = SMIME_DIGEST_VERIFY; - else if (!strcmp(*args, "-digest_create")) + break; + case OPT_DIGEST_CREATE: operation = SMIME_DIGEST_CREATE; - else if (!strcmp(*args, "-compress")) + break; + case OPT_COMPRESS: operation = SMIME_COMPRESS; - else if (!strcmp(*args, "-uncompress")) + break; + case OPT_UNCOMPRESS: operation = SMIME_UNCOMPRESS; - else if (!strcmp(*args, "-EncryptedData_decrypt")) + break; + case OPT_ED_DECRYPT: operation = SMIME_ENCRYPTED_DECRYPT; - else if (!strcmp(*args, "-EncryptedData_encrypt")) + break; + case OPT_ED_ENCRYPT: operation = SMIME_ENCRYPTED_ENCRYPT; -# ifndef OPENSSL_NO_DES - else if (!strcmp(*args, "-des3")) - cipher = EVP_des_ede3_cbc(); - else if (!strcmp(*args, "-des")) - cipher = EVP_des_cbc(); - else if (!strcmp(*args, "-des3-wrap")) - wrap_cipher = EVP_des_ede3_wrap(); -# endif -# ifndef OPENSSL_NO_SEED - else if (!strcmp(*args, "-seed")) - cipher = EVP_seed_cbc(); -# endif -# ifndef OPENSSL_NO_RC2 - else if (!strcmp(*args, "-rc2-40")) - cipher = EVP_rc2_40_cbc(); - else if (!strcmp(*args, "-rc2-128")) - cipher = EVP_rc2_cbc(); - else if (!strcmp(*args, "-rc2-64")) - cipher = EVP_rc2_64_cbc(); -# endif -# ifndef OPENSSL_NO_AES - else if (!strcmp(*args, "-aes128")) - cipher = EVP_aes_128_cbc(); - else if (!strcmp(*args, "-aes192")) - cipher = EVP_aes_192_cbc(); - else if (!strcmp(*args, "-aes256")) - cipher = EVP_aes_256_cbc(); - else if (!strcmp(*args, "-aes128-wrap")) - wrap_cipher = EVP_aes_128_wrap(); - else if (!strcmp(*args, "-aes192-wrap")) - wrap_cipher = EVP_aes_192_wrap(); - else if (!strcmp(*args, "-aes256-wrap")) - wrap_cipher = EVP_aes_256_wrap(); -# endif -# ifndef OPENSSL_NO_CAMELLIA - else if (!strcmp(*args, "-camellia128")) - cipher = EVP_camellia_128_cbc(); - else if (!strcmp(*args, "-camellia192")) - cipher = EVP_camellia_192_cbc(); - else if (!strcmp(*args, "-camellia256")) - cipher = EVP_camellia_256_cbc(); -# endif - else if (!strcmp(*args, "-debug_decrypt")) + break; + case OPT_DEBUG_DECRYPT: flags |= CMS_DEBUG_DECRYPT; - else if (!strcmp(*args, "-text")) + break; + case OPT_TEXT: flags |= CMS_TEXT; - else if (!strcmp(*args, "-nointern")) + break; + case OPT_ASCIICRLF: + flags |= CMS_ASCIICRLF; + break; + case OPT_NOINTERN: flags |= CMS_NOINTERN; - else if (!strcmp(*args, "-noverify") - || !strcmp(*args, "-no_signer_cert_verify")) + break; + case OPT_NOVERIFY: flags |= CMS_NO_SIGNER_CERT_VERIFY; - else if (!strcmp(*args, "-nocerts")) + break; + case OPT_NOCERTS: flags |= CMS_NOCERTS; - else if (!strcmp(*args, "-noattr")) + break; + case OPT_NOATTR: flags |= CMS_NOATTR; - else if (!strcmp(*args, "-nodetach")) + break; + case OPT_NODETACH: flags &= ~CMS_DETACHED; - else if (!strcmp(*args, "-nosmimecap")) + break; + case OPT_NOSMIMECAP: flags |= CMS_NOSMIMECAP; - else if (!strcmp(*args, "-binary")) + break; + case OPT_BINARY: flags |= CMS_BINARY; - else if (!strcmp(*args, "-keyid")) + break; + case OPT_KEYID: flags |= CMS_USE_KEYID; - else if (!strcmp(*args, "-nosigs")) + break; + case OPT_NOSIGS: flags |= CMS_NOSIGS; - else if (!strcmp(*args, "-no_content_verify")) + break; + case OPT_NO_CONTENT_VERIFY: flags |= CMS_NO_CONTENT_VERIFY; - else if (!strcmp(*args, "-no_attr_verify")) + break; + case OPT_NO_ATTR_VERIFY: flags |= CMS_NO_ATTR_VERIFY; - else if (!strcmp(*args, "-stream")) - flags |= CMS_STREAM; - else if (!strcmp(*args, "-indef")) + break; + case OPT_INDEF: flags |= CMS_STREAM; - else if (!strcmp(*args, "-noindef")) + break; + case OPT_NOINDEF: flags &= ~CMS_STREAM; - else if (!strcmp(*args, "-nooldmime")) - flags |= CMS_NOOLDMIMETYPE; - else if (!strcmp(*args, "-crlfeol")) + break; + case OPT_CRLFEOL: + mime_eol = "\r\n"; flags |= CMS_CRLFEOL; - else if (!strcmp(*args, "-noout")) + break; + case OPT_NOOUT: noout = 1; - else if (!strcmp(*args, "-receipt_request_print")) + break; + case OPT_RR_PRINT: rr_print = 1; - else if (!strcmp(*args, "-receipt_request_all")) + break; + case OPT_RR_ALL: rr_allorfirst = 0; - else if (!strcmp(*args, "-receipt_request_first")) + break; + case OPT_RR_FIRST: rr_allorfirst = 1; - else if (!strcmp(*args, "-receipt_request_from")) { - if (!args[1]) - goto argerr; - args++; - if (!rr_from) - rr_from = sk_OPENSSL_STRING_new_null(); - sk_OPENSSL_STRING_push(rr_from, *args); - } else if (!strcmp(*args, "-receipt_request_to")) { - if (!args[1]) - goto argerr; - args++; - if (!rr_to) - rr_to = sk_OPENSSL_STRING_new_null(); - sk_OPENSSL_STRING_push(rr_to, *args); - } else if (!strcmp(*args, "-print")) { - noout = 1; - print = 1; - } else if (!strcmp(*args, "-secretkey")) { - long ltmp; - if (!args[1]) - goto argerr; - args++; - secret_key = string_to_hex(*args, <mp); - if (!secret_key) { - BIO_printf(bio_err, "Invalid key %s\n", *args); - goto argerr; + break; + case OPT_RCTFORM: + if (rctformat == FORMAT_SMIME) + rcms = SMIME_read_CMS(rctin, NULL); + else if (rctformat == FORMAT_PEM) + rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); + else if (rctformat == FORMAT_ASN1) + if (!opt_format(opt_arg(), + OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat)) + goto opthelp; + break; + case OPT_CERTFILE: + certfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_CONTENT: + contfile = opt_arg(); + break; + case OPT_RR_FROM: + if (rr_from == NULL + && (rr_from = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(rr_from, opt_arg()); + break; + case OPT_RR_TO: + if (rr_to == NULL + && (rr_to = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(rr_to, opt_arg()); + break; + case OPT_PRINT: + noout = print = 1; + break; + case OPT_SECRETKEY: + if (secret_key != NULL) { + BIO_printf(bio_err, "Invalid key (supplied twice) %s\n", + opt_arg()); + goto opthelp; + } + secret_key = OPENSSL_hexstr2buf(opt_arg(), <mp); + if (secret_key == NULL) { + BIO_printf(bio_err, "Invalid key %s\n", opt_arg()); + goto end; } secret_keylen = (size_t)ltmp; - } else if (!strcmp(*args, "-secretkeyid")) { - long ltmp; - if (!args[1]) - goto argerr; - args++; - secret_keyid = string_to_hex(*args, <mp); - if (!secret_keyid) { - BIO_printf(bio_err, "Invalid id %s\n", *args); - goto argerr; + break; + case OPT_SECRETKEYID: + if (secret_keyid != NULL) { + BIO_printf(bio_err, "Invalid id (supplied twice) %s\n", + opt_arg()); + goto opthelp; + } + secret_keyid = OPENSSL_hexstr2buf(opt_arg(), <mp); + if (secret_keyid == NULL) { + BIO_printf(bio_err, "Invalid id %s\n", opt_arg()); + goto opthelp; } secret_keyidlen = (size_t)ltmp; - } else if (!strcmp(*args, "-pwri_password")) { - if (!args[1]) - goto argerr; - args++; - pwri_pass = (unsigned char *)*args; - } else if (!strcmp(*args, "-econtent_type")) { - if (!args[1]) - goto argerr; - args++; - econtent_type = OBJ_txt2obj(*args, 0); - if (!econtent_type) { - BIO_printf(bio_err, "Invalid OID %s\n", *args); - goto argerr; + break; + case OPT_PWRI_PASSWORD: + pwri_pass = (unsigned char *)opt_arg(); + break; + case OPT_ECONTENT_TYPE: + if (econtent_type != NULL) { + BIO_printf(bio_err, "Invalid OID (supplied twice) %s\n", + opt_arg()); + goto opthelp; } - } else if (!strcmp(*args, "-rand")) { - if (!args[1]) - goto argerr; - args++; - inrand = *args; - need_rand = 1; - } -# ifndef OPENSSL_NO_ENGINE - else if (!strcmp(*args, "-engine")) { - if (!args[1]) - goto argerr; - engine = *++args; - } -# endif - else if (!strcmp(*args, "-passin")) { - if (!args[1]) - goto argerr; - passargin = *++args; - } else if (!strcmp(*args, "-to")) { - if (!args[1]) - goto argerr; - to = *++args; - } else if (!strcmp(*args, "-from")) { - if (!args[1]) - goto argerr; - from = *++args; - } else if (!strcmp(*args, "-subject")) { - if (!args[1]) - goto argerr; - subject = *++args; - } else if (!strcmp(*args, "-signer")) { - if (!args[1]) - goto argerr; + econtent_type = OBJ_txt2obj(opt_arg(), 0); + if (econtent_type == NULL) { + BIO_printf(bio_err, "Invalid OID %s\n", opt_arg()); + goto opthelp; + } + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_TO: + to = opt_arg(); + break; + case OPT_FROM: + from = opt_arg(); + break; + case OPT_SUBJECT: + subject = opt_arg(); + break; + case OPT_CERTSOUT: + certsoutfile = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_arg(), &sign_md)) + goto end; + break; + case OPT_SIGNER: /* If previous -signer argument add signer to list */ - - if (signerfile) { - if (!sksigners) - sksigners = sk_OPENSSL_STRING_new_null(); + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); - if (!keyfile) + if (keyfile == NULL) keyfile = signerfile; - if (!skkeys) - skkeys = sk_OPENSSL_STRING_new_null(); + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(skkeys, keyfile); keyfile = NULL; } - signerfile = *++args; - } else if (!strcmp(*args, "-recip")) { - if (!args[1]) - goto argerr; - if (operation == SMIME_ENCRYPT) { - if (!encerts) - encerts = sk_X509_new_null(); - cert = load_cert(bio_err, *++args, FORMAT_PEM, - NULL, e, "recipient certificate file"); - if (!cert) - goto end; - sk_X509_push(encerts, cert); - cert = NULL; - } else - recipfile = *++args; - } else if (!strcmp(*args, "-certsout")) { - if (!args[1]) - goto argerr; - certsoutfile = *++args; - } else if (!strcmp(*args, "-md")) { - if (!args[1]) - goto argerr; - sign_md = EVP_get_digestbyname(*++args); - if (sign_md == NULL) { - BIO_printf(bio_err, "Unknown digest %s\n", *args); - goto argerr; - } - } else if (!strcmp(*args, "-inkey")) { - if (!args[1]) - goto argerr; - /* If previous -inkey arument add signer to list */ - if (keyfile) { - if (!signerfile) { + signerfile = opt_arg(); + break; + case OPT_INKEY: + /* If previous -inkey argument add signer to list */ + if (keyfile != NULL) { + if (signerfile == NULL) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); - goto argerr; + goto end; } - if (!sksigners) - sksigners = sk_OPENSSL_STRING_new_null(); + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); signerfile = NULL; - if (!skkeys) - skkeys = sk_OPENSSL_STRING_new_null(); + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(skkeys, keyfile); } - keyfile = *++args; - } else if (!strcmp(*args, "-keyform")) { - if (!args[1]) - goto argerr; - keyform = str2fmt(*++args); - } else if (!strcmp(*args, "-keyopt")) { - int keyidx = -1; - if (!args[1]) - goto argerr; + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_RECIP: if (operation == SMIME_ENCRYPT) { - if (encerts) + if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL) + goto end; + cert = load_cert(opt_arg(), FORMAT_PEM, + "recipient certificate file"); + if (cert == NULL) + goto end; + sk_X509_push(encerts, cert); + cert = NULL; + } else { + recipfile = opt_arg(); + } + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &cipher)) + goto end; + break; + case OPT_KEYOPT: + keyidx = -1; + if (operation == SMIME_ENCRYPT) { + if (encerts != NULL) keyidx += sk_X509_num(encerts); } else { - if (keyfile || signerfile) + if (keyfile != NULL || signerfile != NULL) keyidx++; - if (skkeys) + if (skkeys != NULL) keyidx += sk_OPENSSL_STRING_num(skkeys); } if (keyidx < 0) { BIO_printf(bio_err, "No key specified\n"); - goto argerr; + goto opthelp; } if (key_param == NULL || key_param->idx != keyidx) { cms_key_param *nparam; - nparam = OPENSSL_malloc(sizeof(cms_key_param)); - if (!nparam) { - BIO_printf(bio_err, "Out of memory\n"); - goto argerr; - } + nparam = app_malloc(sizeof(*nparam), "key param buffer"); nparam->idx = keyidx; - nparam->param = sk_OPENSSL_STRING_new_null(); + if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; nparam->next = NULL; if (key_first == NULL) key_first = nparam; @@ -474,229 +555,107 @@ int MAIN(int argc, char **argv) key_param->next = nparam; key_param = nparam; } - sk_OPENSSL_STRING_push(key_param->param, *++args); - } else if (!strcmp(*args, "-rctform")) { - if (!args[1]) - goto argerr; - rctformat = str2fmt(*++args); - } else if (!strcmp(*args, "-certfile")) { - if (!args[1]) - goto argerr; - certfile = *++args; - } else if (!strcmp(*args, "-CAfile")) { - if (!args[1]) - goto argerr; - CAfile = *++args; - } else if (!strcmp(*args, "-CApath")) { - if (!args[1]) - goto argerr; - CApath = *++args; - } else if (!strcmp(*args, "-in")) { - if (!args[1]) - goto argerr; - infile = *++args; - } else if (!strcmp(*args, "-inform")) { - if (!args[1]) - goto argerr; - informat = str2fmt(*++args); - } else if (!strcmp(*args, "-outform")) { - if (!args[1]) - goto argerr; - outformat = str2fmt(*++args); - } else if (!strcmp(*args, "-out")) { - if (!args[1]) - goto argerr; - outfile = *++args; - } else if (!strcmp(*args, "-content")) { - if (!args[1]) - goto argerr; - contfile = *++args; - } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) - continue; - else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL) - badarg = 1; - args++; + sk_OPENSSL_STRING_push(key_param->param, opt_arg()); + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_3DES_WRAP: +# ifndef OPENSSL_NO_DES + wrap_cipher = EVP_des_ede3_wrap(); +# endif + break; + case OPT_AES128_WRAP: + wrap_cipher = EVP_aes_128_wrap(); + break; + case OPT_AES192_WRAP: + wrap_cipher = EVP_aes_192_wrap(); + break; + case OPT_AES256_WRAP: + wrap_cipher = EVP_aes_256_wrap(); + break; + } } + argc = opt_num_rest(); + argv = opt_rest(); - if (((rr_allorfirst != -1) || rr_from) && !rr_to) { + if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) { BIO_puts(bio_err, "No Signed Receipts Recipients\n"); - goto argerr; + goto opthelp; } - if (!(operation & SMIME_SIGNERS) && (rr_to || rr_from)) { + if (!(operation & SMIME_SIGNERS) && (rr_to != NULL || rr_from != NULL)) { BIO_puts(bio_err, "Signed receipts only allowed with -sign\n"); - goto argerr; + goto opthelp; } - if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { + if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); - goto argerr; + goto opthelp; } if (operation & SMIME_SIGNERS) { - if (keyfile && !signerfile) { + if (keyfile != NULL && signerfile == NULL) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); - goto argerr; + goto opthelp; } /* Check to see if any final signer needs to be appended */ - if (signerfile) { - if (!sksigners) - sksigners = sk_OPENSSL_STRING_new_null(); + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); - if (!skkeys) - skkeys = sk_OPENSSL_STRING_new_null(); - if (!keyfile) + if (skkeys == NULL && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + if (keyfile == NULL) keyfile = signerfile; sk_OPENSSL_STRING_push(skkeys, keyfile); } - if (!sksigners) { + if (sksigners == NULL) { BIO_printf(bio_err, "No signer certificate specified\n"); - badarg = 1; + goto opthelp; } signerfile = NULL; keyfile = NULL; - need_rand = 1; - } - - else if (operation == SMIME_DECRYPT) { - if (!recipfile && !keyfile && !secret_key && !pwri_pass) { + } else if (operation == SMIME_DECRYPT) { + if (recipfile == NULL && keyfile == NULL + && secret_key == NULL && pwri_pass == NULL) { BIO_printf(bio_err, "No recipient certificate or key specified\n"); - badarg = 1; + goto opthelp; } } else if (operation == SMIME_ENCRYPT) { - if (!*args && !secret_key && !pwri_pass && !encerts) { + if (*argv == NULL && secret_key == NULL + && pwri_pass == NULL && encerts == NULL) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); - badarg = 1; + goto opthelp; } - need_rand = 1; - } else if (!operation) - badarg = 1; - - if (badarg) { - argerr: - BIO_printf(bio_err, "Usage cms [options] cert.pem ...\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-encrypt encrypt message\n"); - BIO_printf(bio_err, "-decrypt decrypt encrypted message\n"); - BIO_printf(bio_err, "-sign sign message\n"); - BIO_printf(bio_err, "-verify verify signed message\n"); - BIO_printf(bio_err, "-cmsout output CMS structure\n"); -# ifndef OPENSSL_NO_DES - BIO_printf(bio_err, "-des3 encrypt with triple DES\n"); - BIO_printf(bio_err, "-des encrypt with DES\n"); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, "-seed encrypt with SEED\n"); -# endif -# ifndef OPENSSL_NO_RC2 - BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); - BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n"); - BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n"); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc aes\n"); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc camellia\n"); -# endif - BIO_printf(bio_err, - "-nointern don't search certificates in message for signer\n"); - BIO_printf(bio_err, - "-nosigs don't verify message signature\n"); - BIO_printf(bio_err, - "-noverify don't verify signers certificate\n"); - BIO_printf(bio_err, - "-nocerts don't include signers certificate when signing\n"); - BIO_printf(bio_err, "-nodetach use opaque signing\n"); - BIO_printf(bio_err, - "-noattr don't include any signed attributes\n"); - BIO_printf(bio_err, - "-binary don't translate message to text\n"); - BIO_printf(bio_err, "-certfile file other certificates file\n"); - BIO_printf(bio_err, "-certsout file certificate output file\n"); - BIO_printf(bio_err, "-signer file signer certificate file\n"); - BIO_printf(bio_err, - "-recip file recipient certificate file for decryption\n"); - BIO_printf(bio_err, "-keyid use subject key identifier\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, - "-inform arg input format SMIME (default), PEM or DER\n"); - BIO_printf(bio_err, - "-inkey file input private key (if not signer or recipient)\n"); - BIO_printf(bio_err, - "-keyform arg input private key format (PEM or ENGINE)\n"); - BIO_printf(bio_err, "-keyopt nm:v set public key parameters\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, - "-outform arg output format SMIME (default), PEM or DER\n"); - BIO_printf(bio_err, - "-content file supply or override content for detached signature\n"); - BIO_printf(bio_err, "-to addr to address\n"); - BIO_printf(bio_err, "-from ad from address\n"); - BIO_printf(bio_err, "-subject s subject\n"); - BIO_printf(bio_err, - "-text include or delete text MIME headers\n"); - BIO_printf(bio_err, - "-CApath dir trusted certificates directory\n"); - BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); - BIO_printf(bio_err, - "-no_alt_chains only ever use the first certificate chain found\n"); - BIO_printf(bio_err, - "-crl_check check revocation status of signer's certificate using CRLs\n"); - BIO_printf(bio_err, - "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); - BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - BIO_printf(bio_err, - "cert.pem recipient certificate(s) for encryption\n"); - goto end; + } else if (!operation) { + goto opthelp; } - e = setup_engine(bio_err, engine, 0); - if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } - if (need_rand) { - app_RAND_load_file(NULL, bio_err, (inrand != NULL)); - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - } - ret = 2; if (!(operation & SMIME_SIGNERS)) flags &= ~CMS_DETACHED; - if (operation & SMIME_OP) { - if (outformat == FORMAT_ASN1) - outmode = "wb"; - } else { + if (!(operation & SMIME_OP)) if (flags & CMS_BINARY) - outmode = "wb"; - } + outformat = FORMAT_BINARY; - if (operation & SMIME_IP) { - if (informat == FORMAT_ASN1) - inmode = "rb"; - } else { + if (!(operation & SMIME_IP)) if (flags & CMS_BINARY) - inmode = "rb"; - } + informat = FORMAT_BINARY; if (operation == SMIME_ENCRYPT) { if (!cipher) { @@ -713,90 +672,87 @@ int MAIN(int argc, char **argv) goto end; } - if (*args && !encerts) - encerts = sk_X509_new_null(); - while (*args) { - if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, - NULL, e, "recipient certificate file"))) + if (*argv && encerts == NULL) + if ((encerts = sk_X509_new_null()) == NULL) + goto end; + while (*argv) { + if ((cert = load_cert(*argv, FORMAT_PEM, + "recipient certificate file")) == NULL) goto end; sk_X509_push(encerts, cert); cert = NULL; - args++; + argv++; } } - if (certfile) { - if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL, - e, "certificate file"))) { + if (certfile != NULL) { + if (!load_certs(certfile, &other, FORMAT_PEM, NULL, + "certificate file")) { ERR_print_errors(bio_err); goto end; } } - if (recipfile && (operation == SMIME_DECRYPT)) { - if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL, - e, "recipient certificate file"))) { + if (recipfile != NULL && (operation == SMIME_DECRYPT)) { + if ((recip = load_cert(recipfile, FORMAT_PEM, + "recipient certificate file")) == NULL) { ERR_print_errors(bio_err); goto end; } } if (operation == SMIME_SIGN_RECEIPT) { - if (!(signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, - e, "receipt signer certificate file"))) { + if ((signer = load_cert(signerfile, FORMAT_PEM, + "receipt signer certificate file")) == NULL) { ERR_print_errors(bio_err); goto end; } } if (operation == SMIME_DECRYPT) { - if (!keyfile) + if (keyfile == NULL) keyfile = recipfile; } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) { - if (!keyfile) + if (keyfile == NULL) keyfile = signerfile; - } else + } else { keyfile = NULL; + } - if (keyfile) { - key = load_key(bio_err, keyfile, keyform, 0, passin, e, - "signing key file"); - if (!key) + if (keyfile != NULL) { + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) goto end; } - if (infile) { - if (!(in = BIO_new_file(infile, inmode))) { - BIO_printf(bio_err, "Can't open input file %s\n", infile); - goto end; - } - } else - in = BIO_new_fp(stdin, BIO_NOCLOSE); + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; if (operation & SMIME_IP) { - if (informat == FORMAT_SMIME) + if (informat == FORMAT_SMIME) { cms = SMIME_read_CMS(in, &indata); - else if (informat == FORMAT_PEM) + } else if (informat == FORMAT_PEM) { cms = PEM_read_bio_CMS(in, NULL, NULL, NULL); - else if (informat == FORMAT_ASN1) + } else if (informat == FORMAT_ASN1) { cms = d2i_CMS_bio(in, NULL); - else { + } else { BIO_printf(bio_err, "Bad input format for CMS file\n"); goto end; } - if (!cms) { + if (cms == NULL) { BIO_printf(bio_err, "Error reading S/MIME message\n"); goto end; } - if (contfile) { + if (contfile != NULL) { BIO_free(indata); - if (!(indata = BIO_new_file(contfile, "rb"))) { + if ((indata = BIO_new_file(contfile, "rb")) == NULL) { BIO_printf(bio_err, "Can't read content file %s\n", contfile); goto end; } } - if (certsoutfile) { + if (certsoutfile != NULL) { STACK_OF(X509) *allcerts; allcerts = CMS_get1_certs(cms); if (!save_certs(certsoutfile, allcerts)) { @@ -809,50 +765,39 @@ int MAIN(int argc, char **argv) } } - if (rctfile) { + if (rctfile != NULL) { char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r"; - if (!(rctin = BIO_new_file(rctfile, rctmode))) { + if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) { BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile); goto end; } - if (rctformat == FORMAT_SMIME) + if (rctformat == FORMAT_SMIME) { rcms = SMIME_read_CMS(rctin, NULL); - else if (rctformat == FORMAT_PEM) + } else if (rctformat == FORMAT_PEM) { rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); - else if (rctformat == FORMAT_ASN1) + } else if (rctformat == FORMAT_ASN1) { rcms = d2i_CMS_bio(rctin, NULL); - else { + } else { BIO_printf(bio_err, "Bad input format for receipt\n"); goto end; } - if (!rcms) { + if (rcms == NULL) { BIO_printf(bio_err, "Error reading receipt\n"); goto end; } } - if (outfile) { - if (!(out = BIO_new_file(outfile, outmode))) { - BIO_printf(bio_err, "Can't open output file %s\n", outfile); - goto end; - } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) { - if (!(store = setup_verify(bio_err, CAfile, CApath))) + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) goto end; X509_STORE_set_verify_cb(store, cms_cb); - if (vpm) + if (vpmtouched) X509_STORE_set1_param(store, vpm); } @@ -868,7 +813,7 @@ int MAIN(int argc, char **argv) int i; flags |= CMS_PARTIAL; cms = CMS_encrypt(NULL, in, cipher, flags); - if (!cms) + if (cms == NULL) goto end; for (i = 0; i < sk_X509_num(encerts); i++) { CMS_RecipientInfo *ri; @@ -882,9 +827,9 @@ int MAIN(int argc, char **argv) } } ri = CMS_add1_recipient_cert(cms, x, tflags); - if (!ri) + if (ri == NULL) goto end; - if (kparam) { + if (kparam != NULL) { EVP_PKEY_CTX *pctx; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!cms_set_pkey_param(pctx, kparam->param)) @@ -898,7 +843,7 @@ int MAIN(int argc, char **argv) } } - if (secret_key) { + if (secret_key != NULL) { if (!CMS_add0_recipient_key(cms, NID_undef, secret_key, secret_keylen, secret_keyid, secret_keyidlen, @@ -908,13 +853,13 @@ int MAIN(int argc, char **argv) secret_key = NULL; secret_keyid = NULL; } - if (pwri_pass) { - pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass); - if (!pwri_tmp) + if (pwri_pass != NULL) { + pwri_tmp = (unsigned char *)OPENSSL_strdup((char *)pwri_pass); + if (pwri_tmp == NULL) goto end; - if (!CMS_add0_recipient_password(cms, - -1, NID_undef, NID_undef, - pwri_tmp, -1, NULL)) + if (CMS_add0_recipient_password(cms, + -1, NID_undef, NID_undef, + pwri_tmp, -1, NULL) == NULL) goto end; pwri_tmp = NULL; } @@ -931,11 +876,11 @@ int MAIN(int argc, char **argv) STACK_OF(CMS_SignerInfo) *sis; CMS_SignerInfo *si; sis = CMS_get0_SignerInfos(cms); - if (!sis) + if (sis == NULL) goto end; si = sk_CMS_SignerInfo_value(sis, 0); srcms = CMS_sign_receipt(si, signer, key, other, flags); - if (!srcms) + if (srcms == NULL) goto end; CMS_ContentInfo_free(cms); cms = srcms; @@ -953,21 +898,22 @@ int MAIN(int argc, char **argv) } flags |= CMS_PARTIAL; cms = CMS_sign(NULL, NULL, other, in, flags); - if (!cms) + if (cms == NULL) goto end; - if (econtent_type) + if (econtent_type != NULL) CMS_set1_eContentType(cms, econtent_type); - if (rr_to) { + if (rr_to != NULL) { rr = make_receipt_request(rr_to, rr_allorfirst, rr_from); - if (!rr) { + if (rr == NULL) { BIO_puts(bio_err, "Signed Receipt Request Creation Error\n"); goto end; } } - } else + } else { flags |= CMS_REUSE_DIGEST; + } for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { CMS_SignerInfo *si; cms_key_param *kparam; @@ -975,15 +921,13 @@ int MAIN(int argc, char **argv) signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); - signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, - e, "signer certificate"); - if (!signer) { + signer = load_cert(signerfile, FORMAT_PEM, "signer certificate"); + if (signer == NULL) { ret = 2; goto end; } - key = load_key(bio_err, keyfile, keyform, 0, passin, e, - "signing key file"); - if (!key) { + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) { ret = 2; goto end; } @@ -994,15 +938,15 @@ int MAIN(int argc, char **argv) } } si = CMS_add1_signer(cms, signer, key, sign_md, tflags); - if (!si) + if (si == NULL) goto end; - if (kparam) { + if (kparam != NULL) { EVP_PKEY_CTX *pctx; pctx = CMS_SignerInfo_get0_pkey_ctx(si); if (!cms_set_pkey_param(pctx, kparam->param)) goto end; } - if (rr && !CMS_add1_ReceiptRequest(si, rr)) + if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr)) goto end; X509_free(signer); signer = NULL; @@ -1016,7 +960,7 @@ int MAIN(int argc, char **argv) } } - if (!cms) { + if (cms == NULL) { BIO_printf(bio_err, "Error creating CMS structure\n"); goto end; } @@ -1026,7 +970,7 @@ int MAIN(int argc, char **argv) if (flags & CMS_DEBUG_DECRYPT) CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags); - if (secret_key) { + if (secret_key != NULL) { if (!CMS_decrypt_set1_key(cms, secret_key, secret_keylen, secret_keyid, secret_keyidlen)) { @@ -1035,14 +979,14 @@ int MAIN(int argc, char **argv) } } - if (key) { + if (key != NULL) { if (!CMS_decrypt_set1_pkey(cms, key, recip)) { BIO_puts(bio_err, "Error decrypting CMS using private key\n"); goto end; } } - if (pwri_pass) { + if (pwri_pass != NULL) { if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) { BIO_puts(bio_err, "Error decrypting CMS using password\n"); goto end; @@ -1060,9 +1004,9 @@ int MAIN(int argc, char **argv) if (!CMS_uncompress(cms, indata, out, flags)) goto end; } else if (operation == SMIME_DIGEST_VERIFY) { - if (CMS_digest_verify(cms, indata, out, flags) > 0) + if (CMS_digest_verify(cms, indata, out, flags) > 0) { BIO_printf(bio_err, "Verification successful\n"); - else { + } else { BIO_printf(bio_err, "Verification failure\n"); goto end; } @@ -1071,15 +1015,15 @@ int MAIN(int argc, char **argv) indata, out, flags)) goto end; } else if (operation == SMIME_VERIFY) { - if (CMS_verify(cms, other, store, indata, out, flags) > 0) + if (CMS_verify(cms, other, store, indata, out, flags) > 0) { BIO_printf(bio_err, "Verification successful\n"); - else { + } else { BIO_printf(bio_err, "Verification failure\n"); if (verify_retcode) ret = verify_err + 32; goto end; } - if (signerfile) { + if (signerfile != NULL) { STACK_OF(X509) *signers; signers = CMS_get0_signers(cms); if (!save_certs(signerfile, signers)) { @@ -1091,12 +1035,12 @@ int MAIN(int argc, char **argv) sk_X509_free(signers); } if (rr_print) - receipt_request_print(bio_err, cms); + receipt_request_print(cms); } else if (operation == SMIME_VERIFY_RECEIPT) { - if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) + if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) { BIO_printf(bio_err, "Verification successful\n"); - else { + } else { BIO_printf(bio_err, "Verification failure\n"); goto end; } @@ -1106,20 +1050,20 @@ int MAIN(int argc, char **argv) CMS_ContentInfo_print_ctx(out, cms, 0, NULL); } else if (outformat == FORMAT_SMIME) { if (to) - BIO_printf(out, "To: %s\n", to); + BIO_printf(out, "To: %s%s", to, mime_eol); if (from) - BIO_printf(out, "From: %s\n", from); + BIO_printf(out, "From: %s%s", from, mime_eol); if (subject) - BIO_printf(out, "Subject: %s\n", subject); + BIO_printf(out, "Subject: %s%s", subject, mime_eol); if (operation == SMIME_RESIGN) ret = SMIME_write_CMS(out, cms, indata, flags); else ret = SMIME_write_CMS(out, cms, in, flags); - } else if (outformat == FORMAT_PEM) + } else if (outformat == FORMAT_PEM) { ret = PEM_write_bio_CMS_stream(out, cms, in, flags); - else if (outformat == FORMAT_ASN1) + } else if (outformat == FORMAT_ASN1) { ret = i2d_CMS_bio_stream(out, cms, in, flags); - else { + } else { BIO_printf(bio_err, "Bad output format for CMS file\n"); goto end; } @@ -1132,30 +1076,18 @@ int MAIN(int argc, char **argv) end: if (ret) ERR_print_errors(bio_err); - if (need_rand) - app_RAND_write_file(NULL, bio_err); sk_X509_pop_free(encerts, X509_free); sk_X509_pop_free(other, X509_free); - if (vpm) - X509_VERIFY_PARAM_free(vpm); - if (sksigners) - sk_OPENSSL_STRING_free(sksigners); - if (skkeys) - sk_OPENSSL_STRING_free(skkeys); - if (secret_key) - OPENSSL_free(secret_key); - if (secret_keyid) - OPENSSL_free(secret_keyid); - if (pwri_tmp) - OPENSSL_free(pwri_tmp); - if (econtent_type) - ASN1_OBJECT_free(econtent_type); - if (rr) - CMS_ReceiptRequest_free(rr); - if (rr_to) - sk_OPENSSL_STRING_free(rr_to); - if (rr_from) - sk_OPENSSL_STRING_free(rr_from); + X509_VERIFY_PARAM_free(vpm); + sk_OPENSSL_STRING_free(sksigners); + sk_OPENSSL_STRING_free(skkeys); + OPENSSL_free(secret_key); + OPENSSL_free(secret_keyid); + OPENSSL_free(pwri_tmp); + ASN1_OBJECT_free(econtent_type); + CMS_ReceiptRequest_free(rr); + sk_OPENSSL_STRING_free(rr_to); + sk_OPENSSL_STRING_free(rr_from); for (key_param = key_first; key_param;) { cms_key_param *tparam; sk_OPENSSL_STRING_free(key_param->param); @@ -1175,19 +1107,18 @@ int MAIN(int argc, char **argv) BIO_free(in); BIO_free(indata); BIO_free_all(out); - if (passin) - OPENSSL_free(passin); - return (ret); + OPENSSL_free(passin); + return ret; } static int save_certs(char *signerfile, STACK_OF(X509) *signers) { int i; BIO *tmp; - if (!signerfile) + if (signerfile == NULL) return 1; tmp = BIO_new_file(signerfile, "w"); - if (!tmp) + if (tmp == NULL) return 0; for (i = 0; i < sk_X509_num(signers); i++) PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); @@ -1209,30 +1140,31 @@ static int cms_cb(int ok, X509_STORE_CTX *ctx) && ((error != X509_V_OK) || (ok != 2))) return ok; - policies_print(NULL, ctx); + policies_print(ctx); return ok; } -static void gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns) +static void gnames_stack_print(STACK_OF(GENERAL_NAMES) *gns) { STACK_OF(GENERAL_NAME) *gens; GENERAL_NAME *gen; int i, j; + for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) { gens = sk_GENERAL_NAMES_value(gns, i); for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) { gen = sk_GENERAL_NAME_value(gens, j); - BIO_puts(out, " "); - GENERAL_NAME_print(out, gen); - BIO_puts(out, "\n"); + BIO_puts(bio_err, " "); + GENERAL_NAME_print(bio_err, gen); + BIO_puts(bio_err, "\n"); } } return; } -static void receipt_request_print(BIO *out, CMS_ContentInfo *cms) +static void receipt_request_print(CMS_ContentInfo *cms) { STACK_OF(CMS_SignerInfo) *sis; CMS_SignerInfo *si; @@ -1246,35 +1178,35 @@ static void receipt_request_print(BIO *out, CMS_ContentInfo *cms) si = sk_CMS_SignerInfo_value(sis, i); rv = CMS_get1_ReceiptRequest(si, &rr); BIO_printf(bio_err, "Signer %d:\n", i + 1); - if (rv == 0) + if (rv == 0) { BIO_puts(bio_err, " No Receipt Request\n"); - else if (rv < 0) { + } else if (rv < 0) { BIO_puts(bio_err, " Receipt Request Parse Error\n"); ERR_print_errors(bio_err); } else { - char *id; + const char *id; int idlen; CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst, &rlist, &rto); - BIO_puts(out, " Signed Content ID:\n"); + BIO_puts(bio_err, " Signed Content ID:\n"); idlen = ASN1_STRING_length(scid); - id = (char *)ASN1_STRING_data(scid); - BIO_dump_indent(out, id, idlen, 4); - BIO_puts(out, " Receipts From"); - if (rlist) { - BIO_puts(out, " List:\n"); - gnames_stack_print(out, rlist); - } else if (allorfirst == 1) - BIO_puts(out, ": First Tier\n"); - else if (allorfirst == 0) - BIO_puts(out, ": All\n"); - else - BIO_printf(out, " Unknown (%d)\n", allorfirst); - BIO_puts(out, " Receipts To:\n"); - gnames_stack_print(out, rto); + id = (const char *)ASN1_STRING_get0_data(scid); + BIO_dump_indent(bio_err, id, idlen, 4); + BIO_puts(bio_err, " Receipts From"); + if (rlist != NULL) { + BIO_puts(bio_err, " List:\n"); + gnames_stack_print(rlist); + } else if (allorfirst == 1) { + BIO_puts(bio_err, ": First Tier\n"); + } else if (allorfirst == 0) { + BIO_puts(bio_err, ": All\n"); + } else { + BIO_printf(bio_err, " Unknown (%d)\n", allorfirst); + } + BIO_puts(bio_err, " Receipts To:\n"); + gnames_stack_print(rto); } - if (rr) - CMS_ReceiptRequest_free(rr); + CMS_ReceiptRequest_free(rr); } } @@ -1285,15 +1217,15 @@ static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns) GENERAL_NAMES *gens = NULL; GENERAL_NAME *gen = NULL; ret = sk_GENERAL_NAMES_new_null(); - if (!ret) + if (ret == NULL) goto err; for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) { char *str = sk_OPENSSL_STRING_value(ns, i); gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0); - if (!gen) + if (gen == NULL) goto err; gens = GENERAL_NAMES_new(); - if (!gens) + if (gens == NULL) goto err; if (!sk_GENERAL_NAME_push(gens, gen)) goto err; @@ -1306,12 +1238,9 @@ static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns) return ret; err: - if (ret) - sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free); - if (gens) - GENERAL_NAMES_free(gens); - if (gen) - GENERAL_NAME_free(gen); + sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free); + GENERAL_NAMES_free(gens); + GENERAL_NAME_free(gen); return NULL; } @@ -1319,21 +1248,23 @@ static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) *rr_from) { - STACK_OF(GENERAL_NAMES) *rct_to, *rct_from; + STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL; CMS_ReceiptRequest *rr; rct_to = make_names_stack(rr_to); - if (!rct_to) + if (rct_to == NULL) goto err; - if (rr_from) { + if (rr_from != NULL) { rct_from = make_names_stack(rr_from); - if (!rct_from) + if (rct_from == NULL) goto err; - } else + } else { rct_from = NULL; + } rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from, rct_to); return rr; err: + sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free); return NULL; } diff --git a/apps/crl.c b/apps/crl.c index c9c3a5f6d196..031fada14c84 100644 --- a/apps/crl.c +++ b/apps/crl.c @@ -1,286 +1,209 @@ -/* apps/crl.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/x509.h> #include <openssl/x509v3.h> #include <openssl/pem.h> -#undef PROG -#define PROG crl_main - -#undef POSTFIX -#define POSTFIX ".rvk" +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_IN, OPT_OUTFORM, OPT_OUT, OPT_KEYFORM, OPT_KEY, + OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT, + OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE, + OPT_NOCAPATH, OPT_NOCAFILE, OPT_VERIFY, OPT_TEXT, OPT_HASH, OPT_HASH_OLD, + OPT_NOOUT, OPT_NAMEOPT, OPT_MD +} OPTION_CHOICE; -static const char *crl_usage[] = { - "usage: crl args\n", - "\n", - " -inform arg - input format - default PEM (DER or PEM)\n", - " -outform arg - output format - default PEM\n", - " -text - print out a text format version\n", - " -in arg - input file - default stdin\n", - " -out arg - output file - default stdout\n", - " -hash - print hash value\n", +const OPTIONS crl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format; default PEM"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, + {"out", OPT_OUT, '>', "output file - default stdout"}, + {"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"}, + {"key", OPT_KEY, '<', "CRL signing Private key to use"}, + {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, + {"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"}, + {"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"}, + {"noout", OPT_NOOUT, '-', "No CRL output"}, + {"fingerprint", OPT_FINGERPRINT, '-', "Print the crl fingerprint"}, + {"crlnumber", OPT_CRLNUMBER, '-', "Print CRL number"}, + {"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded CRL signature (for test)" }, + {"gendelta", OPT_GENDELTA, '<', "Other CRL to compare/diff to the Input one"}, + {"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"}, + {"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"verify", OPT_VERIFY, '-', "Verify CRL signature"}, + {"text", OPT_TEXT, '-', "Print out a text format version"}, + {"hash", OPT_HASH, '-', "Print hash value"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"", OPT_MD, '-', "Any supported digest"}, #ifndef OPENSSL_NO_MD5 - " -hash_old - print old-style (MD5) hash value\n", + {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"}, #endif - " -fingerprint - print the crl fingerprint\n", - " -issuer - print issuer DN\n", - " -lastupdate - lastUpdate field\n", - " -nextupdate - nextUpdate field\n", - " -crlnumber - print CRL number\n", - " -noout - no CRL output\n", - " -CAfile name - verify CRL using certificates in file \"name\"\n", - " -CApath dir - verify CRL using certificates in \"dir\"\n", - " -nameopt arg - various certificate name options\n", - NULL + {NULL} }; -static BIO *bio_out = NULL; - -int MAIN(int, char **); - -int MAIN(int argc, char **argv) +int crl_main(int argc, char **argv) { - unsigned long nmflag = 0; X509_CRL *x = NULL; - char *CAfile = NULL, *CApath = NULL; - int ret = 1, i, num, badops = 0, badsig = 0; BIO *out = NULL; - int informat, outformat, keyformat; + X509_STORE *store = NULL; + X509_STORE_CTX *ctx = NULL; + X509_LOOKUP *lookup = NULL; + X509_OBJECT *xobj = NULL; + EVP_PKEY *pkey; + const EVP_MD *digest = EVP_sha1(); char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL; - int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = - 0, text = 0; + const char *CAfile = NULL, *CApath = NULL, *prog; + OPTION_CHOICE o; + int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; + int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0; + int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0; + int i; #ifndef OPENSSL_NO_MD5 int hash_old = 0; #endif - int fingerprint = 0, crlnumber = 0; - const char **pp; - X509_STORE *store = NULL; - X509_STORE_CTX ctx; - X509_LOOKUP *lookup = NULL; - X509_OBJECT xobj; - EVP_PKEY *pkey; - int do_ver = 0; - const EVP_MD *md_alg, *digest = EVP_sha1(); - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - if (!load_config(bio_err, NULL)) - goto end; - - if (bio_out == NULL) - if ((bio_out = BIO_new(BIO_s_file())) != NULL) { - BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - bio_out = BIO_push(tmpbio, bio_out); - } -#endif - } - - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - keyformat = FORMAT_PEM; - - argc--; - argv++; - num = 0; - while (argc >= 1) { -#ifdef undef - if (strcmp(*argv, "-p") == 0) { - if (--argc < 1) - goto bad; - if (!args_from_file(++argv, Nargc, Nargv)) { - goto end; - } - */} -#endif - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-gendelta") == 0) { - if (--argc < 1) - goto bad; - crldiff = *(++argv); - } else if (strcmp(*argv, "-key") == 0) { - if (--argc < 1) - goto bad; - keyfile = *(++argv); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - goto bad; - keyformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-CApath") == 0) { - if (--argc < 1) - goto bad; - CApath = *(++argv); - do_ver = 1; - } else if (strcmp(*argv, "-CAfile") == 0) { - if (--argc < 1) - goto bad; - CAfile = *(++argv); + prog = opt_init(argc, argv, crl_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(crl_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) + goto opthelp; + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_GENDELTA: + crldiff = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); do_ver = 1; - } else if (strcmp(*argv, "-verify") == 0) + break; + case OPT_CAFILE: + CAfile = opt_arg(); do_ver = 1; - else if (strcmp(*argv, "-text") == 0) - text = 1; - else if (strcmp(*argv, "-hash") == 0) - hash = ++num; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_HASH_OLD: #ifndef OPENSSL_NO_MD5 - else if (strcmp(*argv, "-hash_old") == 0) hash_old = ++num; #endif - else if (strcmp(*argv, "-nameopt") == 0) { - if (--argc < 1) - goto bad; - if (!set_name_ex(&nmflag, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-issuer") == 0) + break; + case OPT_VERIFY: + do_ver = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_HASH: + hash = ++num; + break; + case OPT_ISSUER: issuer = ++num; - else if (strcmp(*argv, "-lastupdate") == 0) + break; + case OPT_LASTUPDATE: lastupdate = ++num; - else if (strcmp(*argv, "-nextupdate") == 0) + break; + case OPT_NEXTUPDATE: nextupdate = ++num; - else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_NOOUT: noout = ++num; - else if (strcmp(*argv, "-fingerprint") == 0) + break; + case OPT_FINGERPRINT: fingerprint = ++num; - else if (strcmp(*argv, "-crlnumber") == 0) + break; + case OPT_CRLNUMBER: crlnumber = ++num; - else if (strcmp(*argv, "-badsig") == 0) + break; + case OPT_BADSIG: badsig = 1; - else if ((md_alg = EVP_get_digestbyname(*argv + 1))) { - /* ok */ - digest = md_alg; - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto opthelp; + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &digest)) + goto opthelp; } - argc--; - argv++; - } - - if (badops) { - bad: - for (pp = crl_usage; (*pp != NULL); pp++) - BIO_printf(bio_err, "%s", *pp); - goto end; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - ERR_load_crypto_strings(); x = load_crl(infile, informat); - if (x == NULL) { + if (x == NULL) goto end; - } if (do_ver) { - store = X509_STORE_new(); - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - if (lookup == NULL) + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) goto end; - if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) - X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); - - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; - if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) - X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); - ERR_clear_error(); - - if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { + ctx = X509_STORE_CTX_new(); + if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } - i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, - X509_CRL_get_issuer(x), &xobj); - if (i <= 0) { + xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, + X509_CRL_get_issuer(x)); + if (xobj == NULL) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } - pkey = X509_get_pubkey(xobj.data.x509); - X509_OBJECT_free_contents(&xobj); + pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj)); + X509_OBJECT_free(xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; @@ -304,8 +227,7 @@ int MAIN(int argc, char **argv) newcrl = load_crl(crldiff, informat); if (!newcrl) goto end; - pkey = load_key(bio_err, keyfile, keyformat, 0, NULL, NULL, - "CRL signing key"); + pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key"); if (!pkey) { X509_CRL_free(newcrl); goto end; @@ -322,11 +244,18 @@ int MAIN(int argc, char **argv) } } + if (badsig) { + const ASN1_BIT_STRING *sig; + + X509_CRL_get0_signature(x, &sig, NULL); + corrupt_signature(sig); + } + if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), - nmflag); + get_nameopt()); } if (crlnumber == i) { ASN1_INTEGER *crlnum; @@ -351,13 +280,13 @@ int MAIN(int argc, char **argv) #endif if (lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); - ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); + ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); - if (X509_CRL_get_nextUpdate(x)) - ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); + if (X509_CRL_get0_nextUpdate(x)) + ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); @@ -380,63 +309,34 @@ int MAIN(int argc, char **argv) } } } - - out = BIO_new(BIO_s_file()); - if (out == NULL) { - ERR_print_errors(bio_err); + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) goto end; - } - - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } if (text) - X509_CRL_print(out, x); + X509_CRL_print_ex(out, x, get_nameopt()); if (noout) { ret = 0; goto end; } - if (badsig) - x->signature->data[x->signature->length - 1] ^= 0x1; - if (outformat == FORMAT_ASN1) i = (int)i2d_X509_CRL_bio(out, x); - else if (outformat == FORMAT_PEM) + else i = PEM_write_bio_X509_CRL(out, x); - else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; - } if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; + end: if (ret != 0) ERR_print_errors(bio_err); BIO_free_all(out); - BIO_free_all(bio_out); - bio_out = NULL; X509_CRL_free(x); - if (store) { - X509_STORE_CTX_cleanup(&ctx); - X509_STORE_free(store); - } - apps_shutdown(); - OPENSSL_EXIT(ret); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return ret; } diff --git a/apps/crl2p7.c b/apps/crl2p7.c index 0763817e617b..88fabcb22c36 100644 --- a/apps/crl2p7.c +++ b/apps/crl2p7.c @@ -1,71 +1,17 @@ -/* apps/crl2p7.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - /* - * This was written by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu> and - * donated 'to the cause' along with lots and lots of other fixes to the - * library. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <string.h> #include <sys/types.h> #include "apps.h" +#include "progs.h" #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/x509.h> @@ -74,129 +20,89 @@ #include <openssl/objects.h> static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile); -#undef PROG -#define PROG crl2pkcs7_main -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - */ +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS crl2pkcs7_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"nocrl", OPT_NOCRL, '-', "No crl to load, just certs from '-certfile'"}, + {"certfile", OPT_CERTFILE, '<', + "File of chain of certs to a trusted CA; can be repeated"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int crl2pkcs7_main(int argc, char **argv) { - int i, badops = 0; BIO *in = NULL, *out = NULL; - int informat, outformat; - char *infile, *outfile, *prog, *certfile; PKCS7 *p7 = NULL; PKCS7_SIGNED *p7s = NULL; - X509_CRL *crl = NULL; STACK_OF(OPENSSL_STRING) *certflst = NULL; - STACK_OF(X509_CRL) *crl_stack = NULL; STACK_OF(X509) *cert_stack = NULL; - int ret = 1, nocrl = 0; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; + STACK_OF(X509_CRL) *crl_stack = NULL; + X509_CRL *crl = NULL; + char *infile = NULL, *outfile = NULL, *prog, *certfile; + int i = 0, informat = FORMAT_PEM, outformat = FORMAT_PEM, ret = 1, nocrl = + 0; + OPTION_CHOICE o; - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-nocrl") == 0) { + prog = opt_init(argc, argv, crl2pkcs7_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(crl2pkcs7_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOCRL: nocrl = 1; - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-certfile") == 0) { - if (--argc < 1) - goto bad; - if (!certflst) - certflst = sk_OPENSSL_STRING_new_null(); - if (!certflst) + break; + case OPT_CERTFILE: + if ((certflst == NULL) + && (certflst = sk_OPENSSL_STRING_new_null()) == NULL) goto end; - if (!sk_OPENSSL_STRING_push(certflst, *(++argv))) { - sk_OPENSSL_STRING_free(certflst); + if (!sk_OPENSSL_STRING_push(certflst, opt_arg())) goto end; - } - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; break; } - argc--; - argv++; - } - - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - DER or PEM\n"); - BIO_printf(bio_err, " -outform arg output format - DER or PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, - " -certfile arg certificates file of chain to a trusted CA\n"); - BIO_printf(bio_err, " (can be used more than once)\n"); - BIO_printf(bio_err, - " -nocrl no crl to load, just certs from '-certfile'\n"); - ret = 1; - goto end; - } - - ERR_load_crypto_strings(); - - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); - goto end; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; if (!nocrl) { - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; if (informat == FORMAT_ASN1) crl = d2i_X509_CRL_bio(in, NULL); else if (informat == FORMAT_PEM) crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); - else { - BIO_printf(bio_err, "bad input format specified for input crl\n"); - goto end; - } if (crl == NULL) { BIO_printf(bio_err, "unable to load CRL\n"); ERR_print_errors(bio_err); @@ -226,7 +132,7 @@ int MAIN(int argc, char **argv) goto end; p7s->cert = cert_stack; - if (certflst) + if (certflst != NULL) for (i = 0; i < sk_OPENSSL_STRING_num(certflst); i++) { certfile = sk_OPENSSL_STRING_value(certflst, i); if (add_certs_from_file(cert_stack, certfile) < 0) { @@ -236,31 +142,14 @@ int MAIN(int argc, char **argv) } } - sk_OPENSSL_STRING_free(certflst); - - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; if (outformat == FORMAT_ASN1) i = i2d_PKCS7_bio(out, p7); else if (outformat == FORMAT_PEM) i = PEM_write_bio_PKCS7(out, p7); - else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; - } if (!i) { BIO_printf(bio_err, "unable to write pkcs7 object\n"); ERR_print_errors(bio_err); @@ -268,17 +157,13 @@ int MAIN(int argc, char **argv) } ret = 0; end: - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (p7 != NULL) - PKCS7_free(p7); - if (crl != NULL) - X509_CRL_free(crl); + sk_OPENSSL_STRING_free(certflst); + BIO_free(in); + BIO_free_all(out); + PKCS7_free(p7); + X509_CRL_free(crl); - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } /*- @@ -299,8 +184,8 @@ static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile) STACK_OF(X509_INFO) *sk = NULL; X509_INFO *xi; - in = BIO_new(BIO_s_file()); - if ((in == NULL) || (BIO_read_filename(in, certfile) <= 0)) { + in = BIO_new_file(certfile, "r"); + if (in == NULL) { BIO_printf(bio_err, "error opening the file, %s\n", certfile); goto end; } @@ -326,9 +211,7 @@ static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile) ret = count; end: /* never need to OPENSSL_free x */ - if (in != NULL) - BIO_free(in); - if (sk != NULL) - sk_X509_INFO_free(sk); - return (ret); + BIO_free(in); + sk_X509_INFO_free(sk); + return ret; } diff --git a/apps/ct_log_list.cnf b/apps/ct_log_list.cnf new file mode 100644 index 000000000000..650aa22da59c --- /dev/null +++ b/apps/ct_log_list.cnf @@ -0,0 +1,9 @@ +# This file specifies the Certificate Transparency logs +# that are to be trusted. + +# Google's list of logs can be found here: +# www.certificate-transparency.org/known-logs +# A Python program to convert the log list to OpenSSL's format can be +# found here: +# https://github.com/google/certificate-transparency/blob/master/python/utilities/log_list/print_log_list.py +# Use the "--openssl_output" flag. diff --git a/apps/dgst.c b/apps/dgst.c index 686fe344fbf5..d158a0ccb284 100644 --- a/apps/dgst.c +++ b/apps/dgst.c @@ -1,65 +1,17 @@ -/* apps/dgst.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/evp.h> @@ -71,230 +23,182 @@ #undef BUFSIZE #define BUFSIZE 1024*8 -#undef PROG -#define PROG dgst_main - int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *sig_name, const char *md_name, - const char *file, BIO *bmd); + const char *file); -static void list_md_fn(const EVP_MD *m, - const char *from, const char *to, void *arg) -{ - const char *mname; - /* Skip aliases */ - if (!m) - return; - mname = OBJ_nid2ln(EVP_MD_type(m)); - /* Skip shortnames */ - if (strcmp(from, mname)) - return; - /* Skip clones */ - if (EVP_MD_flags(m) & EVP_MD_FLAG_PKEY_DIGEST) - return; - if (strchr(mname, ' ')) - mname = EVP_MD_name(m); - BIO_printf(arg, "-%-14s to use the %s message digest algorithm\n", - mname, mname); -} +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY, + OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL, + OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT, + OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, + OPT_DIGEST, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS dgst_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"}, + {OPT_HELP_STR, 1, '-', + " file... files to digest (default is stdin)\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"c", OPT_C, '-', "Print the digest with separating colons"}, + {"r", OPT_R, '-', "Print the digest in coreutils format"}, + {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"sign", OPT_SIGN, 's', "Sign digest using private key"}, + {"verify", OPT_VERIFY, 's', + "Verify a signature using public key"}, + {"prverify", OPT_PRVERIFY, 's', + "Verify a signature using private key"}, + {"signature", OPT_SIGNATURE, '<', "File with signature to verify"}, + {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"}, + {"hex", OPT_HEX, '-', "Print as hex dump"}, + {"binary", OPT_BINARY, '-', "Print in binary form"}, + {"d", OPT_DEBUG, '-', "Print debug info"}, + {"debug", OPT_DEBUG, '-', "Print debug info"}, + {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-', + "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"}, + {"hmac", OPT_HMAC, 's', "Create hashed MAC with key"}, + {"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"}, + {"", OPT_DIGEST, '-', "Any supported digest"}, + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, + {"engine_impl", OPT_ENGINE_IMPL, '-', + "Also use engine given by -engine for digest operations"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int dgst_main(int argc, char **argv) { + BIO *in = NULL, *inp, *bmd = NULL, *out = NULL; ENGINE *e = NULL, *impl = NULL; - unsigned char *buf = NULL; - int i, err = 1; - const EVP_MD *md = NULL, *m; - BIO *in = NULL, *inp; - BIO *bmd = NULL; - BIO *out = NULL; -#define PROG_NAME_SIZE 39 - char pname[PROG_NAME_SIZE + 1]; - int separator = 0; - int debug = 0; - int keyform = FORMAT_PEM; - const char *outfile = NULL, *keyfile = NULL; - const char *sigfile = NULL, *randfile = NULL; - int out_bin = -1, want_pub = 0, do_verify = 0; EVP_PKEY *sigkey = NULL; - unsigned char *sigbuf = NULL; - int siglen = 0; - char *passargin = NULL, *passin = NULL; -#ifndef OPENSSL_NO_ENGINE - char *engine = NULL; - int engine_impl = 0; -#endif + STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; char *hmac_key = NULL; char *mac_name = NULL; - int non_fips_allow = 0; - STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; - - apps_startup(); - - if ((buf = (unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL) { - BIO_printf(bio_err, "out of memory\n"); - goto end; - } - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - /* first check the program name */ - program_name(argv[0], pname, sizeof(pname)); + char *passinarg = NULL, *passin = NULL; + const EVP_MD *md = NULL, *m; + const char *outfile = NULL, *keyfile = NULL, *prog = NULL; + const char *sigfile = NULL; + OPTION_CHOICE o; + int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0; + int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0; + unsigned char *buf = NULL, *sigbuf = NULL; + int engine_impl = 0; - md = EVP_get_digestbyname(pname); + prog = opt_progname(argv[0]); + buf = app_malloc(BUFSIZE, "I/O buffer"); + md = EVP_get_digestbyname(prog); - argc--; - argv++; - while (argc > 0) { - if ((*argv)[0] != '-') - break; - if (strcmp(*argv, "-c") == 0) + prog = opt_init(argc, argv, dgst_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dgst_options); + ret = 0; + goto end; + case OPT_C: separator = 1; - else if (strcmp(*argv, "-r") == 0) + break; + case OPT_R: separator = 2; - else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - break; - randfile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - break; - outfile = *(++argv); - } else if (strcmp(*argv, "-sign") == 0) { - if (--argc < 1) - break; - keyfile = *(++argv); - } else if (!strcmp(*argv, "-passin")) { - if (--argc < 1) - break; - passargin = *++argv; - } else if (strcmp(*argv, "-verify") == 0) { - if (--argc < 1) - break; - keyfile = *(++argv); - want_pub = 1; - do_verify = 1; - } else if (strcmp(*argv, "-prverify") == 0) { - if (--argc < 1) - break; - keyfile = *(++argv); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_SIGN: + keyfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_VERIFY: + keyfile = opt_arg(); + want_pub = do_verify = 1; + break; + case OPT_PRVERIFY: + keyfile = opt_arg(); do_verify = 1; - } else if (strcmp(*argv, "-signature") == 0) { - if (--argc < 1) - break; - sigfile = *(++argv); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - break; - keyform = str2fmt(*(++argv)); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - break; - engine = *(++argv); - e = setup_engine(bio_err, engine, 0); - } else if (strcmp(*argv, "-engine_impl") == 0) + break; + case OPT_SIGNATURE: + sigfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_ENGINE_IMPL: engine_impl = 1; -#endif - else if (strcmp(*argv, "-hex") == 0) + break; + case OPT_HEX: out_bin = 0; - else if (strcmp(*argv, "-binary") == 0) + break; + case OPT_BINARY: out_bin = 1; - else if (strcmp(*argv, "-d") == 0) + break; + case OPT_DEBUG: debug = 1; - else if (!strcmp(*argv, "-fips-fingerprint")) + break; + case OPT_FIPS_FINGERPRINT: hmac_key = "etaonrishdlcupfm"; - else if (strcmp(*argv, "-non-fips-allow") == 0) - non_fips_allow = 1; - else if (!strcmp(*argv, "-hmac")) { - if (--argc < 1) - break; - hmac_key = *++argv; - } else if (!strcmp(*argv, "-mac")) { - if (--argc < 1) - break; - mac_name = *++argv; - } else if (strcmp(*argv, "-sigopt") == 0) { - if (--argc < 1) - break; + break; + case OPT_HMAC: + hmac_key = opt_arg(); + break; + case OPT_MAC: + mac_name = opt_arg(); + break; + case OPT_SIGOPT: if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); - if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) - break; - } else if (strcmp(*argv, "-macopt") == 0) { - if (--argc < 1) - break; + if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto opthelp; + break; + case OPT_MACOPT: if (!macopts) macopts = sk_OPENSSL_STRING_new_null(); - if (!macopts || !sk_OPENSSL_STRING_push(macopts, *(++argv))) - break; - } else if ((m = EVP_get_digestbyname(&((*argv)[1]))) != NULL) + if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg())) + goto opthelp; + break; + case OPT_DIGEST: + if (!opt_md(opt_unknown(), &m)) + goto opthelp; md = m; - else break; - argc--; - argv++; + } } - + argc = opt_num_rest(); + argv = opt_rest(); if (keyfile != NULL && argc > 1) { - BIO_printf(bio_err, "Can only sign or verify one file\n"); + BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog); goto end; } - if (do_verify && !sigfile) { + if (do_verify && sigfile == NULL) { BIO_printf(bio_err, "No signature to verify: use the -signature option\n"); goto end; } - - if ((argc > 0) && (argv[0][0] == '-')) { /* bad option */ - BIO_printf(bio_err, "unknown option '%s'\n", *argv); - BIO_printf(bio_err, "options are\n"); - BIO_printf(bio_err, - "-c to output the digest with separating colons\n"); - BIO_printf(bio_err, - "-r to output the digest in coreutils format\n"); - BIO_printf(bio_err, "-d to output debug info\n"); - BIO_printf(bio_err, "-hex output as hex dump\n"); - BIO_printf(bio_err, "-binary output in binary form\n"); - BIO_printf(bio_err, "-hmac arg set the HMAC key to arg\n"); - BIO_printf(bio_err, "-non-fips-allow allow use of non FIPS digest\n"); - BIO_printf(bio_err, - "-sign file sign digest using private key in file\n"); - BIO_printf(bio_err, - "-verify file verify a signature using public key in file\n"); - BIO_printf(bio_err, - "-prverify file verify a signature using private key in file\n"); - BIO_printf(bio_err, - "-keyform arg key file format (PEM or ENGINE)\n"); - BIO_printf(bio_err, - "-out filename output to filename rather than stdout\n"); - BIO_printf(bio_err, "-signature file signature to verify\n"); - BIO_printf(bio_err, "-sigopt nm:v signature parameter\n"); - BIO_printf(bio_err, "-hmac key create hashed MAC with key\n"); - BIO_printf(bio_err, - "-mac algorithm create MAC (not neccessarily HMAC)\n"); - BIO_printf(bio_err, - "-macopt nm:v MAC algorithm parameters or key\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); -#endif - - EVP_MD_do_all_sorted(list_md_fn, bio_err); - goto end; - } -#ifndef OPENSSL_NO_ENGINE if (engine_impl) impl = e; -#endif in = BIO_new(BIO_s_file()); bmd = BIO_new(BIO_f_md()); @@ -309,68 +213,57 @@ int MAIN(int argc, char **argv) BIO_set_callback_arg(in, (char *)bio_err); } - if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (out_bin == -1) { - if (keyfile) + if (keyfile != NULL) out_bin = 1; else out_bin = 0; } - if (randfile) - app_RAND_load_file(randfile, bio_err, 0); - - if (outfile) { - if (out_bin) - out = BIO_new_file(outfile, "wb"); - else - out = BIO_new_file(outfile, "w"); - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } - - if (!out) { - BIO_printf(bio_err, "Error opening output file %s\n", - outfile ? outfile : "(stdout)"); - ERR_print_errors(bio_err); + out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); + if (out == NULL) goto end; - } - if ((! !mac_name + ! !keyfile + ! !hmac_key) > 1) { + + if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) { BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n"); goto end; } - if (keyfile) { + if (keyfile != NULL) { + int type; + if (want_pub) - sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, - e, "key file"); + sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file"); else - sigkey = load_key(bio_err, keyfile, keyform, 0, passin, - e, "key file"); - if (!sigkey) { + sigkey = load_key(keyfile, keyform, 0, passin, e, "key file"); + if (sigkey == NULL) { /* * load_[pub]key() has already printed an appropriate message */ goto end; } + type = EVP_PKEY_id(sigkey); + if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) { + /* + * We implement PureEdDSA for these which doesn't have a separate + * digest, and only supports one shot. + */ + BIO_printf(bio_err, "Key type not supported for this operation\n"); + goto end; + } } - if (mac_name) { + if (mac_name != NULL) { EVP_PKEY_CTX *mac_ctx = NULL; int r = 0; - if (!init_gen_str(bio_err, &mac_ctx, mac_name, impl, 0)) + if (!init_gen_str(&mac_ctx, mac_name, impl, 0)) goto mac_end; - if (macopts) { + if (macopts != NULL) { char *macopt; for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) { macopt = sk_OPENSSL_STRING_value(macopts, i); @@ -389,26 +282,19 @@ int MAIN(int argc, char **argv) } r = 1; mac_end: - if (mac_ctx) - EVP_PKEY_CTX_free(mac_ctx); + EVP_PKEY_CTX_free(mac_ctx); if (r == 0) goto end; } - if (non_fips_allow) { - EVP_MD_CTX *md_ctx; - BIO_get_md_ctx(bmd, &md_ctx); - EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - } - - if (hmac_key) { - sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, impl, - (unsigned char *)hmac_key, -1); - if (!sigkey) + if (hmac_key != NULL) { + sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl, + (unsigned char *)hmac_key, -1); + if (sigkey == NULL) goto end; } - if (sigkey) { + if (sigkey != NULL) { EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; int r; @@ -426,7 +312,7 @@ int MAIN(int argc, char **argv) ERR_print_errors(bio_err); goto end; } - if (sigopts) { + if (sigopts != NULL) { char *sigopt; for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { sigopt = sk_OPENSSL_STRING_value(sigopts, i); @@ -447,29 +333,23 @@ int MAIN(int argc, char **argv) goto end; } if (md == NULL) - md = EVP_md5(); + md = EVP_sha256(); if (!EVP_DigestInit_ex(mctx, md, impl)) { - BIO_printf(bio_err, "Error setting digest %s\n", pname); + BIO_printf(bio_err, "Error setting digest\n"); ERR_print_errors(bio_err); goto end; } } - if (sigfile && sigkey) { - BIO *sigbio; - sigbio = BIO_new_file(sigfile, "rb"); - siglen = EVP_PKEY_size(sigkey); - sigbuf = OPENSSL_malloc(siglen); - if (!sigbio) { + if (sigfile != NULL && sigkey != NULL) { + BIO *sigbio = BIO_new_file(sigfile, "rb"); + if (sigbio == NULL) { BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); ERR_print_errors(bio_err); goto end; } - if (!sigbuf) { - BIO_printf(bio_err, "Out of memory\n"); - ERR_print_errors(bio_err); - goto end; - } + siglen = EVP_PKEY_size(sigkey); + sigbuf = app_malloc(siglen, "signature buffer"); siglen = BIO_read(sigbio, sigbuf, siglen); BIO_free(sigbio); if (siglen <= 0) { @@ -488,64 +368,55 @@ int MAIN(int argc, char **argv) if (argc == 0) { BIO_set_fp(in, stdin, BIO_NOCLOSE); - err = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, - siglen, NULL, NULL, "stdin", bmd); + ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, + siglen, NULL, NULL, "stdin"); } else { const char *md_name = NULL, *sig_name = NULL; if (!out_bin) { - if (sigkey) { + if (sigkey != NULL) { const EVP_PKEY_ASN1_METHOD *ameth; ameth = EVP_PKEY_get0_asn1(sigkey); if (ameth) EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &sig_name, ameth); } - if (md) + if (md != NULL) md_name = EVP_MD_name(md); } - err = 0; + ret = 0; for (i = 0; i < argc; i++) { int r; if (BIO_read_filename(in, argv[i]) <= 0) { perror(argv[i]); - err++; + ret++; continue; - } else + } else { r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, - siglen, sig_name, md_name, argv[i], bmd); + siglen, sig_name, md_name, argv[i]); + } if (r) - err = r; + ret = r; (void)BIO_reset(bmd); } } end: - if (buf != NULL) { - OPENSSL_cleanse(buf, BUFSIZE); - OPENSSL_free(buf); - } - if (in != NULL) - BIO_free(in); - if (passin) - OPENSSL_free(passin); + OPENSSL_clear_free(buf, BUFSIZE); + BIO_free(in); + OPENSSL_free(passin); BIO_free_all(out); EVP_PKEY_free(sigkey); - if (sigopts) - sk_OPENSSL_STRING_free(sigopts); - if (macopts) - sk_OPENSSL_STRING_free(macopts); - if (sigbuf) - OPENSSL_free(sigbuf); - if (bmd != NULL) - BIO_free(bmd); + sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(macopts); + OPENSSL_free(sigbuf); + BIO_free(bmd); release_engine(e); - apps_shutdown(); - OPENSSL_EXIT(err); + return ret; } int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *sig_name, const char *md_name, - const char *file, BIO *bmd) + const char *file) { size_t len; int i; @@ -560,13 +431,13 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, if (i == 0) break; } - if (sigin) { + if (sigin != NULL) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen); - if (i > 0) + if (i > 0) { BIO_printf(out, "Verified OK\n"); - else if (i == 0) { + } else if (i == 0) { BIO_printf(out, "Verification Failure\n"); return 1; } else { @@ -576,7 +447,7 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, } return 0; } - if (key) { + if (key != NULL) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); len = BUFSIZE; @@ -593,22 +464,23 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, } } - if (binout) + if (binout) { BIO_write(out, buf, len); - else if (sep == 2) { + } else if (sep == 2) { for (i = 0; i < (int)len; i++) BIO_printf(out, "%02x", buf[i]); BIO_printf(out, " *%s\n", file); } else { - if (sig_name) { + if (sig_name != NULL) { BIO_puts(out, sig_name); - if (md_name) + if (md_name != NULL) BIO_printf(out, "-%s", md_name); BIO_printf(out, "(%s)= ", file); - } else if (md_name) + } else if (md_name != NULL) { BIO_printf(out, "%s(%s)= ", md_name, file); - else + } else { BIO_printf(out, "(%s)= ", file); + } for (i = 0; i < (int)len; i++) { if (sep && (i != 0)) BIO_printf(out, ":"); diff --git a/apps/dh.c b/apps/dh.c deleted file mode 100644 index bb13fef16e43..000000000000 --- a/apps/dh.c +++ /dev/null @@ -1,331 +0,0 @@ -/* apps/dh.c */ -/* obsoleted by dhparam.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include <openssl/opensslconf.h> /* for OPENSSL_NO_DH */ -#ifndef OPENSSL_NO_DH -# include <stdio.h> -# include <stdlib.h> -# include <time.h> -# include <string.h> -# include "apps.h" -# include <openssl/bio.h> -# include <openssl/err.h> -# include <openssl/bn.h> -# include <openssl/dh.h> -# include <openssl/x509.h> -# include <openssl/pem.h> - -# undef PROG -# define PROG dh_main - -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -check - check the parameters are ok - * -noout - * -text - * -C - */ - -int MAIN(int, char **); - -int MAIN(int argc, char **argv) -{ - DH *dh = NULL; - int i, badops = 0, text = 0; - BIO *in = NULL, *out = NULL; - int informat, outformat, check = 0, noout = 0, C = 0, ret = 1; - char *infile, *outfile, *prog; - char *engine; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - engine = NULL; - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -# endif - else if (strcmp(*argv, "-check") == 0) - check = 1; - else if (strcmp(*argv, "-text") == 0) - text = 1; - else if (strcmp(*argv, "-C") == 0) - C = 1; - else if (strcmp(*argv, "-noout") == 0) - noout = 1; - else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; - break; - } - argc--; - argv++; - } - - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - one of DER PEM\n"); - BIO_printf(bio_err, - " -outform arg output format - one of DER PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, " -check check the DH parameters\n"); - BIO_printf(bio_err, - " -text print a text form of the DH parameters\n"); - BIO_printf(bio_err, " -C Output C code\n"); - BIO_printf(bio_err, " -noout no output\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -# endif - goto end; - } - - ERR_load_crypto_strings(); - - setup_engine(bio_err, engine, 0); - - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); - goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } - - if (informat == FORMAT_ASN1) - dh = d2i_DHparams_bio(in, NULL); - else if (informat == FORMAT_PEM) - dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); - else { - BIO_printf(bio_err, "bad input format specified\n"); - goto end; - } - if (dh == NULL) { - BIO_printf(bio_err, "unable to load DH parameters\n"); - ERR_print_errors(bio_err); - goto end; - } - - if (text) { - DHparams_print(out, dh); -# ifdef undef - printf("p="); - BN_print(stdout, dh->p); - printf("\ng="); - BN_print(stdout, dh->g); - printf("\n"); - if (dh->length != 0) - printf("recommended private length=%ld\n", dh->length); -# endif - } - - if (check) { - if (!DH_check(dh, &i)) { - ERR_print_errors(bio_err); - goto end; - } - if (i & DH_CHECK_P_NOT_PRIME) - printf("p value is not prime\n"); - if (i & DH_CHECK_P_NOT_SAFE_PRIME) - printf("p value is not a safe prime\n"); - if (i & DH_UNABLE_TO_CHECK_GENERATOR) - printf("unable to check the generator value\n"); - if (i & DH_NOT_SUITABLE_GENERATOR) - printf("the g value is not a generator\n"); - if (i == 0) - printf("DH parameters appear to be ok.\n"); - } - if (C) { - unsigned char *data; - int len, l, bits; - - len = BN_num_bytes(dh->p); - bits = BN_num_bits(dh->p); - data = (unsigned char *)OPENSSL_malloc(len); - if (data == NULL) { - perror("OPENSSL_malloc"); - goto end; - } - l = BN_bn2bin(dh->p, data); - printf("static unsigned char dh%d_p[]={", bits); - for (i = 0; i < l; i++) { - if ((i % 12) == 0) - printf("\n\t"); - printf("0x%02X,", data[i]); - } - printf("\n\t};\n"); - - l = BN_bn2bin(dh->g, data); - printf("static unsigned char dh%d_g[]={", bits); - for (i = 0; i < l; i++) { - if ((i % 12) == 0) - printf("\n\t"); - printf("0x%02X,", data[i]); - } - printf("\n\t};\n\n"); - - printf("DH *get_dh%d()\n\t{\n", bits); - printf("\tDH *dh;\n\n"); - printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n"); - printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n", - bits, bits); - printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n", - bits, bits); - printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n"); - printf("\t\treturn(NULL);\n"); - printf("\treturn(dh);\n\t}\n"); - OPENSSL_free(data); - } - - if (!noout) { - if (outformat == FORMAT_ASN1) - i = i2d_DHparams_bio(out, dh); - else if (outformat == FORMAT_PEM) - i = PEM_write_bio_DHparams(out, dh); - else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; - } - if (!i) { - BIO_printf(bio_err, "unable to write DH parameters\n"); - ERR_print_errors(bio_err); - goto end; - } - } - ret = 0; - end: - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (dh != NULL) - DH_free(dh); - apps_shutdown(); - OPENSSL_EXIT(ret); -} -#else /* !OPENSSL_NO_DH */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - -#endif diff --git a/apps/dh1024.pem b/apps/dh1024.pem index 6eaeca9b8eb1..f1a5e180aa95 100644 --- a/apps/dh1024.pem +++ b/apps/dh1024.pem @@ -1,10 +1,10 @@ -----BEGIN DH PARAMETERS----- -MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY -jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6 -ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC +MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR +Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL +/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC -----END DH PARAMETERS----- -These are the 1024 bit DH parameters from "Assigned Number for SKIP Protocols" -(http://www.skip-vpn.org/spec/numbers.html). -See there for how they were generated. -Note that g is not a generator, but this is not a problem since p is a safe prime. +These are the 1024-bit DH parameters from "Internet Key Exchange +Protocol Version 2 (IKEv2)": https://tools.ietf.org/html/rfc5996 + +See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dh2048.pem b/apps/dh2048.pem index dcd0b8d01b89..e899f2e0296d 100644 --- a/apps/dh2048.pem +++ b/apps/dh2048.pem @@ -1,12 +1,14 @@ -----BEGIN DH PARAMETERS----- -MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV -89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50 -T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb -zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX -Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT -CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg== +MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb +IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft +awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT +mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh +fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq +5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg== -----END DH PARAMETERS----- -These are the 2048 bit DH parameters from "Assigned Number for SKIP Protocols" -(http://www.skip-vpn.org/spec/numbers.html). -See there for how they were generated. +These are the 2048-bit DH parameters from "More Modular Exponential +(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": +https://tools.ietf.org/html/rfc3526 + +See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dh4096.pem b/apps/dh4096.pem index 1b35ad8e62eb..adada2b55815 100644 --- a/apps/dh4096.pem +++ b/apps/dh4096.pem @@ -1,18 +1,19 @@ -----BEGIN DH PARAMETERS----- -MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ -l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt -Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS -Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98 -VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc -alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM -sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9 -ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte -OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH -AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL -KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI= +MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb +IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft +awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT +mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh +fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq +5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM +fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq +ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI +ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O ++S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI +HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI= -----END DH PARAMETERS----- -These are the 4096 bit DH parameters from "Assigned Number for SKIP Protocols" -(http://www.skip-vpn.org/spec/numbers.html). -See there for how they were generated. -Note that g is not a generator, but this is not a problem since p is a safe prime. +These are the 4096-bit DH parameters from "More Modular Exponential +(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": +https://tools.ietf.org/html/rfc3526 + +See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dh512.pem b/apps/dh512.pem deleted file mode 100644 index 200d16cd8971..000000000000 --- a/apps/dh512.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN DH PARAMETERS----- -MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak -XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC ------END DH PARAMETERS----- - -These are the 512 bit DH parameters from "Assigned Number for SKIP Protocols" -(http://www.skip-vpn.org/spec/numbers.html). -See there for how they were generated. -Note that g is not a generator, but this is not a problem since p is a safe prime. diff --git a/apps/dhparam.c b/apps/dhparam.c index bd91234abd66..13f76754d27c 100644 --- a/apps/dhparam.c +++ b/apps/dhparam.c @@ -1,121 +1,23 @@ -/* apps/dhparam.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <openssl/opensslconf.h> /* for OPENSSL_NO_DH */ -#ifndef OPENSSL_NO_DH +#include <openssl/opensslconf.h> +#ifdef OPENSSL_NO_DH +NON_EMPTY_TRANSLATION_UNIT +#else + # include <stdio.h> # include <stdlib.h> # include <time.h> # include <string.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/bn.h> @@ -127,179 +29,149 @@ # include <openssl/dsa.h> # endif -# undef PROG -# define PROG dhparam_main - # define DEFBITS 2048 -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -dsaparam - read or generate DSA parameters, convert to DH - * -check - check the parameters are ok - * -noout - * -text - * -C - */ - -static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb); +static int dh_cb(int p, int n, BN_GENCB *cb); -int MAIN(int, char **); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, + OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT, + OPT_DSAPARAM, OPT_C, OPT_2, OPT_5, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int argc, char **argv) -{ - DH *dh = NULL; - int i, badops = 0, text = 0; +const OPTIONS dhparam_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [flags] [numbits]\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"}, + {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"check", OPT_CHECK, '-', "Check the DH parameters"}, + {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"}, + {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"}, + OPT_R_OPTIONS, + {"C", OPT_C, '-', "Print C code"}, + {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"}, + {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"}, # ifndef OPENSSL_NO_DSA - int dsaparam = 0; + {"dsaparam", OPT_DSAPARAM, '-', + "Read or generate DSA parameters, convert to DH"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, # endif + {NULL} +}; + +int dhparam_main(int argc, char **argv) +{ BIO *in = NULL, *out = NULL; - int informat, outformat, check = 0, noout = 0, C = 0, ret = 1; - char *infile, *outfile, *prog; - char *inrand = NULL; - char *engine = NULL; + DH *dh = NULL; + char *infile = NULL, *outfile = NULL, *prog; ENGINE *e = NULL; - int num = 0, g = 0; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; +#ifndef OPENSSL_NO_DSA + int dsaparam = 0; +#endif + int i, text = 0, C = 0, ret = 1, num = 0, g = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0; + OPTION_CHOICE o; - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -# endif - else if (strcmp(*argv, "-check") == 0) + prog = opt_init(argc, argv, dhparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dhparam_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_CHECK: check = 1; - else if (strcmp(*argv, "-text") == 0) + break; + case OPT_TEXT: text = 1; -# ifndef OPENSSL_NO_DSA - else if (strcmp(*argv, "-dsaparam") == 0) + break; + case OPT_DSAPARAM: +#ifndef OPENSSL_NO_DSA dsaparam = 1; -# endif - else if (strcmp(*argv, "-C") == 0) +#endif + break; + case OPT_C: C = 1; - else if (strcmp(*argv, "-noout") == 0) - noout = 1; - else if (strcmp(*argv, "-2") == 0) + break; + case OPT_2: g = 2; - else if (strcmp(*argv, "-5") == 0) + break; + case OPT_5: g = 5; - else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - } else if (((sscanf(*argv, "%d", &num) == 0) || (num <= 0))) - goto bad; - argv++; - argc--; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + } } + argc = opt_num_rest(); + argv = opt_rest(); - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] [numbits]\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - one of DER PEM\n"); - BIO_printf(bio_err, - " -outform arg output format - one of DER PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -out arg output file\n"); -# ifndef OPENSSL_NO_DSA - BIO_printf(bio_err, - " -dsaparam read or generate DSA parameters, convert to DH\n"); -# endif - BIO_printf(bio_err, " -check check the DH parameters\n"); - BIO_printf(bio_err, - " -text print a text form of the DH parameters\n"); - BIO_printf(bio_err, " -C Output C code\n"); - BIO_printf(bio_err, - " -2 generate parameters using 2 as the generator value\n"); - BIO_printf(bio_err, - " -5 generate parameters using 5 as the generator value\n"); - BIO_printf(bio_err, - " numbits number of bits in to generate (default 2048)\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " - load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - BIO_printf(bio_err, " -noout no output\n"); + if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0)) goto end; - } - - ERR_load_crypto_strings(); - - e = setup_engine(bio_err, engine, 0); if (g && !num) num = DEFBITS; # ifndef OPENSSL_NO_DSA - if (dsaparam) { - if (g) { - BIO_printf(bio_err, - "generator may not be chosen for DSA parameters\n"); - goto end; - } - } else -# endif - { - /* DH parameters */ - if (num && !g) - g = 2; + if (dsaparam && g) { + BIO_printf(bio_err, + "generator may not be chosen for DSA parameters\n"); + goto end; } +# endif + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + /* DH parameters */ + if (num && !g) + g = 2; if (num) { - BN_GENCB cb; - BN_GENCB_set(&cb, dh_cb, bio_err); - if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) { - BIO_printf(bio_err, - "warning, not much extra random data, consider using the -rand option\n"); + BN_GENCB *cb; + cb = BN_GENCB_new(); + if (cb == NULL) { + ERR_print_errors(bio_err); + goto end; } - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); + + BN_GENCB_set(cb, dh_cb, bio_err); # ifndef OPENSSL_NO_DSA if (dsaparam) { @@ -307,11 +179,11 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num); - if (!dsa + if (dsa == NULL || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, - &cb)) { - if (dsa) - DSA_free(dsa); + cb)) { + DSA_free(dsa); + BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } @@ -319,6 +191,7 @@ int MAIN(int argc, char **argv) dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { + BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } @@ -330,33 +203,20 @@ int MAIN(int argc, char **argv) "Generating DH parameters, %d bit long safe prime, generator %d\n", num, g); BIO_printf(bio_err, "This is going to take a long time\n"); - if (!dh || !DH_generate_parameters_ex(dh, num, g, &cb)) { + if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) { + BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } } - app_RAND_write_file(NULL, bio_err); + BN_GENCB_free(cb); } else { - in = BIO_new(BIO_s_file()); - if (in == NULL) { - ERR_print_errors(bio_err); + in = bio_open_default(infile, 'r', informat); + if (in == NULL) goto end; - } - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } - if (informat != FORMAT_ASN1 && informat != FORMAT_PEM) { - BIO_printf(bio_err, "bad input format specified\n"); - goto end; - } # ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa; @@ -405,26 +265,6 @@ int MAIN(int argc, char **argv) /* dh != NULL */ } - out = BIO_new(BIO_s_file()); - if (out == NULL) { - ERR_print_errors(bio_err); - goto end; - } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } - if (text) { DHparams_print(out, dh); } @@ -435,77 +275,82 @@ int MAIN(int argc, char **argv) goto end; } if (i & DH_CHECK_P_NOT_PRIME) - printf("p value is not prime\n"); + BIO_printf(bio_err, "WARNING: p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) - printf("p value is not a safe prime\n"); + BIO_printf(bio_err, "WARNING: p value is not a safe prime\n"); + if (i & DH_CHECK_Q_NOT_PRIME) + BIO_printf(bio_err, "WARNING: q value is not a prime\n"); + if (i & DH_CHECK_INVALID_Q_VALUE) + BIO_printf(bio_err, "WARNING: q value is invalid\n"); + if (i & DH_CHECK_INVALID_J_VALUE) + BIO_printf(bio_err, "WARNING: j value is invalid\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) - printf("unable to check the generator value\n"); + BIO_printf(bio_err, + "WARNING: unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) - printf("the g value is not a generator\n"); + BIO_printf(bio_err, "WARNING: the g value is not a generator\n"); if (i == 0) - printf("DH parameters appear to be ok.\n"); + BIO_printf(bio_err, "DH parameters appear to be ok.\n"); + if (num != 0 && i != 0) { + /* + * We have generated parameters but DH_check() indicates they are + * invalid! This should never happen! + */ + BIO_printf(bio_err, "ERROR: Invalid parameters generated\n"); + goto end; + } } if (C) { unsigned char *data; - int len, l, bits; + int len, bits; + const BIGNUM *pbn, *gbn; - len = BN_num_bytes(dh->p); - bits = BN_num_bits(dh->p); - data = (unsigned char *)OPENSSL_malloc(len); - if (data == NULL) { - perror("OPENSSL_malloc"); - goto end; - } - printf("#ifndef HEADER_DH_H\n" - "#include <openssl/dh.h>\n" "#endif\n"); - printf("DH *get_dh%d()\n\t{\n", bits); - - l = BN_bn2bin(dh->p, data); - printf("\tstatic unsigned char dh%d_p[]={", bits); - for (i = 0; i < l; i++) { - if ((i % 12) == 0) - printf("\n\t\t"); - printf("0x%02X,", data[i]); - } - printf("\n\t\t};\n"); + len = DH_size(dh); + bits = DH_bits(dh); + DH_get0_pqg(dh, &pbn, NULL, &gbn); + data = app_malloc(len, "print a BN"); - l = BN_bn2bin(dh->g, data); - printf("\tstatic unsigned char dh%d_g[]={", bits); - for (i = 0; i < l; i++) { - if ((i % 12) == 0) - printf("\n\t\t"); - printf("0x%02X,", data[i]); - } - printf("\n\t\t};\n"); - - printf("\tDH *dh;\n\n"); - printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n"); - printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n", - bits, bits); - printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n", - bits, bits); - printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n"); - printf("\t\t{ DH_free(dh); return(NULL); }\n"); - if (dh->length) - printf("\tdh->length = %ld;\n", dh->length); - printf("\treturn(dh);\n\t}\n"); + BIO_printf(out, "static DH *get_dh%d(void)\n{\n", bits); + print_bignum_var(out, pbn, "dhp", bits, data); + print_bignum_var(out, gbn, "dhg", bits, data); + BIO_printf(out, " DH *dh = DH_new();\n" + " BIGNUM *p, *g;\n" + "\n" + " if (dh == NULL)\n" + " return NULL;\n"); + BIO_printf(out, " p = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n", + bits, bits); + BIO_printf(out, " g = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n", + bits, bits); + BIO_printf(out, " if (p == NULL || g == NULL\n" + " || !DH_set0_pqg(dh, p, NULL, g)) {\n" + " DH_free(dh);\n" + " BN_free(p);\n" + " BN_free(g);\n" + " return NULL;\n" + " }\n"); + if (DH_get_length(dh) > 0) + BIO_printf(out, + " if (!DH_set_length(dh, %ld)) {\n" + " DH_free(dh);\n" + " return NULL;\n" + " }\n", DH_get_length(dh)); + BIO_printf(out, " return dh;\n}\n"); OPENSSL_free(data); } if (!noout) { + const BIGNUM *q; + DH_get0_pqg(dh, NULL, &q, NULL); if (outformat == FORMAT_ASN1) { - if (dh->q != NULL) + if (q != NULL) i = i2d_DHxparams_bio(out, dh); else i = i2d_DHparams_bio(out, dh); - } else if (outformat == FORMAT_PEM) { - if (dh->q != NULL) - i = PEM_write_bio_DHxparams(out, dh); - else - i = PEM_write_bio_DHparams(out, dh); + } else if (q != NULL) { + i = PEM_write_bio_DHxparams(out, dh); } else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; + i = PEM_write_bio_DHparams(out, dh); } if (!i) { BIO_printf(bio_err, "unable to write DH parameters\n"); @@ -515,42 +360,20 @@ int MAIN(int argc, char **argv) } ret = 0; end: - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (dh != NULL) - DH_free(dh); + BIO_free(in); + BIO_free_all(out); + DH_free(dh); release_engine(e); - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } -/* dh_cb is identical to dsa_cb in apps/dsaparam.c */ -static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb) +static int dh_cb(int p, int n, BN_GENCB *cb) { - char c = '*'; + static const char symbols[] = ".+*\n"; + char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; - if (p == 0) - c = '.'; - if (p == 1) - c = '+'; - if (p == 2) - c = '*'; - if (p == 3) - c = '\n'; - BIO_write(cb->arg, &c, 1); - (void)BIO_flush(cb->arg); -# ifdef LINT - p = n; -# endif + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void)BIO_flush(BN_GENCB_get_arg(cb)); return 1; } - -#else /* !OPENSSL_NO_DH */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/dsa-ca.pem b/apps/dsa-ca.pem index cccc14208fc1..3ce8dc60538e 100644 --- a/apps/dsa-ca.pem +++ b/apps/dsa-ca.pem @@ -11,30 +11,37 @@ tOFDITEAl+YZZariXOD7tdOSOl9RLMPC6+daHKS9e68u3enxhqnDGQIUB78dhW77 J6zsFbSEHaQGUmfSeoM= -----END DSA PRIVATE KEY----- -----BEGIN CERTIFICATE REQUEST----- -MIICUjCCAhECAQAwUjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx -ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UEAxMCQ0Ew -ggG0MIIBKQYFKw4DAgwwggEeAoGBAKc/boW/QWopffCfRxkwkJoJHdpqMx7FPYaW -sxXgUy6P4FmCc5A+dTGZR3pS+4Xk2aZ7OJtoioSbh8YetX6GS1NbWc9xZRmIbs5m -rmuINvvsKNzC16W75Sw5JkvamnAYlTeVEFYj9hXtugRe3jlP/bdDH7WkZW/NgBHk -cJVbUM1JAhUA9wcx7fpsBgPVhYocrJxl51BmZW8CgYBN30wDppGK9RlvUEYlmeVo -bzDjaeHls12YuyiGSPzemQQ/X4gMnHMkDSBduSqaPxiWJ+Rih8F7dGJT/GEnqHqR -CZ228U2cVA9YBu5JdAfOVX4jzhb2ytxaYQF+yXG1TfbcNCmHaPZeIJOz2/XkCWxB -F5WS6wG1c6Vqftgy7Q4CuAOBhAACgYAapll6iqz9XrZFlk2GCVcB+KihxWnH7IuH -vSLw9YUrJahcBHmbpvt494lF4gC5w3WPM+vXJofbusk4GoQEEsQNMDaah4m49uUq -AylOVFJJJXuirVJ+o+0TtOFDITEAl+YZZariXOD7tdOSOl9RLMPC6+daHKS9e68u -3enxhqnDGaAAMAkGBSsOAwIbBQADMAAwLQIVAJGVuFsG/0DBuSZ0jF7ypdU0/G0v -AhQfeF5BoMMDbX/kidUVpQ6gadPlZA== +MIICVjCCAhMCAQAwUjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UEAwwCQ0Ew +ggG2MIIBKwYHKoZIzjgEATCCAR4CgYEApz9uhb9Bail98J9HGTCQmgkd2mozHsU9 +hpazFeBTLo/gWYJzkD51MZlHelL7heTZpns4m2iKhJuHxh61foZLU1tZz3FlGYhu +zmaua4g2++wo3MLXpbvlLDkmS9qacBiVN5UQViP2Fe26BF7eOU/9t0MftaRlb82A +EeRwlVtQzUkCFQD3BzHt+mwGA9WFihysnGXnUGZlbwKBgE3fTAOmkYr1GW9QRiWZ +5WhvMONp4eWzXZi7KIZI/N6ZBD9fiAyccyQNIF25Kpo/GJYn5GKHwXt0YlP8YSeo +epEJnbbxTZxUD1gG7kl0B85VfiPOFvbK3FphAX7JcbVN9tw0KYdo9l4gk7Pb9eQJ +bEEXlZLrAbVzpWp+2DLtDgK4A4GEAAKBgBqmWXqKrP1etkWWTYYJVwH4qKHFacfs +i4e9IvD1hSslqFwEeZum+3j3iUXiALnDdY8z69cmh9u6yTgahAQSxA0wNpqHibj2 +5SoDKU5UUkkle6KtUn6j7RO04UMhMQCX5hllquJc4Pu105I6X1Esw8Lr51ocpL17 +ry7d6fGGqcMZoAAwCwYJYIZIAWUDBAMCAzAAMC0CFCp7rUwGJNtxK6Aqo6k6US+S +KP8sAhUAyfSi8Zs3QAvkJoFG0IMRaq8M03I= -----END CERTIFICATE REQUEST----- -----BEGIN CERTIFICATE----- -MIIBrjCCAWwCAQswCQYFKw4DAhsFADBTMQswCQYDVQQGEwJBVTETMBEGA1UECBMK -U29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQww -CgYDVQQDEwNQQ0EwHhcNOTcwNjE1MDIxNDI5WhcNOTcwNzE1MDIxNDI5WjBSMQsw -CQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu -ZXQgV2lkZ2l0cyBQdHkgTHRkMQswCQYDVQQDEwJDQTCBkjAJBgUrDgMCDAUAA4GE -AAKBgBqmWXqKrP1etkWWTYYJVwH4qKHFacfsi4e9IvD1hSslqFwEeZum+3j3iUXi -ALnDdY8z69cmh9u6yTgahAQSxA0wNpqHibj25SoDKU5UUkkle6KtUn6j7RO04UMh -MQCX5hllquJc4Pu105I6X1Esw8Lr51ocpL17ry7d6fGGqcMZMAkGBSsOAwIbBQAD -MQAwLgIVAJ4wtQsANPxHo7Q4IQZYsL12SKdbAhUAjJ9n38zxT+iai2164xS+LIfa -C1Q= +MIIDMDCCAuygAwIBAgIBAjALBglghkgBZQMEAwIwUzELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 +IEx0ZDEMMAoGA1UEAwwDUENBMCAXDTE2MDExMzIxNDE0OVoYDzMwMTUwNTE2MjE0 +MTQ5WjBSMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE +CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQswCQYDVQQDDAJDQTCCAbYwggEr +BgcqhkjOOAQBMIIBHgKBgQCnP26Fv0FqKX3wn0cZMJCaCR3aajMexT2GlrMV4FMu +j+BZgnOQPnUxmUd6UvuF5NmmezibaIqEm4fGHrV+hktTW1nPcWUZiG7OZq5riDb7 +7Cjcwtelu+UsOSZL2ppwGJU3lRBWI/YV7boEXt45T/23Qx+1pGVvzYAR5HCVW1DN +SQIVAPcHMe36bAYD1YWKHKycZedQZmVvAoGATd9MA6aRivUZb1BGJZnlaG8w42nh +5bNdmLsohkj83pkEP1+IDJxzJA0gXbkqmj8YlifkYofBe3RiU/xhJ6h6kQmdtvFN +nFQPWAbuSXQHzlV+I84W9srcWmEBfslxtU323DQph2j2XiCTs9v15AlsQReVkusB +tXOlan7YMu0OArgDgYQAAoGAGqZZeoqs/V62RZZNhglXAfioocVpx+yLh70i8PWF +KyWoXAR5m6b7ePeJReIAucN1jzPr1yaH27rJOBqEBBLEDTA2moeJuPblKgMpTlRS +SSV7oq1SfqPtE7ThQyExAJfmGWWq4lzg+7XTkjpfUSzDwuvnWhykvXuvLt3p8Yap +wxmjUDBOMB0GA1UdDgQWBBTMZcORcBEVlqO/CD4pf4V6N1NM1zAfBgNVHSMEGDAW +gBTGjwJ33uvjSa20RNrMKWoGptOLdDAMBgNVHRMEBTADAQH/MAsGCWCGSAFlAwQD +AgMxADAuAhUA4V6MrHufG8R79E+AtVO02olPxK8CFQDkZyo/TWpavsUBRDJbCeD9 +jgjIkA== -----END CERTIFICATE----- - diff --git a/apps/dsa-pca.pem b/apps/dsa-pca.pem index d23774edd618..a51a06ed14aa 100644 --- a/apps/dsa-pca.pem +++ b/apps/dsa-pca.pem @@ -11,36 +11,37 @@ umz6tl+iUcNe5EoxdsYV1IXSddjOi08LOLsZq7AQlNnKvbtlmMDULpqkZJD0bO7A 6TicfImU7UFRn9h00j0lJQ== -----END DSA PRIVATE KEY----- -----BEGIN CERTIFICATE REQUEST----- -MIICVTCCAhMCAQAwUzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx -ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEMMAoGA1UEAxMDUENB -MIIBtTCCASkGBSsOAwIMMIIBHgKBgQCnP26Fv0FqKX3wn0cZMJCaCR3aajMexT2G -lrMV4FMuj+BZgnOQPnUxmUd6UvuF5NmmezibaIqEm4fGHrV+hktTW1nPcWUZiG7O -Zq5riDb77Cjcwtelu+UsOSZL2ppwGJU3lRBWI/YV7boEXt45T/23Qx+1pGVvzYAR -5HCVW1DNSQIVAPcHMe36bAYD1YWKHKycZedQZmVvAoGATd9MA6aRivUZb1BGJZnl -aG8w42nh5bNdmLsohkj83pkEP1+IDJxzJA0gXbkqmj8YlifkYofBe3RiU/xhJ6h6 -kQmdtvFNnFQPWAbuSXQHzlV+I84W9srcWmEBfslxtU323DQph2j2XiCTs9v15Als -QReVkusBtXOlan7YMu0OArgDgYUAAoGBAKbtuR5AdW+ICjCFe2ixjUiJJzM2IKwe -6NZEMXg39+HQ1UTPTmfLZLps+rZfolHDXuRKMXbGFdSF0nXYzotPCzi7GauwEJTZ -yr27ZZjA1C6apGSQ9GzuwNvZ4rCXystVEagAS8OQ4H3D4dWS17Zg31ICb5o4E5r0 -z09o/Uz46u0VoAAwCQYFKw4DAhsFAAMxADAuAhUArRubTxsbIXy3AhtjQ943AbNB -nSICFQCu+g1iW3jwF+gOcbroD4S/ZcvB3w== +MIICWDCCAhUCAQAwUzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEMMAoGA1UEAwwDUENB +MIIBtzCCASsGByqGSM44BAEwggEeAoGBAKc/boW/QWopffCfRxkwkJoJHdpqMx7F +PYaWsxXgUy6P4FmCc5A+dTGZR3pS+4Xk2aZ7OJtoioSbh8YetX6GS1NbWc9xZRmI +bs5mrmuINvvsKNzC16W75Sw5JkvamnAYlTeVEFYj9hXtugRe3jlP/bdDH7WkZW/N +gBHkcJVbUM1JAhUA9wcx7fpsBgPVhYocrJxl51BmZW8CgYBN30wDppGK9RlvUEYl +meVobzDjaeHls12YuyiGSPzemQQ/X4gMnHMkDSBduSqaPxiWJ+Rih8F7dGJT/GEn +qHqRCZ228U2cVA9YBu5JdAfOVX4jzhb2ytxaYQF+yXG1TfbcNCmHaPZeIJOz2/Xk +CWxBF5WS6wG1c6Vqftgy7Q4CuAOBhQACgYEApu25HkB1b4gKMIV7aLGNSIknMzYg +rB7o1kQxeDf34dDVRM9OZ8tkumz6tl+iUcNe5EoxdsYV1IXSddjOi08LOLsZq7AQ +lNnKvbtlmMDULpqkZJD0bO7A29nisJfKy1URqABLw5DgfcPh1ZLXtmDfUgJvmjgT +mvTPT2j9TPjq7RWgADALBglghkgBZQMEAwIDMAAwLQIVAPA6/jxCT1D2HgzE4iZR +AEup/C7YAhRPLTQvQnAiS5FRrA+8SwBLvDAsaw== -----END CERTIFICATE REQUEST----- -----BEGIN CERTIFICATE----- -MIIC0zCCApECAQAwCQYFKw4DAhsFADBTMQswCQYDVQQGEwJBVTETMBEGA1UECBMK -U29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQww -CgYDVQQDEwNQQ0EwHhcNOTcwNjE0MjI1NDQ1WhcNOTcwNzE0MjI1NDQ1WjBTMQsw -CQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu -ZXQgV2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDEwNQQ0EwggG1MIIBKQYFKw4DAgww -ggEeAoGBAKc/boW/QWopffCfRxkwkJoJHdpqMx7FPYaWsxXgUy6P4FmCc5A+dTGZ -R3pS+4Xk2aZ7OJtoioSbh8YetX6GS1NbWc9xZRmIbs5mrmuINvvsKNzC16W75Sw5 -JkvamnAYlTeVEFYj9hXtugRe3jlP/bdDH7WkZW/NgBHkcJVbUM1JAhUA9wcx7fps -BgPVhYocrJxl51BmZW8CgYBN30wDppGK9RlvUEYlmeVobzDjaeHls12YuyiGSPze -mQQ/X4gMnHMkDSBduSqaPxiWJ+Rih8F7dGJT/GEnqHqRCZ228U2cVA9YBu5JdAfO -VX4jzhb2ytxaYQF+yXG1TfbcNCmHaPZeIJOz2/XkCWxBF5WS6wG1c6Vqftgy7Q4C -uAOBhQACgYEApu25HkB1b4gKMIV7aLGNSIknMzYgrB7o1kQxeDf34dDVRM9OZ8tk -umz6tl+iUcNe5EoxdsYV1IXSddjOi08LOLsZq7AQlNnKvbtlmMDULpqkZJD0bO7A -29nisJfKy1URqABLw5DgfcPh1ZLXtmDfUgJvmjgTmvTPT2j9TPjq7RUwCQYFKw4D -AhsFAAMxADAuAhUAvtv6AkMolix1Jvy3UnVEIUqdCUICFQC+jq8P49mwrY9oJ24n -5rKUjNBhSg== +MIIDMDCCAu6gAwIBAgIBATALBglghkgBZQMEAwIwUzELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 +IEx0ZDEMMAoGA1UEAwwDUENBMCAXDTE2MDExMzIxNDE0OVoYDzMwMTUwNTE2MjE0 +MTQ5WjBTMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE +CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDDANQQ0EwggG3MIIB +KwYHKoZIzjgEATCCAR4CgYEApz9uhb9Bail98J9HGTCQmgkd2mozHsU9hpazFeBT +Lo/gWYJzkD51MZlHelL7heTZpns4m2iKhJuHxh61foZLU1tZz3FlGYhuzmaua4g2 +++wo3MLXpbvlLDkmS9qacBiVN5UQViP2Fe26BF7eOU/9t0MftaRlb82AEeRwlVtQ +zUkCFQD3BzHt+mwGA9WFihysnGXnUGZlbwKBgE3fTAOmkYr1GW9QRiWZ5WhvMONp +4eWzXZi7KIZI/N6ZBD9fiAyccyQNIF25Kpo/GJYn5GKHwXt0YlP8YSeoepEJnbbx +TZxUD1gG7kl0B85VfiPOFvbK3FphAX7JcbVN9tw0KYdo9l4gk7Pb9eQJbEEXlZLr +AbVzpWp+2DLtDgK4A4GFAAKBgQCm7bkeQHVviAowhXtosY1IiSczNiCsHujWRDF4 +N/fh0NVEz05ny2S6bPq2X6JRw17kSjF2xhXUhdJ12M6LTws4uxmrsBCU2cq9u2WY +wNQumqRkkPRs7sDb2eKwl8rLVRGoAEvDkOB9w+HVkte2YN9SAm+aOBOa9M9PaP1M ++OrtFaNQME4wHQYDVR0OBBYEFMaPAnfe6+NJrbRE2swpagam04t0MB8GA1UdIwQY +MBaAFMaPAnfe6+NJrbRE2swpagam04t0MAwGA1UdEwQFMAMBAf8wCwYJYIZIAWUD +BAMCAy8AMCwCFFhdz4fzQo9BBF20U1CHldYTi/D7AhQydDnDMj21y+U1UhDZJrvh +lnt88g== -----END CERTIFICATE----- - diff --git a/apps/dsa.c b/apps/dsa.c index 82a870eb2910..6022e64cd4ce 100644 --- a/apps/dsa.c +++ b/apps/dsa.c @@ -1,68 +1,23 @@ -/* apps/dsa.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <openssl/opensslconf.h> /* for OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DSA +#include <openssl/opensslconf.h> +#ifdef OPENSSL_NO_DSA +NON_EMPTY_TRANSLATION_UNIT +#else + # include <stdio.h> # include <stdlib.h> # include <string.h> # include <time.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/dsa.h> @@ -71,206 +26,143 @@ # include <openssl/pem.h> # include <openssl/bn.h> -# undef PROG -# define PROG dsa_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE, + /* Do not change the order here; see case statements below */ + OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, + OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN, + OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT +} OPTION_CHOICE; -/*- - * -inform arg - input format - default PEM (one of DER, NET or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -des - encrypt output if PEM format with DES in cbc mode - * -des3 - encrypt output if PEM format - * -idea - encrypt output if PEM format - * -aes128 - encrypt output if PEM format - * -aes192 - encrypt output if PEM format - * -aes256 - encrypt output if PEM format - * -camellia128 - encrypt output if PEM format - * -camellia192 - encrypt output if PEM format - * -camellia256 - encrypt output if PEM format - * -seed - encrypt output if PEM format - * -text - print a text version - * -modulus - print the DSA public key - */ - -int MAIN(int, char **); +const OPTIONS dsa_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"}, + {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"}, + {"in", OPT_IN, 's', "Input key"}, + {"out", OPT_OUT, '>', "Output file"}, + {"noout", OPT_NOOUT, '-', "Don't print key out"}, + {"text", OPT_TEXT, '-', "Print the key in text"}, + {"modulus", OPT_MODULUS, '-', "Print the DSA public value"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# ifndef OPENSSL_NO_RC4 + {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, + {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, + {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +# endif + {NULL} +}; -int MAIN(int argc, char **argv) +int dsa_main(int argc, char **argv) { - ENGINE *e = NULL; - int ret = 1; + BIO *out = NULL; DSA *dsa = NULL; - int i, badops = 0; + ENGINE *e = NULL; const EVP_CIPHER *enc = NULL; - BIO *in = NULL, *out = NULL; - int informat, outformat, text = 0, noout = 0; - int pubin = 0, pubout = 0; - char *infile, *outfile, *prog; - char *engine; - char *passargin = NULL, *passargout = NULL; - char *passin = NULL, *passout = NULL; - int modulus = 0; - + char *infile = NULL, *outfile = NULL, *prog; + char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; + OPTION_CHOICE o; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; + int i, modulus = 0, pubin = 0, pubout = 0, ret = 1; +# ifndef OPENSSL_NO_RC4 int pvk_encr = 2; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - engine = NULL; - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-passout") == 0) { - if (--argc < 1) - goto bad; - passargout = *(++argv); - } -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } # endif - else if (strcmp(*argv, "-pvk-strong") == 0) - pvk_encr = 2; - else if (strcmp(*argv, "-pvk-weak") == 0) - pvk_encr = 1; - else if (strcmp(*argv, "-pvk-none") == 0) - pvk_encr = 0; - else if (strcmp(*argv, "-noout") == 0) + int private = 0; + + prog = opt_init(argc, argv, dsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + ret = 0; + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dsa_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_PVK_STRONG: /* pvk_encr:= 2 */ + case OPT_PVK_WEAK: /* pvk_encr:= 1 */ + case OPT_PVK_NONE: /* pvk_encr:= 0 */ +#ifndef OPENSSL_NO_RC4 + pvk_encr = (o - OPT_PVK_NONE); +#endif + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-text") == 0) + break; + case OPT_TEXT: text = 1; - else if (strcmp(*argv, "-modulus") == 0) + break; + case OPT_MODULUS: modulus = 1; - else if (strcmp(*argv, "-pubin") == 0) + break; + case OPT_PUBIN: pubin = 1; - else if (strcmp(*argv, "-pubout") == 0) + break; + case OPT_PUBOUT: pubout = 1; - else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto end; break; } - argc--; - argv++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - DER or PEM\n"); - BIO_printf(bio_err, " -outform arg output format - DER or PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, - " -passin arg input file pass phrase source\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, - " -passout arg output file pass phrase source\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, - " -des encrypt PEM output with cbc des\n"); - BIO_printf(bio_err, - " -des3 encrypt PEM output with ede cbc des using 168 bit key\n"); -# ifndef OPENSSL_NO_IDEA - BIO_printf(bio_err, - " -idea encrypt PEM output with cbc idea\n"); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, " -aes128, -aes192, -aes256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc aes\n"); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, " -camellia128, -camellia192, -camellia256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc camellia\n"); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, - " -seed encrypt PEM output with cbc seed\n"); -# endif - BIO_printf(bio_err, " -text print the key in text\n"); - BIO_printf(bio_err, " -noout don't print key out\n"); - BIO_printf(bio_err, " -modulus print the DSA public value\n"); - goto end; - } + private = pubin || pubout ? 0 : 1; + if (text && !pubin) + private = 1; - ERR_load_crypto_strings(); - - e = setup_engine(bio_err, engine, 0); - - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); - goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } - BIO_printf(bio_err, "read DSA key\n"); - { EVP_PKEY *pkey; if (pubin) - pkey = load_pubkey(bio_err, infile, informat, 1, - passin, e, "Public Key"); + pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); else - pkey = load_key(bio_err, infile, informat, 1, - passin, e, "Private Key"); + pkey = load_key(infile, informat, 1, passin, e, "Private Key"); - if (pkey) { + if (pkey != NULL) { dsa = EVP_PKEY_get1_DSA(pkey); EVP_PKEY_free(pkey); } @@ -281,49 +173,48 @@ int MAIN(int argc, char **argv) goto end; } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; - if (text) + if (text) { + assert(pubin || private); if (!DSA_print(out, dsa, 0)) { perror(outfile); ERR_print_errors(bio_err); goto end; } + } if (modulus) { - fprintf(stdout, "Public Key="); - BN_print(out, dsa->pub_key); - fprintf(stdout, "\n"); + const BIGNUM *pub_key = NULL; + DSA_get0_key(dsa, &pub_key, NULL); + BIO_printf(out, "Public Key="); + BN_print(out, pub_key); + BIO_printf(out, "\n"); } - if (noout) + if (noout) { + ret = 0; goto end; + } BIO_printf(bio_err, "writing DSA key\n"); if (outformat == FORMAT_ASN1) { - if (pubin || pubout) + if (pubin || pubout) { i = i2d_DSA_PUBKEY_bio(out, dsa); - else + } else { + assert(private); i = i2d_DSAPrivateKey_bio(out, dsa); + } } else if (outformat == FORMAT_PEM) { - if (pubin || pubout) + if (pubin || pubout) { i = PEM_write_bio_DSA_PUBKEY(out, dsa); - else + } else { + assert(private); i = PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout); -# if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_RC4) + } +# ifndef OPENSSL_NO_RSA } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { EVP_PKEY *pk; pk = EVP_PKEY_new(); @@ -331,12 +222,26 @@ int MAIN(int argc, char **argv) goto end; EVP_PKEY_set1_DSA(pk, dsa); - if (outformat == FORMAT_PVK) + if (outformat == FORMAT_PVK) { + if (pubin) { + BIO_printf(bio_err, "PVK form impossible with public key input\n"); + EVP_PKEY_free(pk); + goto end; + } + assert(private); +# ifdef OPENSSL_NO_RC4 + BIO_printf(bio_err, "PVK format not supported\n"); + EVP_PKEY_free(pk); + goto end; +# else i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); - else if (pubin || pubout) +# endif + } else if (pubin || pubout) { i = i2b_PublicKey_bio(out, pk); - else + } else { + assert(private); i = i2b_PrivateKey_bio(out, pk); + } EVP_PKEY_free(pk); # endif } else { @@ -346,27 +251,15 @@ int MAIN(int argc, char **argv) if (i <= 0) { BIO_printf(bio_err, "unable to write private key\n"); ERR_print_errors(bio_err); - } else - ret = 0; + goto end; + } + ret = 0; end: - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (dsa != NULL) - DSA_free(dsa); + BIO_free_all(out); + DSA_free(dsa); release_engine(e); - if (passin) - OPENSSL_free(passin); - if (passout) - OPENSSL_free(passout); - apps_shutdown(); - OPENSSL_EXIT(ret); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; } -#else /* !OPENSSL_NO_DSA */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/dsaparam.c b/apps/dsaparam.c index 3a4a123846c4..b227b76a3723 100644 --- a/apps/dsaparam.c +++ b/apps/dsaparam.c @@ -1,77 +1,23 @@ -/* apps/dsaparam.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <openssl/opensslconf.h> /* for OPENSSL_NO_DSA */ -/* - * Until the key-gen callbacks are modified to use newer prototypes, we allow - * deprecated functions for openssl-internal code - */ -#ifdef OPENSSL_NO_DEPRECATED -# undef OPENSSL_NO_DEPRECATED -#endif +#include <openssl/opensslconf.h> +#ifdef OPENSSL_NO_DSA +NON_EMPTY_TRANSLATION_UNIT +#else -#ifndef OPENSSL_NO_DSA -# include <assert.h> # include <stdio.h> # include <stdlib.h> # include <time.h> # include <string.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/bn.h> @@ -79,245 +25,138 @@ # include <openssl/x509.h> # include <openssl/pem.h> -# undef PROG -# define PROG dsaparam_main - -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -noout - * -text - * -C - * -noout - * -genkey - * #ifdef GENCB_TEST - * -timebomb n - interrupt keygen after <n> seconds - * #endif - */ - -# ifdef GENCB_TEST +static int dsa_cb(int p, int n, BN_GENCB *cb); -static int stop_keygen_flag = 0; - -static void timebomb_sigalarm(int foo) -{ - stop_keygen_flag = 1; -} +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, + OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM +} OPTION_CHOICE; +const OPTIONS dsaparam_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"text", OPT_TEXT, '-', "Print as text"}, + {"C", OPT_C, '-', "Output C code"}, + {"noout", OPT_NOOUT, '-', "No output"}, + {"genkey", OPT_GENKEY, '-', "Generate a DSA key"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, # endif + {NULL} +}; -static int MS_CALLBACK dsa_cb(int p, int n, BN_GENCB *cb); - -int MAIN(int, char **); - -int MAIN(int argc, char **argv) +int dsaparam_main(int argc, char **argv) { + ENGINE *e = NULL; DSA *dsa = NULL; - int i, badops = 0, text = 0; BIO *in = NULL, *out = NULL; - int informat, outformat, noout = 0, C = 0, ret = 1; - char *infile, *outfile, *prog, *inrand = NULL; - int numbits = -1, num, genkey = 0; - int need_rand = 0; - char *engine = NULL; - ENGINE *e = NULL; -# ifdef GENCB_TEST - int timebomb = 0; -# endif - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); + BN_GENCB *cb = NULL; + int numbits = -1, num = 0, genkey = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; + int ret = 1, i, text = 0, private = 0; + char *infile = NULL, *outfile = NULL, *prog; + OPTION_CHOICE o; - if (!load_config(bio_err, NULL)) - goto end; - - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -# endif -# ifdef GENCB_TEST - else if (strcmp(*argv, "-timebomb") == 0) { - if (--argc < 1) - goto bad; - timebomb = atoi(*(++argv)); - } -# endif - else if (strcmp(*argv, "-text") == 0) + prog = opt_init(argc, argv, dsaparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dsaparam_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_TEXT: text = 1; - else if (strcmp(*argv, "-C") == 0) + break; + case OPT_C: C = 1; - else if (strcmp(*argv, "-genkey") == 0) { + break; + case OPT_GENKEY: genkey = 1; - need_rand = 1; - } else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - need_rand = 1; - } else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_NOOUT: noout = 1; - else if (sscanf(*argv, "%d", &num) == 1) { - /* generate a key */ - numbits = num; - need_rand = 1; - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; break; } - argc--; - argv++; } + argc = opt_num_rest(); + argv = opt_rest(); - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] [bits] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - DER or PEM\n"); - BIO_printf(bio_err, " -outform arg output format - DER or PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, " -text print as text\n"); - BIO_printf(bio_err, " -C Output C code\n"); - BIO_printf(bio_err, " -noout no output\n"); - BIO_printf(bio_err, " -genkey generate a DSA key\n"); - BIO_printf(bio_err, - " -rand files to use for random number input\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -# endif -# ifdef GENCB_TEST - BIO_printf(bio_err, - " -timebomb n interrupt keygen after <n> seconds\n"); -# endif - BIO_printf(bio_err, - " number number of bits to use for generating private key\n"); - goto end; + if (argc == 1) { + if (!opt_int(argv[0], &num) || num < 0) + goto end; + /* generate a key */ + numbits = num; } + private = genkey ? 1 : 0; - ERR_load_crypto_strings(); - - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) goto end; - } - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); + if (numbits > 0) { + if (numbits > OPENSSL_DSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for DSA keys.\n" + " Your key size is %d! Larger key size may behave not as expected.\n", + OPENSSL_DSA_MAX_MODULUS_BITS, numbits); + + cb = BN_GENCB_new(); + if (cb == NULL) { + BIO_printf(bio_err, "Error allocating BN_GENCB object\n"); goto end; } - } - - e = setup_engine(bio_err, engine, 0); - - if (need_rand) { - app_RAND_load_file(NULL, bio_err, (inrand != NULL)); - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - } - - if (numbits > 0) { - BN_GENCB cb; - BN_GENCB_set(&cb, dsa_cb, bio_err); - assert(need_rand); + BN_GENCB_set(cb, dsa_cb, bio_err); dsa = DSA_new(); - if (!dsa) { + if (dsa == NULL) { BIO_printf(bio_err, "Error allocating DSA object\n"); goto end; } BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num); BIO_printf(bio_err, "This could take some time\n"); -# ifdef GENCB_TEST - if (timebomb > 0) { - struct sigaction act; - act.sa_handler = timebomb_sigalarm; - act.sa_flags = 0; - BIO_printf(bio_err, - "(though I'll stop it if not done within %d secs)\n", - timebomb); - if (sigaction(SIGALRM, &act, NULL) != 0) { - BIO_printf(bio_err, "Error, couldn't set SIGALRM handler\n"); - goto end; - } - alarm(timebomb); - } -# endif - if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, &cb)) { -# ifdef GENCB_TEST - if (stop_keygen_flag) { - BIO_printf(bio_err, "DSA key generation time-stopped\n"); - /* This is an asked-for behaviour! */ - ret = 0; - goto end; - } -# endif + if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) { ERR_print_errors(bio_err); BIO_printf(bio_err, "Error, DSA key generation failed\n"); goto end; } - } else if (informat == FORMAT_ASN1) + } else if (informat == FORMAT_ASN1) { dsa = d2i_DSAparams_bio(in, NULL); - else if (informat == FORMAT_PEM) + } else { dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); - else { - BIO_printf(bio_err, "bad input format specified\n"); - goto end; } if (dsa == NULL) { BIO_printf(bio_err, "unable to load DSA parameters\n"); @@ -330,56 +169,39 @@ int MAIN(int argc, char **argv) } if (C) { + const BIGNUM *p = NULL, *q = NULL, *g = NULL; unsigned char *data; - int l, len, bits_p; + int len, bits_p; - len = BN_num_bytes(dsa->p); - bits_p = BN_num_bits(dsa->p); - data = (unsigned char *)OPENSSL_malloc(len + 20); - if (data == NULL) { - perror("OPENSSL_malloc"); - goto end; - } - l = BN_bn2bin(dsa->p, data); - printf("static unsigned char dsa%d_p[]={", bits_p); - for (i = 0; i < l; i++) { - if ((i % 12) == 0) - printf("\n\t"); - printf("0x%02X,", data[i]); - } - printf("\n\t};\n"); + DSA_get0_pqg(dsa, &p, &q, &g); + len = BN_num_bytes(p); + bits_p = BN_num_bits(p); - l = BN_bn2bin(dsa->q, data); - printf("static unsigned char dsa%d_q[]={", bits_p); - for (i = 0; i < l; i++) { - if ((i % 12) == 0) - printf("\n\t"); - printf("0x%02X,", data[i]); - } - printf("\n\t};\n"); + data = app_malloc(len + 20, "BN space"); - l = BN_bn2bin(dsa->g, data); - printf("static unsigned char dsa%d_g[]={", bits_p); - for (i = 0; i < l; i++) { - if ((i % 12) == 0) - printf("\n\t"); - printf("0x%02X,", data[i]); - } - printf("\n\t};\n\n"); - - printf("DSA *get_dsa%d()\n\t{\n", bits_p); - printf("\tDSA *dsa;\n\n"); - printf("\tif ((dsa=DSA_new()) == NULL) return(NULL);\n"); - printf("\tdsa->p=BN_bin2bn(dsa%d_p,sizeof(dsa%d_p),NULL);\n", - bits_p, bits_p); - printf("\tdsa->q=BN_bin2bn(dsa%d_q,sizeof(dsa%d_q),NULL);\n", - bits_p, bits_p); - printf("\tdsa->g=BN_bin2bn(dsa%d_g,sizeof(dsa%d_g),NULL);\n", - bits_p, bits_p); - printf - ("\tif ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))\n"); - printf("\t\t{ DSA_free(dsa); return(NULL); }\n"); - printf("\treturn(dsa);\n\t}\n"); + BIO_printf(bio_out, "static DSA *get_dsa%d(void)\n{\n", bits_p); + print_bignum_var(bio_out, p, "dsap", bits_p, data); + print_bignum_var(bio_out, q, "dsaq", bits_p, data); + print_bignum_var(bio_out, g, "dsag", bits_p, data); + BIO_printf(bio_out, " DSA *dsa = DSA_new();\n" + " BIGNUM *p, *q, *g;\n" + "\n"); + BIO_printf(bio_out, " if (dsa == NULL)\n" + " return NULL;\n"); + BIO_printf(bio_out, " if (!DSA_set0_pqg(dsa, p = BN_bin2bn(dsap_%d, sizeof(dsap_%d), NULL),\n", + bits_p, bits_p); + BIO_printf(bio_out, " q = BN_bin2bn(dsaq_%d, sizeof(dsaq_%d), NULL),\n", + bits_p, bits_p); + BIO_printf(bio_out, " g = BN_bin2bn(dsag_%d, sizeof(dsag_%d), NULL))) {\n", + bits_p, bits_p); + BIO_printf(bio_out, " DSA_free(dsa);\n" + " BN_free(p);\n" + " BN_free(q);\n" + " BN_free(g);\n" + " return NULL;\n" + " }\n" + " return dsa;\n}\n"); + OPENSSL_free(data); } if (outformat == FORMAT_ASN1 && genkey) @@ -388,12 +210,8 @@ int MAIN(int argc, char **argv) if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_DSAparams_bio(out, dsa); - else if (outformat == FORMAT_PEM) + else i = PEM_write_bio_DSAparams(out, dsa); - else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; - } if (!i) { BIO_printf(bio_err, "unable to write DSA parameters\n"); ERR_print_errors(bio_err); @@ -403,7 +221,6 @@ int MAIN(int argc, char **argv) if (genkey) { DSA *dsakey; - assert(need_rand); if ((dsakey = DSAparams_dup(dsa)) == NULL) goto end; if (!DSA_generate_key(dsakey)) { @@ -411,60 +228,31 @@ int MAIN(int argc, char **argv) DSA_free(dsakey); goto end; } + assert(private); if (outformat == FORMAT_ASN1) i = i2d_DSAPrivateKey_bio(out, dsakey); - else if (outformat == FORMAT_PEM) + else i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL, NULL); - else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - DSA_free(dsakey); - goto end; - } DSA_free(dsakey); } - if (need_rand) - app_RAND_write_file(NULL, bio_err); ret = 0; end: - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (dsa != NULL) - DSA_free(dsa); + BN_GENCB_free(cb); + BIO_free(in); + BIO_free_all(out); + DSA_free(dsa); release_engine(e); - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } -static int MS_CALLBACK dsa_cb(int p, int n, BN_GENCB *cb) +static int dsa_cb(int p, int n, BN_GENCB *cb) { - char c = '*'; + static const char symbols[] = ".+*\n"; + char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; - if (p == 0) - c = '.'; - if (p == 1) - c = '+'; - if (p == 2) - c = '*'; - if (p == 3) - c = '\n'; - BIO_write(cb->arg, &c, 1); - (void)BIO_flush(cb->arg); -# ifdef LINT - p = n; -# endif -# ifdef GENCB_TEST - if (stop_keygen_flag) - return 0; -# endif + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void)BIO_flush(BN_GENCB_get_arg(cb)); return 1; } -#else /* !OPENSSL_NO_DSA */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/ec.c b/apps/ec.c index d2263c87392e..03abb0068337 100644 --- a/apps/ec.c +++ b/apps/ec.c @@ -1,262 +1,180 @@ -/* apps/ec.c */ /* - * Written by Nils Larsch for the OpenSSL project. - */ -/* ==================================================================== - * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC +#ifdef OPENSSL_NO_EC +NON_EMPTY_TRANSLATION_UNIT +#else + # include <stdio.h> # include <stdlib.h> # include <string.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/evp.h> # include <openssl/pem.h> -# undef PROG -# define PROG ec_main +static OPT_PAIR conv_forms[] = { + {"compressed", POINT_CONVERSION_COMPRESSED}, + {"uncompressed", POINT_CONVERSION_UNCOMPRESSED}, + {"hybrid", POINT_CONVERSION_HYBRID}, + {NULL} +}; -/*- - * -inform arg - input format - default PEM (one of DER, NET or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -des - encrypt output if PEM format with DES in cbc mode - * -text - print a text version - * -param_out - print the elliptic curve parameters - * -conv_form arg - specifies the point encoding form - * -param_enc arg - specifies the parameter encoding - */ +static OPT_PAIR param_enc[] = { + {"named_curve", OPENSSL_EC_NAMED_CURVE}, + {"explicit", 0}, + {NULL} +}; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, + OPT_NOOUT, OPT_TEXT, OPT_PARAM_OUT, OPT_PUBIN, OPT_PUBOUT, + OPT_PASSIN, OPT_PASSOUT, OPT_PARAM_ENC, OPT_CONV_FORM, OPT_CIPHER, + OPT_NO_PUBLIC, OPT_CHECK +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS ec_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, 's', "Input file"}, + {"inform", OPT_INFORM, 'f', "Input format - DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"noout", OPT_NOOUT, '-', "Don't print key out"}, + {"text", OPT_TEXT, '-', "Print the key"}, + {"param_out", OPT_PARAM_OUT, '-', "Print the elliptic curve parameters"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, + {"no_public", OPT_NO_PUBLIC, '-', "exclude public key from private key"}, + {"check", OPT_CHECK, '-', "check key consistency"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"param_enc", OPT_PARAM_ENC, 's', + "Specifies the way the ec parameters are encoded"}, + {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; -int MAIN(int argc, char **argv) +int ec_main(int argc, char **argv) { - int ret = 1; + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; EC_KEY *eckey = NULL; const EC_GROUP *group; - int i, badops = 0; const EVP_CIPHER *enc = NULL; - BIO *in = NULL, *out = NULL; - int informat, outformat, text = 0, noout = 0; - int pubin = 0, pubout = 0, param_out = 0; - char *infile, *outfile, *prog, *engine; - ENGINE *e = NULL; - char *passargin = NULL, *passargout = NULL; - char *passin = NULL, *passout = NULL; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; - int new_form = 0; - int asn1_flag = OPENSSL_EC_NAMED_CURVE; - int new_asn1_flag = 0; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; + char *infile = NULL, *outfile = NULL, *prog; + char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; + OPTION_CHOICE o; + int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_form = 0, new_asn1_flag = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; + int pubin = 0, pubout = 0, param_out = 0, i, ret = 1, private = 0; + int no_public = 0, check = 0; - engine = NULL; - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-passout") == 0) { - if (--argc < 1) - goto bad; - passargout = *(++argv); - } else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } else if (strcmp(*argv, "-noout") == 0) + prog = opt_init(argc, argv, ec_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ec_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-text") == 0) + break; + case OPT_TEXT: text = 1; - else if (strcmp(*argv, "-conv_form") == 0) { - if (--argc < 1) - goto bad; - ++argv; - new_form = 1; - if (strcmp(*argv, "compressed") == 0) - form = POINT_CONVERSION_COMPRESSED; - else if (strcmp(*argv, "uncompressed") == 0) - form = POINT_CONVERSION_UNCOMPRESSED; - else if (strcmp(*argv, "hybrid") == 0) - form = POINT_CONVERSION_HYBRID; - else - goto bad; - } else if (strcmp(*argv, "-param_enc") == 0) { - if (--argc < 1) - goto bad; - ++argv; - new_asn1_flag = 1; - if (strcmp(*argv, "named_curve") == 0) - asn1_flag = OPENSSL_EC_NAMED_CURVE; - else if (strcmp(*argv, "explicit") == 0) - asn1_flag = 0; - else - goto bad; - } else if (strcmp(*argv, "-param_out") == 0) + break; + case OPT_PARAM_OUT: param_out = 1; - else if (strcmp(*argv, "-pubin") == 0) + break; + case OPT_PUBIN: pubin = 1; - else if (strcmp(*argv, "-pubout") == 0) + break; + case OPT_PUBOUT: pubout = 1; - else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto opthelp; + break; + case OPT_CONV_FORM: + if (!opt_pair(opt_arg(), conv_forms, &i)) + goto opthelp; + new_form = 1; + form = i; + break; + case OPT_PARAM_ENC: + if (!opt_pair(opt_arg(), param_enc, &i)) + goto opthelp; + new_asn1_flag = 1; + asn1_flag = i; + break; + case OPT_NO_PUBLIC: + no_public = 1; + break; + case OPT_CHECK: + check = 1; break; } - argc--; - argv++; - } - - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - " - "DER or PEM\n"); - BIO_printf(bio_err, " -outform arg output format - " - "DER or PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -passin arg input file pass " - "phrase source\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, " -passout arg output file pass " - "phrase source\n"); - BIO_printf(bio_err, " -engine e use engine e, " - "possibly a hardware device.\n"); - BIO_printf(bio_err, " -des encrypt PEM output, " - "instead of 'des' every other \n" - " cipher " - "supported by OpenSSL can be used\n"); - BIO_printf(bio_err, " -text print the key\n"); - BIO_printf(bio_err, " -noout don't print key out\n"); - BIO_printf(bio_err, " -param_out print the elliptic " - "curve parameters\n"); - BIO_printf(bio_err, " -conv_form arg specifies the " - "point conversion form \n"); - BIO_printf(bio_err, " possible values:" - " compressed\n"); - BIO_printf(bio_err, " " - " uncompressed (default)\n"); - BIO_printf(bio_err, " " " hybrid\n"); - BIO_printf(bio_err, " -param_enc arg specifies the way" - " the ec parameters are encoded\n"); - BIO_printf(bio_err, " in the asn1 der " "encoding\n"); - BIO_printf(bio_err, " possible values:" - " named_curve (default)\n"); - BIO_printf(bio_err, " " - "explicit\n"); - goto end; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - ERR_load_crypto_strings(); - - e = setup_engine(bio_err, engine, 0); + private = param_out || pubin || pubout ? 0 : 1; + if (text && !pubin) + private = 1; - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); - goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); + if (informat != FORMAT_ENGINE) { + in = bio_open_default(infile, 'r', informat); + if (in == NULL) goto end; - } } BIO_printf(bio_err, "read EC key\n"); @@ -265,14 +183,21 @@ int MAIN(int argc, char **argv) eckey = d2i_EC_PUBKEY_bio(in, NULL); else eckey = d2i_ECPrivateKey_bio(in, NULL); - } else if (informat == FORMAT_PEM) { + } else if (informat == FORMAT_ENGINE) { + EVP_PKEY *pkey; + if (pubin) + pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); + else + pkey = load_key(infile, informat, 1, passin, e, "Private Key"); + if (pkey != NULL) { + eckey = EVP_PKEY_get1_EC_KEY(pkey); + EVP_PKEY_free(pkey); + } + } else { if (pubin) eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL); else eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin); - } else { - BIO_printf(bio_err, "bad input format specified for key\n"); - goto end; } if (eckey == NULL) { BIO_printf(bio_err, "unable to load Key\n"); @@ -280,20 +205,9 @@ int MAIN(int argc, char **argv) goto end; } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; group = EC_KEY_get0_group(eckey); @@ -303,12 +217,26 @@ int MAIN(int argc, char **argv) if (new_asn1_flag) EC_KEY_set_asn1_flag(eckey, asn1_flag); - if (text) + if (no_public) + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + + if (text) { + assert(pubin || private); if (!EC_KEY_print(out, eckey, 0)) { perror(outfile); ERR_print_errors(bio_err); goto end; } + } + + if (check) { + if (EC_KEY_check_key(eckey) == 1) { + BIO_printf(bio_err, "EC Key valid.\n"); + } else { + BIO_printf(bio_err, "EC Key Invalid!\n"); + ERR_print_errors(bio_err); + } + } if (noout) { ret = 0; @@ -317,49 +245,39 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "writing EC key\n"); if (outformat == FORMAT_ASN1) { - if (param_out) + if (param_out) { i = i2d_ECPKParameters_bio(out, group); - else if (pubin || pubout) + } else if (pubin || pubout) { i = i2d_EC_PUBKEY_bio(out, eckey); - else + } else { + assert(private); i = i2d_ECPrivateKey_bio(out, eckey); - } else if (outformat == FORMAT_PEM) { - if (param_out) + } + } else { + if (param_out) { i = PEM_write_bio_ECPKParameters(out, group); - else if (pubin || pubout) + } else if (pubin || pubout) { i = PEM_write_bio_EC_PUBKEY(out, eckey); - else + } else { + assert(private); i = PEM_write_bio_ECPrivateKey(out, eckey, enc, NULL, 0, NULL, passout); - } else { - BIO_printf(bio_err, "bad output format specified for " "outfile\n"); - goto end; + } } if (!i) { BIO_printf(bio_err, "unable to write private key\n"); ERR_print_errors(bio_err); - } else + } else { ret = 0; + } end: - if (in) - BIO_free(in); - if (out) - BIO_free_all(out); - if (eckey) - EC_KEY_free(eckey); + BIO_free(in); + BIO_free_all(out); + EC_KEY_free(eckey); release_engine(e); - if (passin) - OPENSSL_free(passin); - if (passout) - OPENSSL_free(passout); - apps_shutdown(); - OPENSSL_EXIT(ret); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; } -#else /* !OPENSSL_NO_EC */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/ecparam.c b/apps/ecparam.c index 8d5b7044489c..917f1a86b2e3 100644 --- a/apps/ecparam.c +++ b/apps/ecparam.c @@ -1,82 +1,24 @@ -/* apps/ecparam.c */ /* - * Written by Nils Larsch for the OpenSSL project. - */ -/* ==================================================================== - * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * - * Portions of the attached software ("Contribution") are developed by - * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. - * - * The Contribution is licensed pursuant to the OpenSSL open source - * license provided above. - * - * The elliptic curve binary polynomial software is originally written by - * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC -# include <assert.h> +#ifdef OPENSSL_NO_EC +NON_EMPTY_TRANSLATION_UNIT +#else + # include <stdio.h> # include <stdlib.h> # include <time.h> # include <string.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/bn.h> @@ -84,248 +26,161 @@ # include <openssl/x509.h> # include <openssl/pem.h> -# undef PROG -# define PROG ecparam_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, + OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME, + OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, + OPT_R_ENUM +} OPTION_CHOICE; -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -noout - do not print the ec parameter - * -text - print the ec parameters in text form - * -check - validate the ec parameters - * -C - print a 'C' function creating the parameters - * -name arg - use the ec parameters with 'short name' name - * -list_curves - prints a list of all currently available curve 'short names' - * -conv_form arg - specifies the point conversion form - * - possible values: compressed - * uncompressed (default) - * hybrid - * -param_enc arg - specifies the way the ec parameters are encoded - * in the asn1 der encoding - * possible values: named_curve (default) - * explicit - * -no_seed - if 'explicit' parameters are chosen do not use the seed - * -genkey - generate ec key - * -rand file - files to use for random number input - * -engine e - use engine e, possibly a hardware device - */ +const OPTIONS ecparam_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"text", OPT_TEXT, '-', "Print the ec parameters in text form"}, + {"C", OPT_C, '-', "Print a 'C' function creating the parameters"}, + {"check", OPT_CHECK, '-', "Validate the ec parameters"}, + {"list_curves", OPT_LIST_CURVES, '-', + "Prints a list of all curve 'short names'"}, + {"no_seed", OPT_NO_SEED, '-', + "If 'explicit' parameters are chosen do not use the seed"}, + {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"}, + {"name", OPT_NAME, 's', + "Use the ec parameters with specified 'short name'"}, + {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, + {"param_enc", OPT_PARAM_ENC, 's', + "Specifies the way the ec parameters are encoded"}, + {"genkey", OPT_GENKEY, '-', "Generate ec key"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; -static int ecparam_print_var(BIO *, BIGNUM *, const char *, int, - unsigned char *); +static OPT_PAIR forms[] = { + {"compressed", POINT_CONVERSION_COMPRESSED}, + {"uncompressed", POINT_CONVERSION_UNCOMPRESSED}, + {"hybrid", POINT_CONVERSION_HYBRID}, + {NULL} +}; -int MAIN(int, char **); +static OPT_PAIR encodings[] = { + {"named_curve", OPENSSL_EC_NAMED_CURVE}, + {"explicit", 0}, + {NULL} +}; -int MAIN(int argc, char **argv) +int ecparam_main(int argc, char **argv) { + ENGINE *e = NULL; + BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; + BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL; + BIO *in = NULL, *out = NULL; EC_GROUP *group = NULL; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; - int new_form = 0; - int asn1_flag = OPENSSL_EC_NAMED_CURVE; - int new_asn1_flag = 0; - char *curve_name = NULL, *inrand = NULL; - int list_curves = 0, no_seed = 0, check = 0, - badops = 0, text = 0, i, need_rand = 0, genkey = 0; + char *curve_name = NULL; char *infile = NULL, *outfile = NULL, *prog; - BIO *in = NULL, *out = NULL; - int informat, outformat, noout = 0, C = 0, ret = 1; - char *engine = NULL; - ENGINE *e = NULL; - - BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL, - *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; unsigned char *buffer = NULL; + OPTION_CHOICE o; + int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; + int ret = 1, private = 0; + int list_curves = 0, no_seed = 0, check = 0, new_form = 0; + int text = 0, i, genkey = 0; - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-text") == 0) + prog = opt_init(argc, argv, ecparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ecparam_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_TEXT: text = 1; - else if (strcmp(*argv, "-C") == 0) + break; + case OPT_C: C = 1; - else if (strcmp(*argv, "-check") == 0) + break; + case OPT_CHECK: check = 1; - else if (strcmp(*argv, "-name") == 0) { - if (--argc < 1) - goto bad; - curve_name = *(++argv); - } else if (strcmp(*argv, "-list_curves") == 0) + break; + case OPT_LIST_CURVES: list_curves = 1; - else if (strcmp(*argv, "-conv_form") == 0) { - if (--argc < 1) - goto bad; - ++argv; - new_form = 1; - if (strcmp(*argv, "compressed") == 0) - form = POINT_CONVERSION_COMPRESSED; - else if (strcmp(*argv, "uncompressed") == 0) - form = POINT_CONVERSION_UNCOMPRESSED; - else if (strcmp(*argv, "hybrid") == 0) - form = POINT_CONVERSION_HYBRID; - else - goto bad; - } else if (strcmp(*argv, "-param_enc") == 0) { - if (--argc < 1) - goto bad; - ++argv; - new_asn1_flag = 1; - if (strcmp(*argv, "named_curve") == 0) - asn1_flag = OPENSSL_EC_NAMED_CURVE; - else if (strcmp(*argv, "explicit") == 0) - asn1_flag = 0; - else - goto bad; - } else if (strcmp(*argv, "-no_seed") == 0) + break; + case OPT_NO_SEED: no_seed = 1; - else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-genkey") == 0) { + break; + case OPT_NAME: + curve_name = opt_arg(); + break; + case OPT_CONV_FORM: + if (!opt_pair(opt_arg(), forms, &new_form)) + goto opthelp; + form = new_form; + new_form = 1; + break; + case OPT_PARAM_ENC: + if (!opt_pair(opt_arg(), encodings, &asn1_flag)) + goto opthelp; + new_asn1_flag = 1; + break; + case OPT_GENKEY: genkey = 1; - need_rand = 1; - } else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - need_rand = 1; - } else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); break; } - argc--; - argv++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - " - "default PEM (DER or PEM)\n"); - BIO_printf(bio_err, " -outform arg output format - " - "default PEM\n"); - BIO_printf(bio_err, " -in arg input file - " - "default stdin\n"); - BIO_printf(bio_err, " -out arg output file - " - "default stdout\n"); - BIO_printf(bio_err, " -noout do not print the " - "ec parameter\n"); - BIO_printf(bio_err, " -text print the ec " - "parameters in text form\n"); - BIO_printf(bio_err, " -check validate the ec " - "parameters\n"); - BIO_printf(bio_err, " -C print a 'C' " - "function creating the parameters\n"); - BIO_printf(bio_err, " -name arg use the " - "ec parameters with 'short name' name\n"); - BIO_printf(bio_err, " -list_curves prints a list of " - "all currently available curve 'short names'\n"); - BIO_printf(bio_err, " -conv_form arg specifies the " - "point conversion form \n"); - BIO_printf(bio_err, " possible values:" - " compressed\n"); - BIO_printf(bio_err, " " - " uncompressed (default)\n"); - BIO_printf(bio_err, " " - " hybrid\n"); - BIO_printf(bio_err, " -param_enc arg specifies the way" - " the ec parameters are encoded\n"); - BIO_printf(bio_err, " in the asn1 der " - "encoding\n"); - BIO_printf(bio_err, " possible values:" - " named_curve (default)\n"); - BIO_printf(bio_err, " " - " explicit\n"); - BIO_printf(bio_err, " -no_seed if 'explicit'" - " parameters are chosen do not" " use the seed\n"); - BIO_printf(bio_err, " -genkey generate ec" " key\n"); - BIO_printf(bio_err, " -rand file files to use for" - " random number input\n"); - BIO_printf(bio_err, " -engine e use engine e, " - "possibly a hardware device\n"); - goto end; - } + private = genkey ? 1 : 0; - ERR_load_crypto_strings(); - - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } - - e = setup_engine(bio_err, engine, 0); if (list_curves) { EC_builtin_curve *curves = NULL; - size_t crv_len = 0; - size_t n = 0; - - crv_len = EC_get_builtin_curves(NULL, 0); - - curves = OPENSSL_malloc((int)(sizeof(EC_builtin_curve) * crv_len)); - - if (curves == NULL) - goto end; + size_t crv_len = EC_get_builtin_curves(NULL, 0); + size_t n; + curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); if (!EC_get_builtin_curves(curves, crv_len)) { OPENSSL_free(curves); goto end; @@ -358,16 +213,17 @@ int MAIN(int argc, char **argv) * are the same as the curves prime192v1 and prime256v1 defined in * X9.62) */ - if (!strcmp(curve_name, "secp192r1")) { + if (strcmp(curve_name, "secp192r1") == 0) { BIO_printf(bio_err, "using curve name prime192v1 " "instead of secp192r1\n"); nid = NID_X9_62_prime192v1; - } else if (!strcmp(curve_name, "secp256r1")) { + } else if (strcmp(curve_name, "secp256r1") == 0) { BIO_printf(bio_err, "using curve name prime256v1 " "instead of secp256r1\n"); nid = NID_X9_62_prime256v1; - } else + } else { nid = OBJ_sn2nid(curve_name); + } if (nid == 0) nid = EC_curve_nist2nid(curve_name); @@ -386,13 +242,9 @@ int MAIN(int argc, char **argv) EC_GROUP_set_point_conversion_form(group, form); } else if (informat == FORMAT_ASN1) { group = d2i_ECPKParameters_bio(in, NULL); - } else if (informat == FORMAT_PEM) { - group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); } else { - BIO_printf(bio_err, "bad input format specified\n"); - goto end; + group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); } - if (group == NULL) { BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); ERR_print_errors(bio_err); @@ -431,24 +283,25 @@ int MAIN(int argc, char **argv) int is_prime, len = 0; const EC_METHOD *meth = EC_GROUP_method_of(group); - if ((ec_p = BN_new()) == NULL || (ec_a = BN_new()) == NULL || - (ec_b = BN_new()) == NULL || (ec_gen = BN_new()) == NULL || - (ec_order = BN_new()) == NULL || - (ec_cofactor = BN_new()) == NULL) { - perror("OPENSSL_malloc"); + if ((ec_p = BN_new()) == NULL + || (ec_a = BN_new()) == NULL + || (ec_b = BN_new()) == NULL + || (ec_gen = BN_new()) == NULL + || (ec_order = BN_new()) == NULL + || (ec_cofactor = BN_new()) == NULL) { + perror("Can't allocate BN"); goto end; } is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); - - if (is_prime) { - if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a, ec_b, NULL)) - goto end; - } else { - /* TODO */ + if (!is_prime) { + BIO_printf(bio_err, "Can only handle X9.62 prime fields\n"); goto end; } + if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL)) + goto end; + if ((point = EC_GROUP_get0_generator(group)) == NULL) goto end; if (!EC_POINT_point2bn(group, point, @@ -478,72 +331,57 @@ int MAIN(int argc, char **argv) if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len) buf_len = tmp_len; - buffer = (unsigned char *)OPENSSL_malloc(buf_len); + buffer = app_malloc(buf_len, "BN buffer"); - if (buffer == NULL) { - perror("OPENSSL_malloc"); - goto end; - } - - ecparam_print_var(out, ec_p, "ec_p", len, buffer); - ecparam_print_var(out, ec_a, "ec_a", len, buffer); - ecparam_print_var(out, ec_b, "ec_b", len, buffer); - ecparam_print_var(out, ec_gen, "ec_gen", len, buffer); - ecparam_print_var(out, ec_order, "ec_order", len, buffer); - ecparam_print_var(out, ec_cofactor, "ec_cofactor", len, buffer); + BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len); + print_bignum_var(out, ec_p, "ec_p", len, buffer); + print_bignum_var(out, ec_a, "ec_a", len, buffer); + print_bignum_var(out, ec_b, "ec_b", len, buffer); + print_bignum_var(out, ec_gen, "ec_gen", len, buffer); + print_bignum_var(out, ec_order, "ec_order", len, buffer); + print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer); + BIO_printf(out, " int ok = 0;\n" + " EC_GROUP *group = NULL;\n" + " EC_POINT *point = NULL;\n" + " BIGNUM *tmp_1 = NULL;\n" + " BIGNUM *tmp_2 = NULL;\n" + " BIGNUM *tmp_3 = NULL;\n" + "\n"); - BIO_printf(out, "\n\n"); - - BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n\t{\n", len); - BIO_printf(out, "\tint ok=0;\n"); - BIO_printf(out, "\tEC_GROUP *group = NULL;\n"); - BIO_printf(out, "\tEC_POINT *point = NULL;\n"); - BIO_printf(out, "\tBIGNUM *tmp_1 = NULL, *tmp_2 = NULL, " - "*tmp_3 = NULL;\n\n"); - BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_p_%d, " - "sizeof(ec_p_%d), NULL)) == NULL)\n\t\t" - "goto err;\n", len, len); - BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_a_%d, " - "sizeof(ec_a_%d), NULL)) == NULL)\n\t\t" - "goto err;\n", len, len); - BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_b_%d, " - "sizeof(ec_b_%d), NULL)) == NULL)\n\t\t" - "goto err;\n", len, len); - if (is_prime) { - BIO_printf(out, "\tif ((group = EC_GROUP_new_curve_" - "GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)" - "\n\t\tgoto err;\n\n"); - } else { - /* TODO */ - goto end; - } - BIO_printf(out, "\t/* build generator */\n"); - BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_gen_%d, " - "sizeof(ec_gen_%d), tmp_1)) == NULL)" - "\n\t\tgoto err;\n", len, len); - BIO_printf(out, "\tpoint = EC_POINT_bn2point(group, tmp_1, " - "NULL, NULL);\n"); - BIO_printf(out, "\tif (point == NULL)\n\t\tgoto err;\n"); - BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_order_%d, " - "sizeof(ec_order_%d), tmp_2)) == NULL)" - "\n\t\tgoto err;\n", len, len); - BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_cofactor_%d, " - "sizeof(ec_cofactor_%d), tmp_3)) == NULL)" - "\n\t\tgoto err;\n", len, len); - BIO_printf(out, "\tif (!EC_GROUP_set_generator(group, point," - " tmp_2, tmp_3))\n\t\tgoto err;\n"); - BIO_printf(out, "\n\tok=1;\n"); - BIO_printf(out, "err:\n"); - BIO_printf(out, "\tif (tmp_1)\n\t\tBN_free(tmp_1);\n"); - BIO_printf(out, "\tif (tmp_2)\n\t\tBN_free(tmp_2);\n"); - BIO_printf(out, "\tif (tmp_3)\n\t\tBN_free(tmp_3);\n"); - BIO_printf(out, "\tif (point)\n\t\tEC_POINT_free(point);\n"); - BIO_printf(out, "\tif (!ok)\n"); - BIO_printf(out, "\t\t{\n"); - BIO_printf(out, "\t\tEC_GROUP_free(group);\n"); - BIO_printf(out, "\t\tgroup = NULL;\n"); - BIO_printf(out, "\t\t}\n"); - BIO_printf(out, "\treturn(group);\n\t}\n"); + BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n" + " goto err;\n" + "\n"); + BIO_printf(out, " /* build generator */\n"); + BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n"); + BIO_printf(out, " if (point == NULL)\n" + " goto err;\n"); + BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n" + " goto err;\n" + "ok = 1;" + "\n"); + BIO_printf(out, "err:\n" + " BN_free(tmp_1);\n" + " BN_free(tmp_2);\n" + " BN_free(tmp_3);\n" + " EC_POINT_free(point);\n" + " if (!ok) {\n" + " EC_GROUP_free(group);\n" + " return NULL;\n" + " }\n" + " return (group);\n" + "}\n"); } if (outformat == FORMAT_ASN1 && genkey) @@ -552,13 +390,8 @@ int MAIN(int argc, char **argv) if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_ECPKParameters_bio(out, group); - else if (outformat == FORMAT_PEM) + else i = PEM_write_bio_ECPKParameters(out, group); - else { - BIO_printf(bio_err, "bad output format specified for" - " outfile\n"); - goto end; - } if (!i) { BIO_printf(bio_err, "unable to write elliptic " "curve parameters\n"); @@ -567,101 +400,51 @@ int MAIN(int argc, char **argv) } } - if (need_rand) { - app_RAND_load_file(NULL, bio_err, (inrand != NULL)); - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - } - if (genkey) { EC_KEY *eckey = EC_KEY_new(); if (eckey == NULL) goto end; - assert(need_rand); - - if (EC_KEY_set_group(eckey, group) == 0) + if (EC_KEY_set_group(eckey, group) == 0) { + BIO_printf(bio_err, "unable to set group when generating key\n"); + EC_KEY_free(eckey); + ERR_print_errors(bio_err); goto end; + } if (new_form) EC_KEY_set_conv_form(eckey, form); if (!EC_KEY_generate_key(eckey)) { + BIO_printf(bio_err, "unable to generate key\n"); EC_KEY_free(eckey); + ERR_print_errors(bio_err); goto end; } + assert(private); if (outformat == FORMAT_ASN1) i = i2d_ECPrivateKey_bio(out, eckey); - else if (outformat == FORMAT_PEM) + else i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL); - else { - BIO_printf(bio_err, "bad output format specified " - "for outfile\n"); - EC_KEY_free(eckey); - goto end; - } EC_KEY_free(eckey); } - if (need_rand) - app_RAND_write_file(NULL, bio_err); - ret = 0; end: - if (ec_p) - BN_free(ec_p); - if (ec_a) - BN_free(ec_a); - if (ec_b) - BN_free(ec_b); - if (ec_gen) - BN_free(ec_gen); - if (ec_order) - BN_free(ec_order); - if (ec_cofactor) - BN_free(ec_cofactor); - if (buffer) - OPENSSL_free(buffer); - if (group != NULL) - EC_GROUP_free(group); + BN_free(ec_p); + BN_free(ec_a); + BN_free(ec_b); + BN_free(ec_gen); + BN_free(ec_order); + BN_free(ec_cofactor); + OPENSSL_free(buffer); + EC_GROUP_free(group); release_engine(e); - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - apps_shutdown(); - OPENSSL_EXIT(ret); + BIO_free(in); + BIO_free_all(out); + return ret; } -static int ecparam_print_var(BIO *out, BIGNUM *in, const char *var, - int len, unsigned char *buffer) -{ - BIO_printf(out, "static unsigned char %s_%d[] = {", var, len); - if (BN_is_zero(in)) - BIO_printf(out, "\n\t0x00"); - else { - int i, l; - - l = BN_bn2bin(in, buffer); - for (i = 0; i < l - 1; i++) { - if ((i % 12) == 0) - BIO_printf(out, "\n\t"); - BIO_printf(out, "0x%02X,", buffer[i]); - } - if ((i % 12) == 0) - BIO_printf(out, "\n\t"); - BIO_printf(out, "0x%02X", buffer[i]); - } - BIO_printf(out, "\n\t};\n\n"); - return 1; -} -#else /* !OPENSSL_NO_EC */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/enc.c b/apps/enc.c index 3b7e1eea3d83..8e5a57d3e5d7 100644 --- a/apps/enc.c +++ b/apps/enc.c @@ -1,65 +1,18 @@ -/* apps/enc.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <limits.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/evp.h> @@ -72,356 +25,309 @@ #endif #include <ctype.h> -int set_hex(char *in, unsigned char *out, int size); #undef SIZE #undef BSIZE -#undef PROG - #define SIZE (512) #define BSIZE (8*1024) -#define PROG enc_main + +static int set_hex(const char *in, unsigned char *out, int size); +static void show_ciphers(const OBJ_NAME *name, void *bio_); struct doall_enc_ciphers { BIO *bio; int n; }; -static void show_ciphers(const OBJ_NAME *name, void *arg) -{ - struct doall_enc_ciphers *dec = (struct doall_enc_ciphers *)arg; - const EVP_CIPHER *cipher; - - if (!islower((unsigned char)*name->name)) - return; - - /* Filter out ciphers that we cannot use */ - cipher = EVP_get_cipherbyname(name->name); - if (cipher == NULL || - (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 || - EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE) - return; - - BIO_printf(dec->bio, "-%-25s", name->name); - if (++dec->n == 3) { - BIO_printf(dec->bio, "\n"); - dec->n = 0; - } else - BIO_printf(dec->bio, " "); -} +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_LIST, + OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V, + OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A, + OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE, + OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS enc_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"ciphers", OPT_LIST, '-', "List ciphers"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"pass", OPT_PASS, 's', "Passphrase source"}, + {"e", OPT_E, '-', "Encrypt"}, + {"d", OPT_D, '-', "Decrypt"}, + {"p", OPT_P, '-', "Print the iv/key"}, + {"P", OPT_UPPER_P, '-', "Print the iv/key and exit"}, + {"v", OPT_V, '-', "Verbose output"}, + {"nopad", OPT_NOPAD, '-', "Disable standard block padding"}, + {"salt", OPT_SALT, '-', "Use salt in the KDF (default)"}, + {"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"}, + {"debug", OPT_DEBUG, '-', "Print debug info"}, + {"a", OPT_A, '-', "Base64 encode/decode, depending on encryption flag"}, + {"base64", OPT_A, '-', "Same as option -a"}, + {"A", OPT_UPPER_A, '-', + "Used with -[base64|a] to specify base64 buffer as a single line"}, + {"bufsize", OPT_BUFSIZE, 's', "Buffer size"}, + {"k", OPT_K, 's', "Passphrase"}, + {"kfile", OPT_KFILE, '<', "Read passphrase from file"}, + {"K", OPT_UPPER_K, 's', "Raw key, in hex"}, + {"S", OPT_UPPER_S, 's', "Salt, in hex"}, + {"iv", OPT_IV, 's', "IV in hex"}, + {"md", OPT_MD, 's', "Use specified digest to create a key from the passphrase"}, + {"iter", OPT_ITER, 'p', "Specify the iteration count and force use of PBKDF2"}, + {"pbkdf2", OPT_PBKDF2, '-', "Use password-based key derivation function 2"}, + {"none", OPT_NONE, '-', "Don't encrypt"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, + OPT_R_OPTIONS, +#ifdef ZLIB + {"z", OPT_Z, '-', "Use zlib as the 'encryption'"}, +#endif +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int enc_main(int argc, char **argv) { + static char buf[128]; static const char magic[] = "Salted__"; + ENGINE *e = NULL; + BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio = + NULL, *wbio = NULL; + EVP_CIPHER_CTX *ctx = NULL; + const EVP_CIPHER *cipher = NULL, *c; + const EVP_MD *dgst = NULL; + char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p; + char *infile = NULL, *outfile = NULL, *prog; + char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL; char mbuf[sizeof(magic) - 1]; - char *strbuf = NULL; - unsigned char *buff = NULL, *bufsize = NULL; - int bsize = BSIZE, verbose = 0; - int ret = 1, inl; - int nopad = 0; + OPTION_CHOICE o; + int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0; + int enc = 1, printkey = 0, i, k; + int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY; + int ret = 1, inl, nopad = 0; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; - unsigned char salt[PKCS5_SALT_LEN]; - char *str = NULL, *passarg = NULL, *pass = NULL; - char *hkey = NULL, *hiv = NULL, *hsalt = NULL; - char *md = NULL; - int enc = 1, printkey = 0, i, base64 = 0; + unsigned char *buff = NULL, salt[PKCS5_SALT_LEN]; + int pbkdf2 = 0; + int iter = 0; + long n; + struct doall_enc_ciphers dec; #ifdef ZLIB int do_zlib = 0; BIO *bzl = NULL; #endif - int debug = 0, olb64 = 0, nosalt = 0; - const EVP_CIPHER *cipher = NULL, *c; - EVP_CIPHER_CTX *ctx = NULL; - char *inf = NULL, *outf = NULL; - BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio = - NULL, *wbio = NULL; -#define PROG_NAME_SIZE 39 - char pname[PROG_NAME_SIZE + 1]; - char *engine = NULL; - ENGINE *e = NULL; - const EVP_MD *dgst = NULL; - int non_fips_allow = 0; - struct doall_enc_ciphers dec; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; /* first check the program name */ - program_name(argv[0], pname, sizeof(pname)); - if (strcmp(pname, "base64") == 0) + prog = opt_progname(argv[0]); + if (strcmp(prog, "base64") == 0) { base64 = 1; #ifdef ZLIB - if (strcmp(pname, "zlib") == 0) + } else if (strcmp(prog, "zlib") == 0) { do_zlib = 1; #endif - - cipher = EVP_get_cipherbyname(pname); -#ifdef ZLIB - if (!do_zlib && !base64 && (cipher == NULL) - && (strcmp(pname, "enc") != 0)) -#else - if (!base64 && (cipher == NULL) && (strcmp(pname, "enc") != 0)) -#endif - { - BIO_printf(bio_err, "%s is an unknown cipher\n", pname); - goto bad; + } else { + cipher = EVP_get_cipherbyname(prog); + if (cipher == NULL && strcmp(prog, "enc") != 0) { + BIO_printf(bio_err, "%s is not a known cipher\n", prog); + goto end; + } } - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-e") == 0) + prog = opt_init(argc, argv, enc_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(enc_options); + ret = 0; + goto end; + case OPT_LIST: + BIO_printf(bio_out, "Supported ciphers:\n"); + dec.bio = bio_out; + dec.n = 0; + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, + show_ciphers, &dec); + BIO_printf(bio_out, "\n"); + ret = 0; + goto end; + case OPT_E: enc = 1; - else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - inf = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outf = *(++argv); - } else if (strcmp(*argv, "-pass") == 0) { - if (--argc < 1) - goto bad; - passarg = *(++argv); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -#endif - else if (strcmp(*argv, "-d") == 0) + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_D: enc = 0; - else if (strcmp(*argv, "-p") == 0) + break; + case OPT_P: printkey = 1; - else if (strcmp(*argv, "-v") == 0) + break; + case OPT_V: verbose = 1; - else if (strcmp(*argv, "-nopad") == 0) + break; + case OPT_NOPAD: nopad = 1; - else if (strcmp(*argv, "-salt") == 0) + break; + case OPT_SALT: nosalt = 0; - else if (strcmp(*argv, "-nosalt") == 0) + break; + case OPT_NOSALT: nosalt = 1; - else if (strcmp(*argv, "-debug") == 0) + break; + case OPT_DEBUG: debug = 1; - else if (strcmp(*argv, "-P") == 0) + break; + case OPT_UPPER_P: printkey = 2; - else if (strcmp(*argv, "-A") == 0) + break; + case OPT_UPPER_A: olb64 = 1; - else if (strcmp(*argv, "-a") == 0) - base64 = 1; - else if (strcmp(*argv, "-base64") == 0) + break; + case OPT_A: base64 = 1; + break; + case OPT_Z: #ifdef ZLIB - else if (strcmp(*argv, "-z") == 0) do_zlib = 1; #endif - else if (strcmp(*argv, "-bufsize") == 0) { - if (--argc < 1) - goto bad; - bufsize = (unsigned char *)*(++argv); - } else if (strcmp(*argv, "-k") == 0) { - if (--argc < 1) - goto bad; - str = *(++argv); - } else if (strcmp(*argv, "-kfile") == 0) { - static char buf[128]; - FILE *infile; - char *file; - - if (--argc < 1) - goto bad; - file = *(++argv); - infile = fopen(file, "r"); - if (infile == NULL) { - BIO_printf(bio_err, "unable to read key from '%s'\n", file); - goto bad; - } - buf[0] = '\0'; - if (!fgets(buf, sizeof(buf), infile)) { - BIO_printf(bio_err, "unable to read key from '%s'\n", file); - goto bad; + break; + case OPT_BUFSIZE: + p = opt_arg(); + i = (int)strlen(p) - 1; + k = i >= 1 && p[i] == 'k'; + if (k) + p[i] = '\0'; + if (!opt_long(opt_arg(), &n) + || n < 0 || (k && n >= LONG_MAX / 1024)) + goto opthelp; + if (k) + n *= 1024; + bsize = (int)n; + break; + case OPT_K: + str = opt_arg(); + break; + case OPT_KFILE: + in = bio_open_default(opt_arg(), 'r', FORMAT_TEXT); + if (in == NULL) + goto opthelp; + i = BIO_gets(in, buf, sizeof(buf)); + BIO_free(in); + in = NULL; + if (i <= 0) { + BIO_printf(bio_err, + "%s Can't read key from %s\n", prog, opt_arg()); + goto opthelp; } - fclose(infile); - i = strlen(buf); - if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r'))) - buf[--i] = '\0'; - if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r'))) - buf[--i] = '\0'; - if (i < 1) { - BIO_printf(bio_err, "zero length password\n"); - goto bad; + while (--i > 0 && (buf[i] == '\r' || buf[i] == '\n')) + buf[i] = '\0'; + if (i <= 0) { + BIO_printf(bio_err, "%s: zero length password\n", prog); + goto opthelp; } str = buf; - } else if (strcmp(*argv, "-K") == 0) { - if (--argc < 1) - goto bad; - hkey = *(++argv); - } else if (strcmp(*argv, "-S") == 0) { - if (--argc < 1) - goto bad; - hsalt = *(++argv); - } else if (strcmp(*argv, "-iv") == 0) { - if (--argc < 1) - goto bad; - hiv = *(++argv); - } else if (strcmp(*argv, "-md") == 0) { - if (--argc < 1) - goto bad; - md = *(++argv); - } else if (strcmp(*argv, "-non-fips-allow") == 0) - non_fips_allow = 1; - else if ((argv[0][0] == '-') && - ((c = EVP_get_cipherbyname(&(argv[0][1]))) != NULL)) { + break; + case OPT_UPPER_K: + hkey = opt_arg(); + break; + case OPT_UPPER_S: + hsalt = opt_arg(); + break; + case OPT_IV: + hiv = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_arg(), &dgst)) + goto opthelp; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &c)) + goto opthelp; cipher = c; - } else if (strcmp(*argv, "-none") == 0) + break; + case OPT_ITER: + if (!opt_int(opt_arg(), &iter)) + goto opthelp; + pbkdf2 = 1; + break; + case OPT_PBKDF2: + pbkdf2 = 1; + if (iter == 0) /* do not overwrite a chosen value */ + iter = 10000; + break; + case OPT_NONE: cipher = NULL; - else { - BIO_printf(bio_err, "unknown option '%s'\n", *argv); - bad: - BIO_printf(bio_err, "options are\n"); - BIO_printf(bio_err, "%-14s input file\n", "-in <file>"); - BIO_printf(bio_err, "%-14s output file\n", "-out <file>"); - BIO_printf(bio_err, "%-14s pass phrase source\n", "-pass <arg>"); - BIO_printf(bio_err, "%-14s encrypt\n", "-e"); - BIO_printf(bio_err, "%-14s decrypt\n", "-d"); - BIO_printf(bio_err, - "%-14s base64 encode/decode, depending on encryption flag\n", - "-a/-base64"); - BIO_printf(bio_err, "%-14s passphrase is the next argument\n", - "-k"); - BIO_printf(bio_err, - "%-14s passphrase is the first line of the file argument\n", - "-kfile"); - BIO_printf(bio_err, - "%-14s the next argument is the md to use to create a key\n", - "-md"); - BIO_printf(bio_err, - "%-14s from a passphrase. One of md2, md5, sha or sha1\n", - ""); - BIO_printf(bio_err, "%-14s salt in hex is the next argument\n", - "-S"); - BIO_printf(bio_err, "%-14s key/iv in hex is the next argument\n", - "-K/-iv"); - BIO_printf(bio_err, "%-14s print the iv/key (then exit if -P)\n", - "-[pP]"); - BIO_printf(bio_err, "%-14s buffer size\n", "-bufsize <n>"); - BIO_printf(bio_err, "%-14s disable standard block padding\n", - "-nopad"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "%-14s use engine e, possibly a hardware device.\n", - "-engine e"); -#endif - - BIO_printf(bio_err, "Cipher Types\n"); - dec.n = 0; - dec.bio = bio_err; - OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, - show_ciphers, &dec); - BIO_printf(bio_err, "\n"); - - goto end; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; } - argc--; - argv++; } - - e = setup_engine(bio_err, engine, 0); + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) { - BIO_printf(bio_err, - "AEAD ciphers not supported by the enc utility\n"); + BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog); goto end; } if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) { - BIO_printf(bio_err, - "Ciphers in XTS mode are not supported by the enc utility\n"); + BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog); goto end; } - if (md && (dgst = EVP_get_digestbyname(md)) == NULL) { - BIO_printf(bio_err, "%s is an unsupported message digest type\n", md); - goto end; - } + if (dgst == NULL) + dgst = EVP_sha256(); - if (dgst == NULL) { - dgst = EVP_md5(); - } + if (iter == 0) + iter = 1; - if (bufsize != NULL) { - unsigned long n; + /* It must be large enough for a base64 encoded line */ + if (base64 && bsize < 80) + bsize = 80; + if (verbose) + BIO_printf(bio_err, "bufsize=%d\n", bsize); - for (n = 0; *bufsize; bufsize++) { - i = *bufsize; - if ((i <= '9') && (i >= '0')) - n = n * 10 + i - '0'; - else if (i == 'k') { - n *= 1024; - bufsize++; - break; - } - } - if (*bufsize != '\0') { - BIO_printf(bio_err, "invalid 'bufsize' specified.\n"); - goto end; +#ifdef ZLIB + if (!do_zlib) +#endif + if (base64) { + if (enc) + outformat = FORMAT_BASE64; + else + informat = FORMAT_BASE64; } - /* It must be large enough for a base64 encoded line */ - if (base64 && n < 80) - n = 80; - - bsize = (int)n; - if (verbose) - BIO_printf(bio_err, "bufsize=%d\n", bsize); - } - - strbuf = OPENSSL_malloc(SIZE); - buff = (unsigned char *)OPENSSL_malloc(EVP_ENCODE_LENGTH(bsize)); - if ((buff == NULL) || (strbuf == NULL)) { - BIO_printf(bio_err, "OPENSSL_malloc failure %ld\n", - (long)EVP_ENCODE_LENGTH(bsize)); - goto end; - } + strbuf = app_malloc(SIZE, "strbuf"); + buff = app_malloc(EVP_ENCODE_LENGTH(bsize), "evp buffer"); - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); - goto end; - } - if (debug) { - BIO_set_callback(in, BIO_debug_callback); - BIO_set_callback(out, BIO_debug_callback); - BIO_set_callback_arg(in, (char *)bio_err); - BIO_set_callback_arg(out, (char *)bio_err); - } - - if (inf == NULL) { -#ifndef OPENSSL_NO_SETVBUF_IONBF - if (bufsize != NULL) - setvbuf(stdin, (char *)NULL, _IONBF, 0); -#endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ - BIO_set_fp(in, stdin, BIO_NOCLOSE); + if (infile == NULL) { + in = dup_bio_in(informat); } else { - if (BIO_read_filename(in, inf) <= 0) { - perror(inf); - goto end; - } + in = bio_open_default(infile, 'r', informat); } + if (in == NULL) + goto end; - if (!str && passarg) { - if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { + if (str == NULL && passarg != NULL) { + if (!app_passwd(passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } @@ -429,56 +335,58 @@ int MAIN(int argc, char **argv) } if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) { - for (;;) { - char buf[200]; + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + for (;;) { + char prompt[200]; - BIO_snprintf(buf, sizeof(buf), "enter %s %s password:", - OBJ_nid2ln(EVP_CIPHER_nid(cipher)), - (enc) ? "encryption" : "decryption"); - strbuf[0] = '\0'; - i = EVP_read_pw_string((char *)strbuf, SIZE, buf, enc); - if (i == 0) { - if (strbuf[0] == '\0') { - ret = 1; + BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:", + OBJ_nid2ln(EVP_CIPHER_nid(cipher)), + (enc) ? "encryption" : "decryption"); + strbuf[0] = '\0'; + i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc); + if (i == 0) { + if (strbuf[0] == '\0') { + ret = 1; + goto end; + } + str = strbuf; + break; + } + if (i < 0) { + BIO_printf(bio_err, "bad password read\n"); goto end; } - str = strbuf; - break; - } - if (i < 0) { - BIO_printf(bio_err, "bad password read\n"); - goto end; } - } - } - - if (outf == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifndef OPENSSL_NO_SETVBUF_IONBF - if (bufsize != NULL) - setvbuf(stdout, (char *)NULL, _IONBF, 0); -#endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } + } else { #endif - } else { - if (BIO_write_filename(out, outf) <= 0) { - perror(outf); + BIO_printf(bio_err, "password required\n"); goto end; } } + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (debug) { + BIO_set_callback(in, BIO_debug_callback); + BIO_set_callback(out, BIO_debug_callback); + BIO_set_callback_arg(in, (char *)bio_err); + BIO_set_callback_arg(out, (char *)bio_err); + } + rbio = in; wbio = out; #ifdef ZLIB - if (do_zlib) { if ((bzl = BIO_new(BIO_f_zlib())) == NULL) goto end; + if (debug) { + BIO_set_callback(bzl, BIO_debug_callback); + BIO_set_callback_arg(bzl, (char *)bio_err); + } if (enc) wbio = BIO_push(bzl, wbio); else @@ -512,17 +420,20 @@ int MAIN(int argc, char **argv) * output BIO. If decrypting read salt from input BIO. */ unsigned char *sptr; - if (nosalt) + size_t str_len = strlen(str); + + if (nosalt) { sptr = NULL; - else { + } else { if (enc) { if (hsalt) { if (!set_hex(hsalt, salt, sizeof(salt))) { BIO_printf(bio_err, "invalid hex salt value\n"); goto end; } - } else if (RAND_bytes(salt, sizeof(salt)) <= 0) + } else if (RAND_bytes(salt, sizeof(salt)) <= 0) { goto end; + } /* * If -P option then don't bother writing */ @@ -545,26 +456,52 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "bad magic number\n"); goto end; } - sptr = salt; } - EVP_BytesToKey(cipher, dgst, sptr, - (unsigned char *)str, strlen(str), 1, key, iv); + if (pbkdf2 == 1) { + /* + * derive key and default iv + * concatenated into a temporary buffer + */ + unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH]; + int iklen = EVP_CIPHER_key_length(cipher); + int ivlen = EVP_CIPHER_iv_length(cipher); + /* not needed if HASH_UPDATE() is fixed : */ + int islen = (sptr != NULL ? sizeof(salt) : 0); + if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen, + iter, dgst, iklen+ivlen, tmpkeyiv)) { + BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n"); + goto end; + } + /* split and move data back to global buffer */ + memcpy(key, tmpkeyiv, iklen); + memcpy(iv, tmpkeyiv+iklen, ivlen); + } else { + BIO_printf(bio_err, "*** WARNING : " + "deprecated key derivation used.\n" + "Using -iter or -pbkdf2 would be better.\n"); + if (!EVP_BytesToKey(cipher, dgst, sptr, + (unsigned char *)str, str_len, + 1, key, iv)) { + BIO_printf(bio_err, "EVP_BytesToKey failed\n"); + goto end; + } + } /* * zero the complete buffer or the string passed from the command - * line bug picked up by Larry J. Hughes Jr. <hughes@indiana.edu> + * line. */ if (str == strbuf) OPENSSL_cleanse(str, SIZE); else - OPENSSL_cleanse(str, strlen(str)); + OPENSSL_cleanse(str, str_len); } if (hiv != NULL) { int siz = EVP_CIPHER_iv_length(cipher); if (siz == 0) { BIO_printf(bio_err, "warning: iv not use by this cipher\n"); - } else if (!set_hex(hiv, iv, sizeof(iv))) { + } else if (!set_hex(hiv, iv, siz)) { BIO_printf(bio_err, "invalid hex iv value\n"); goto end; } @@ -572,16 +509,19 @@ int MAIN(int argc, char **argv) if ((hiv == NULL) && (str == NULL) && EVP_CIPHER_iv_length(cipher) != 0) { /* - * No IV was explicitly set and no IV was generated during - * EVP_BytesToKey. Hence the IV is undefined, making correct - * decryption impossible. + * No IV was explicitly set and no IV was generated. + * Hence the IV is undefined, making correct decryption impossible. */ BIO_printf(bio_err, "iv undefined\n"); goto end; } - if ((hkey != NULL) && !set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) { - BIO_printf(bio_err, "invalid hex key value\n"); - goto end; + if (hkey != NULL) { + if (!set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) { + BIO_printf(bio_err, "invalid hex key value\n"); + goto end; + } + /* wiping secret data as we no longer need it */ + OPENSSL_cleanse(hkey, strlen(hkey)); } if ((benc = BIO_new(BIO_f_cipher())) == NULL) @@ -594,9 +534,6 @@ int MAIN(int argc, char **argv) BIO_get_cipher_ctx(benc, &ctx); - if (non_fips_allow) - EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW); - if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", EVP_CIPHER_name(cipher)); @@ -626,15 +563,15 @@ int MAIN(int argc, char **argv) printf("%02X", salt[i]); printf("\n"); } - if (cipher->key_len > 0) { + if (EVP_CIPHER_key_length(cipher) > 0) { printf("key="); - for (i = 0; i < cipher->key_len; i++) + for (i = 0; i < EVP_CIPHER_key_length(cipher); i++) printf("%02X", key[i]); printf("\n"); } - if (cipher->iv_len > 0) { + if (EVP_CIPHER_iv_length(cipher) > 0) { printf("iv ="); - for (i = 0; i < cipher->iv_len; i++) + for (i = 0; i < EVP_CIPHER_iv_length(cipher); i++) printf("%02X", iv[i]); printf("\n"); } @@ -665,64 +602,74 @@ int MAIN(int argc, char **argv) ret = 0; if (verbose) { - BIO_printf(bio_err, "bytes read :%8ld\n", BIO_number_read(in)); - BIO_printf(bio_err, "bytes written:%8ld\n", BIO_number_written(out)); + BIO_printf(bio_err, "bytes read : %8ju\n", BIO_number_read(in)); + BIO_printf(bio_err, "bytes written: %8ju\n", BIO_number_written(out)); } end: ERR_print_errors(bio_err); - if (strbuf != NULL) - OPENSSL_free(strbuf); - if (buff != NULL) - OPENSSL_free(buff); - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (benc != NULL) - BIO_free(benc); - if (b64 != NULL) - BIO_free(b64); + OPENSSL_free(strbuf); + OPENSSL_free(buff); + BIO_free(in); + BIO_free_all(out); + BIO_free(benc); + BIO_free(b64); #ifdef ZLIB - if (bzl != NULL) - BIO_free(bzl); + BIO_free(bzl); #endif release_engine(e); - if (pass) - OPENSSL_free(pass); - apps_shutdown(); - OPENSSL_EXIT(ret); + OPENSSL_free(pass); + return ret; } -int set_hex(char *in, unsigned char *out, int size) +static void show_ciphers(const OBJ_NAME *name, void *arg) +{ + struct doall_enc_ciphers *dec = (struct doall_enc_ciphers *)arg; + const EVP_CIPHER *cipher; + + if (!islower((unsigned char)*name->name)) + return; + + /* Filter out ciphers that we cannot use */ + cipher = EVP_get_cipherbyname(name->name); + if (cipher == NULL || + (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 || + EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE) + return; + + BIO_printf(dec->bio, "-%-25s", name->name); + if (++dec->n == 3) { + BIO_printf(dec->bio, "\n"); + dec->n = 0; + } else + BIO_printf(dec->bio, " "); +} + +static int set_hex(const char *in, unsigned char *out, int size) { int i, n; unsigned char j; + i = size * 2; n = strlen(in); - if (n > (size * 2)) { - BIO_printf(bio_err, "hex string is too long\n"); - return (0); + if (n > i) { + BIO_printf(bio_err, "hex string is too long, ignoring excess\n"); + n = i; /* ignore exceeding part */ + } else if (n < i) { + BIO_printf(bio_err, "hex string is too short, padding with zero bytes to length\n"); } + memset(out, 0, size); for (i = 0; i < n; i++) { - j = (unsigned char)*in; - *(in++) = '\0'; - if (j == 0) - break; - if ((j >= '0') && (j <= '9')) - j -= '0'; - else if ((j >= 'A') && (j <= 'F')) - j = j - 'A' + 10; - else if ((j >= 'a') && (j <= 'f')) - j = j - 'a' + 10; - else { + j = (unsigned char)*in++; + if (!isxdigit(j)) { BIO_printf(bio_err, "non-hex digit\n"); - return (0); + return 0; } + j = (unsigned char)OPENSSL_hexchar2int(j); if (i & 1) out[i / 2] |= j; else out[i / 2] = (j << 4); } - return (1); + return 1; } diff --git a/apps/engine.c b/apps/engine.c index a8eed9af5c18..83f9588a0ab1 100644 --- a/apps/engine.c +++ b/apps/engine.c @@ -1,137 +1,96 @@ -/* apps/engine.c */ /* - * Written by Richard Levitte <richard@levitte.org> for the OpenSSL project - * 2000. - */ -/* ==================================================================== - * Copyright (c) 2000 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -#endif -#include "apps.h" -#include <openssl/err.h> -#ifndef OPENSSL_NO_ENGINE +#include <openssl/opensslconf.h> +#ifdef OPENSSL_NO_ENGINE +NON_EMPTY_TRANSLATION_UNIT +#else + +# include "apps.h" +# include "progs.h" +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# include <openssl/err.h> # include <openssl/engine.h> # include <openssl/ssl.h> +# include <openssl/store.h> -# undef PROG -# define PROG engine_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST, + OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV +} OPTION_CHOICE; -static const char *engine_usage[] = { - "usage: engine opts [engine ...]\n", - " -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n", - " -vv will additionally display each command's description\n", - " -vvv will also add the input flags for each command\n", - " -vvvv will also show internal input flags\n", - " -c - for each engine, also list the capabilities\n", - " -t[t] - for each engine, check that they are really available\n", - " -tt will display error trace for unavailable engines\n", - " -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n", - " to load it (if -t is used)\n", - " -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n", - " (only used if -t is also provided)\n", - " NB: -pre and -post will be applied to all ENGINEs supplied on the command\n", - " line, or all supported ENGINEs if none are specified.\n", - " Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n", - " argument \"/lib/libdriver.so\".\n", - NULL +const OPTIONS engine_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"}, + {OPT_HELP_STR, 1, '-', + " engine... Engines to load\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"v", OPT_V, '-', "List 'control commands' For each specified engine"}, + {"vv", OPT_VV, '-', "Also display each command's description"}, + {"vvv", OPT_VVV, '-', "Also add the input flags for each command"}, + {"vvvv", OPT_VVVV, '-', "Also show internal input flags"}, + {"c", OPT_C, '-', "List the capabilities of specified engine"}, + {"t", OPT_T, '-', "Check that specified engine is available"}, + {"tt", OPT_TT, '-', "Display error trace for unavailable engines"}, + {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"}, + {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"}, + {OPT_MORE_STR, OPT_EOF, 1, + "Commands are like \"SO_PATH:/lib/libdriver.so\""}, + {NULL} }; -static void identity(char *ptr) +static int append_buf(char **buf, int *size, const char *s) { - return; -} + const int expand = 256; + int len = strlen(s) + 1; + char *p = *buf; -static int append_buf(char **buf, const char *s, int *size, int step) -{ - if (*buf == NULL) { - *size = step; - *buf = OPENSSL_malloc(*size); - if (*buf == NULL) - return 0; - **buf = '\0'; - } + if (p == NULL) { + *size = ((len + expand - 1) / expand) * expand; + p = *buf = app_malloc(*size, "engine buffer"); + } else { + const int blen = strlen(p); - if (strlen(*buf) + strlen(s) >= (unsigned int)*size) { - char *p = *buf; + if (blen > 0) + len += 2 + blen; - *size += step; - *buf = OPENSSL_realloc(*buf, *size); - if (*buf == NULL) { - OPENSSL_free(p); - return 0; + if (len > *size) { + *size = ((len + expand - 1) / expand) * expand; + p = OPENSSL_realloc(p, *size); + if (p == NULL) { + OPENSSL_free(*buf); + *buf = NULL; + return 0; + } + *buf = p; } - } - if (**buf != '\0') - BUF_strlcat(*buf, ", ", *size); - BUF_strlcat(*buf, s, *size); + if (blen > 0) { + p += blen; + *p++ = ','; + *p++ = ' '; + } + } + strcpy(p, s); return 1; } -static int util_flags(BIO *bio_out, unsigned int flags, const char *indent) +static int util_flags(BIO *out, unsigned int flags, const char *indent) { int started = 0, err = 0; /* Indent before displaying input flags */ - BIO_printf(bio_out, "%s%s(input flags): ", indent, indent); + BIO_printf(out, "%s%s(input flags): ", indent, indent); if (flags == 0) { - BIO_printf(bio_out, "<no flags>\n"); + BIO_printf(out, "<no flags>\n"); return 1; } /* @@ -139,11 +98,11 @@ static int util_flags(BIO *bio_out, unsigned int flags, const char *indent) * having it part of all the other flags, even if it really is. */ if (flags & ENGINE_CMD_FLAG_INTERNAL) { - BIO_printf(bio_out, "[Internal] "); + BIO_printf(out, "[Internal] "); } if (flags & ENGINE_CMD_FLAG_NUMERIC) { - BIO_printf(bio_out, "NUMERIC"); + BIO_printf(out, "NUMERIC"); started = 1; } /* @@ -154,18 +113,18 @@ static int util_flags(BIO *bio_out, unsigned int flags, const char *indent) */ if (flags & ENGINE_CMD_FLAG_STRING) { if (started) { - BIO_printf(bio_out, "|"); + BIO_printf(out, "|"); err = 1; } - BIO_printf(bio_out, "STRING"); + BIO_printf(out, "STRING"); started = 1; } if (flags & ENGINE_CMD_FLAG_NO_INPUT) { if (started) { - BIO_printf(bio_out, "|"); + BIO_printf(out, "|"); err = 1; } - BIO_printf(bio_out, "NO_INPUT"); + BIO_printf(out, "NO_INPUT"); started = 1; } /* Check for unknown flags */ @@ -174,17 +133,16 @@ static int util_flags(BIO *bio_out, unsigned int flags, const char *indent) ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL; if (flags) { if (started) - BIO_printf(bio_out, "|"); - BIO_printf(bio_out, "<0x%04X>", flags); + BIO_printf(out, "|"); + BIO_printf(out, "<0x%04X>", flags); } if (err) - BIO_printf(bio_out, " <illegal flags!>"); - BIO_printf(bio_out, "\n"); + BIO_printf(out, " <illegal flags!>"); + BIO_printf(out, "\n"); return 1; } -static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, - const char *indent) +static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent) { static const int line_wrap = 78; int num; @@ -197,16 +155,13 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, 0, NULL, NULL)) <= 0)) { -# if 0 - BIO_printf(bio_out, "%s<no control commands>\n", indent); -# endif return 1; } cmds = sk_OPENSSL_STRING_new_null(); - - if (!cmds) + if (cmds == NULL) goto err; + do { int len; /* Get the command input flags */ @@ -218,8 +173,7 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, NULL, NULL)) <= 0) goto err; - if ((name = OPENSSL_malloc(len + 1)) == NULL) - goto err; + name = app_malloc(len + 1, "name buffer"); if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, NULL) <= 0) goto err; @@ -228,8 +182,7 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, NULL, NULL)) < 0) goto err; if (len > 0) { - if ((desc = OPENSSL_malloc(len + 1)) == NULL) - goto err; + desc = app_malloc(len + 1, "description buffer"); if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, NULL) <= 0) goto err; @@ -237,59 +190,54 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, /* Now decide on the output */ if (xpos == 0) /* Do an indent */ - xpos = BIO_puts(bio_out, indent); + xpos = BIO_puts(out, indent); else /* Otherwise prepend a ", " */ - xpos += BIO_printf(bio_out, ", "); + xpos += BIO_printf(out, ", "); if (verbose == 1) { /* * We're just listing names, comma-delimited */ if ((xpos > (int)strlen(indent)) && (xpos + (int)strlen(name) > line_wrap)) { - BIO_printf(bio_out, "\n"); - xpos = BIO_puts(bio_out, indent); + BIO_printf(out, "\n"); + xpos = BIO_puts(out, indent); } - xpos += BIO_printf(bio_out, "%s", name); + xpos += BIO_printf(out, "%s", name); } else { /* We're listing names plus descriptions */ - BIO_printf(bio_out, "%s: %s\n", name, + BIO_printf(out, "%s: %s\n", name, (desc == NULL) ? "<no description>" : desc); /* ... and sometimes input flags */ - if ((verbose >= 3) && !util_flags(bio_out, flags, indent)) + if ((verbose >= 3) && !util_flags(out, flags, indent)) goto err; xpos = 0; } } OPENSSL_free(name); name = NULL; - if (desc) { - OPENSSL_free(desc); - desc = NULL; - } + OPENSSL_free(desc); + desc = NULL; /* Move to the next command */ num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL); } while (num > 0); if (xpos > 0) - BIO_printf(bio_out, "\n"); + BIO_printf(out, "\n"); ret = 1; err: - if (cmds) - sk_OPENSSL_STRING_pop_free(cmds, identity); - if (name) - OPENSSL_free(name); - if (desc) - OPENSSL_free(desc); + sk_OPENSSL_STRING_free(cmds); + OPENSSL_free(name); + OPENSSL_free(desc); return ret; } static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, - BIO *bio_out, const char *indent) + BIO *out, const char *indent) { int loop, res, num = sk_OPENSSL_STRING_num(cmds); if (num < 0) { - BIO_printf(bio_out, "[Error]: internal stack error\n"); + BIO_printf(out, "[Error]: internal stack error\n"); return; } for (loop = 0; loop < num; loop++) { @@ -303,7 +251,7 @@ static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, res = 0; } else { if ((int)(arg - cmd) > 254) { - BIO_printf(bio_out, "[Error]: command name too long\n"); + BIO_printf(out, "[Error]: command name too long\n"); return; } memcpy(buf, cmd, (int)(arg - cmd)); @@ -313,109 +261,131 @@ static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) res = 0; } - if (res) - BIO_printf(bio_out, "[Success]: %s\n", cmd); - else { - BIO_printf(bio_out, "[Failure]: %s\n", cmd); - ERR_print_errors(bio_out); + if (res) { + BIO_printf(out, "[Success]: %s\n", cmd); + } else { + BIO_printf(out, "[Failure]: %s\n", cmd); + ERR_print_errors(out); } } } -int MAIN(int, char **); +struct util_store_cap_data { + ENGINE *engine; + char **cap_buf; + int *cap_size; + int ok; +}; +static void util_store_cap(const OSSL_STORE_LOADER *loader, void *arg) +{ + struct util_store_cap_data *ctx = arg; -int MAIN(int argc, char **argv) + if (OSSL_STORE_LOADER_get0_engine(loader) == ctx->engine) { + char buf[256]; + BIO_snprintf(buf, sizeof(buf), "STORE(%s)", + OSSL_STORE_LOADER_get0_scheme(loader)); + if (!append_buf(ctx->cap_buf, ctx->cap_size, buf)) + ctx->ok = 0; + } +} + +int engine_main(int argc, char **argv) { int ret = 1, i; - const char **pp; int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0; ENGINE *e; - STACK_OF(OPENSSL_STRING) *engines = sk_OPENSSL_STRING_new_null(); + STACK_OF(OPENSSL_CSTRING) *engines = sk_OPENSSL_CSTRING_new_null(); STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null(); STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null(); - int badops = 1; - BIO *bio_out = NULL; + BIO *out; const char *indent = " "; + OPTION_CHOICE o; + char *prog; + char *argv1; - apps_startup(); - SSL_load_error_strings(); - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) + out = dup_bio_out(FORMAT_TEXT); + if (engines == NULL || pre_cmds == NULL || post_cmds == NULL) goto end; - bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - bio_out = BIO_push(tmpbio, bio_out); - } -# endif - argc--; - argv++; - while (argc >= 1) { - if (strncmp(*argv, "-v", 2) == 0) { - if (strspn(*argv + 1, "v") < strlen(*argv + 1)) - goto skip_arg_loop; - if ((verbose = strlen(*argv + 1)) > 4) - goto skip_arg_loop; - } else if (strcmp(*argv, "-c") == 0) - list_cap = 1; - else if (strncmp(*argv, "-t", 2) == 0) { - test_avail = 1; - if (strspn(*argv + 1, "t") < strlen(*argv + 1)) - goto skip_arg_loop; - if ((test_avail_noise = strlen(*argv + 1) - 1) > 1) - goto skip_arg_loop; - } else if (strcmp(*argv, "-pre") == 0) { - argc--; - argv++; - if (argc == 0) - goto skip_arg_loop; - sk_OPENSSL_STRING_push(pre_cmds, *argv); - } else if (strcmp(*argv, "-post") == 0) { - argc--; - argv++; - if (argc == 0) - goto skip_arg_loop; - sk_OPENSSL_STRING_push(post_cmds, *argv); - } else if ((strncmp(*argv, "-h", 2) == 0) || - (strcmp(*argv, "-?") == 0)) - goto skip_arg_loop; - else - sk_OPENSSL_STRING_push(engines, *argv); + /* Remember the original command name, parse/skip any leading engine + * names, and then setup to parse the rest of the line as flags. */ + prog = argv[0]; + while ((argv1 = argv[1]) != NULL && *argv1 != '-') { + sk_OPENSSL_CSTRING_push(engines, argv1); argc--; argv++; } - /* Looks like everything went OK */ - badops = 0; - skip_arg_loop: + argv[0] = prog; + opt_init(argc, argv, engine_options); - if (badops) { - for (pp = engine_usage; (*pp != NULL); pp++) - BIO_printf(bio_err, "%s", *pp); - goto end; + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(engine_options); + ret = 0; + goto end; + case OPT_VVVV: + case OPT_VVV: + case OPT_VV: + case OPT_V: + /* Convert to an integer from one to four. */ + i = (int)(o - OPT_V) + 1; + if (verbose < i) + verbose = i; + break; + case OPT_C: + list_cap = 1; + break; + case OPT_TT: + test_avail_noise++; + /* fall thru */ + case OPT_T: + test_avail++; + break; + case OPT_PRE: + sk_OPENSSL_STRING_push(pre_cmds, opt_arg()); + break; + case OPT_POST: + sk_OPENSSL_STRING_push(post_cmds, opt_arg()); + break; + } + } + + /* Allow any trailing parameters as engine names. */ + argc = opt_num_rest(); + argv = opt_rest(); + for ( ; *argv; argv++) { + if (**argv == '-') { + BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n", + prog); + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + } + sk_OPENSSL_CSTRING_push(engines, *argv); } - if (sk_OPENSSL_STRING_num(engines) == 0) { + if (sk_OPENSSL_CSTRING_num(engines) == 0) { for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { - sk_OPENSSL_STRING_push(engines, (char *)ENGINE_get_id(e)); + sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e)); } } - for (i = 0; i < sk_OPENSSL_STRING_num(engines); i++) { - const char *id = sk_OPENSSL_STRING_value(engines, i); + ret = 0; + for (i = 0; i < sk_OPENSSL_CSTRING_num(engines); i++) { + const char *id = sk_OPENSSL_CSTRING_value(engines, i); if ((e = ENGINE_by_id(id)) != NULL) { const char *name = ENGINE_get_name(e); /* * Do "id" first, then "name". Easier to auto-parse. */ - BIO_printf(bio_out, "(%s) %s\n", id, name); - util_do_cmds(e, pre_cmds, bio_out, indent); + BIO_printf(out, "(%s) %s\n", id, name); + util_do_cmds(e, pre_cmds, out, indent); if (strcmp(ENGINE_get_id(e), id) != 0) { - BIO_printf(bio_out, "Loaded: (%s) %s\n", + BIO_printf(out, "Loaded: (%s) %s\n", ENGINE_get_id(e), ENGINE_get_name(e)); } if (list_cap) { @@ -428,88 +398,92 @@ int MAIN(int argc, char **argv) ENGINE_PKEY_METHS_PTR fn_pk; if (ENGINE_get_RSA(e) != NULL - && !append_buf(&cap_buf, "RSA", &cap_size, 256)) + && !append_buf(&cap_buf, &cap_size, "RSA")) goto end; if (ENGINE_get_DSA(e) != NULL - && !append_buf(&cap_buf, "DSA", &cap_size, 256)) + && !append_buf(&cap_buf, &cap_size, "DSA")) goto end; if (ENGINE_get_DH(e) != NULL - && !append_buf(&cap_buf, "DH", &cap_size, 256)) + && !append_buf(&cap_buf, &cap_size, "DH")) goto end; if (ENGINE_get_RAND(e) != NULL - && !append_buf(&cap_buf, "RAND", &cap_size, 256)) + && !append_buf(&cap_buf, &cap_size, "RAND")) goto end; fn_c = ENGINE_get_ciphers(e); - if (!fn_c) + if (fn_c == NULL) goto skip_ciphers; n = fn_c(e, NULL, &nids, 0); for (k = 0; k < n; ++k) - if (!append_buf(&cap_buf, - OBJ_nid2sn(nids[k]), &cap_size, 256)) + if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) goto end; skip_ciphers: fn_d = ENGINE_get_digests(e); - if (!fn_d) + if (fn_d == NULL) goto skip_digests; n = fn_d(e, NULL, &nids, 0); for (k = 0; k < n; ++k) - if (!append_buf(&cap_buf, - OBJ_nid2sn(nids[k]), &cap_size, 256)) + if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) goto end; skip_digests: fn_pk = ENGINE_get_pkey_meths(e); - if (!fn_pk) + if (fn_pk == NULL) goto skip_pmeths; n = fn_pk(e, NULL, &nids, 0); for (k = 0; k < n; ++k) - if (!append_buf(&cap_buf, - OBJ_nid2sn(nids[k]), &cap_size, 256)) + if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) goto end; skip_pmeths: - if (cap_buf && (*cap_buf != '\0')) - BIO_printf(bio_out, " [%s]\n", cap_buf); + { + struct util_store_cap_data store_ctx; + + store_ctx.engine = e; + store_ctx.cap_buf = &cap_buf; + store_ctx.cap_size = &cap_size; + store_ctx.ok = 1; + + OSSL_STORE_do_all_loaders(util_store_cap, &store_ctx); + if (!store_ctx.ok) + goto end; + } + if (cap_buf != NULL && (*cap_buf != '\0')) + BIO_printf(out, " [%s]\n", cap_buf); OPENSSL_free(cap_buf); } if (test_avail) { - BIO_printf(bio_out, "%s", indent); + BIO_printf(out, "%s", indent); if (ENGINE_init(e)) { - BIO_printf(bio_out, "[ available ]\n"); - util_do_cmds(e, post_cmds, bio_out, indent); + BIO_printf(out, "[ available ]\n"); + util_do_cmds(e, post_cmds, out, indent); ENGINE_finish(e); } else { - BIO_printf(bio_out, "[ unavailable ]\n"); + BIO_printf(out, "[ unavailable ]\n"); if (test_avail_noise) ERR_print_errors_fp(stdout); ERR_clear_error(); } } - if ((verbose > 0) && !util_verbose(e, verbose, bio_out, indent)) + if ((verbose > 0) && !util_verbose(e, verbose, out, indent)) goto end; ENGINE_free(e); - } else + } else { ERR_print_errors(bio_err); + /* because exit codes above 127 have special meaning on Unix */ + if (++ret > 127) + ret = 127; + } } - ret = 0; end: ERR_print_errors(bio_err); - sk_OPENSSL_STRING_pop_free(engines, identity); - sk_OPENSSL_STRING_pop_free(pre_cmds, identity); - sk_OPENSSL_STRING_pop_free(post_cmds, identity); - if (bio_out != NULL) - BIO_free_all(bio_out); - apps_shutdown(); - OPENSSL_EXIT(ret); + sk_OPENSSL_CSTRING_free(engines); + sk_OPENSSL_STRING_free(pre_cmds); + sk_OPENSSL_STRING_free(post_cmds); + BIO_free_all(out); + return ret; } -#else - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/errstr.c b/apps/errstr.c index c3fef610fc2d..3ef01f076a8c 100644 --- a/apps/errstr.c +++ b/apps/errstr.c @@ -1,121 +1,67 @@ -/* apps/errstr.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> -#include <openssl/lhash.h> #include <openssl/err.h> #include <openssl/ssl.h> -#undef PROG -#define PROG errstr_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS errstr_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] errnum...\n"}, + {OPT_HELP_STR, 1, '-', " errnum Error number\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int errstr_main(int argc, char **argv) { - int i, ret = 0; - char buf[256]; + OPTION_CHOICE o; + char buf[256], *prog; + int ret = 1; unsigned long l; - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - SSL_load_error_strings(); - - if ((argc > 1) && (strcmp(argv[1], "-stats") == 0)) { - BIO *out = NULL; - - out = BIO_new(BIO_s_file()); - if ((out != NULL) && BIO_set_fp(out, stdout, BIO_NOCLOSE)) { -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - lh_ERR_STRING_DATA_node_stats_bio(ERR_get_string_table(), out); - lh_ERR_STRING_DATA_stats_bio(ERR_get_string_table(), out); - lh_ERR_STRING_DATA_node_usage_stats_bio(ERR_get_string_table(), - out); + prog = opt_init(argc, argv, errstr_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(errstr_options); + ret = 0; + goto end; } - if (out != NULL) - BIO_free_all(out); - argc--; - argv++; } - for (i = 1; i < argc; i++) { - if (sscanf(argv[i], "%lx", &l)) { - ERR_error_string_n(l, buf, sizeof(buf)); - printf("%s\n", buf); - } else { - printf("%s: bad error code\n", argv[i]); - printf("usage: errstr [-stats] <errno> ...\n"); + ret = 0; + for (argv = opt_rest(); *argv; argv++) { + if (sscanf(*argv, "%lx", &l) == 0) { ret++; + } else { + /* We're not really an SSL application so this won't auto-init, but + * we're still interested in SSL error strings + */ + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS + | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_error_string_n(l, buf, sizeof(buf)); + BIO_printf(bio_out, "%s\n", buf); } } - apps_shutdown(); - OPENSSL_EXIT(ret); + end: + return ret; } diff --git a/apps/gendh.c b/apps/gendh.c deleted file mode 100644 index 59484c244601..000000000000 --- a/apps/gendh.c +++ /dev/null @@ -1,244 +0,0 @@ -/* apps/gendh.c */ -/* obsoleted by dhparam.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include <openssl/opensslconf.h> -/* - * Until the key-gen callbacks are modified to use newer prototypes, we allow - * deprecated functions for openssl-internal code - */ -#ifdef OPENSSL_NO_DEPRECATED -# undef OPENSSL_NO_DEPRECATED -#endif - -#ifndef OPENSSL_NO_DH -# include <stdio.h> -# include <string.h> -# include <sys/types.h> -# include <sys/stat.h> -# include "apps.h" -# include <openssl/bio.h> -# include <openssl/rand.h> -# include <openssl/err.h> -# include <openssl/bn.h> -# include <openssl/dh.h> -# include <openssl/x509.h> -# include <openssl/pem.h> - -# define DEFBITS 2048 -# undef PROG -# define PROG gendh_main - -static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb); - -int MAIN(int, char **); - -int MAIN(int argc, char **argv) -{ - BN_GENCB cb; - DH *dh = NULL; - int ret = 1, num = DEFBITS; - int g = 2; - char *outfile = NULL; - char *inrand = NULL; - char *engine = NULL; - BIO *out = NULL; - - apps_startup(); - - BN_GENCB_set(&cb, dh_cb, bio_err); - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - argv++; - argc--; - for (;;) { - if (argc <= 0) - break; - if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-2") == 0) - g = 2; -/*- else if (strcmp(*argv,"-3") == 0) - g=3; */ - else if (strcmp(*argv, "-5") == 0) - g = 5; -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -# endif - else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - } else - break; - argv++; - argc--; - } - if ((argc >= 1) && ((sscanf(*argv, "%d", &num) == 0) || (num < 0))) { - bad: - BIO_printf(bio_err, "usage: gendh [args] [numbits]\n"); - BIO_printf(bio_err, " -out file - output the key to 'file\n"); - BIO_printf(bio_err, " -2 - use 2 as the generator value\n"); - /* - * BIO_printf(bio_err," -3 - use 3 as the generator value\n"); - */ - BIO_printf(bio_err, " -5 - use 5 as the generator value\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e - use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " - load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - goto end; - } - setup_engine(bio_err, engine, 0); - - out = BIO_new(BIO_s_file()); - if (out == NULL) { - ERR_print_errors(bio_err); - goto end; - } - - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } - - if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) { - BIO_printf(bio_err, - "warning, not much extra random data, consider using the -rand option\n"); - } - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - - BIO_printf(bio_err, - "Generating DH parameters, %d bit long safe prime, generator %d\n", - num, g); - BIO_printf(bio_err, "This is going to take a long time\n"); - - if (((dh = DH_new()) == NULL) - || !DH_generate_parameters_ex(dh, num, g, &cb)) - goto end; - - app_RAND_write_file(NULL, bio_err); - - if (!PEM_write_bio_DHparams(out, dh)) - goto end; - ret = 0; - end: - if (ret != 0) - ERR_print_errors(bio_err); - if (out != NULL) - BIO_free_all(out); - if (dh != NULL) - DH_free(dh); - apps_shutdown(); - OPENSSL_EXIT(ret); -} - -static int MS_CALLBACK dh_cb(int p, int n, BN_GENCB *cb) -{ - char c = '*'; - - if (p == 0) - c = '.'; - if (p == 1) - c = '+'; - if (p == 2) - c = '*'; - if (p == 3) - c = '\n'; - BIO_write(cb->arg, &c, 1); - (void)BIO_flush(cb->arg); -# ifdef LINT - p = n; -# endif - return 1; -} -#else /* !OPENSSL_NO_DH */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - -#endif diff --git a/apps/gendsa.c b/apps/gendsa.c index 31510e6123d7..401375420bff 100644 --- a/apps/gendsa.c +++ b/apps/gendsa.c @@ -1,68 +1,23 @@ -/* apps/gendsa.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <openssl/opensslconf.h> /* for OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DSA +#include <openssl/opensslconf.h> +#ifdef OPENSSL_NO_DSA +NON_EMPTY_TRANSLATION_UNIT +#else + # include <stdio.h> # include <string.h> # include <sys/types.h> # include <sys/stat.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/bn.h> @@ -70,153 +25,85 @@ # include <openssl/x509.h> # include <openssl/pem.h> -# define DEFBITS 512 -# undef PROG -# define PROG gendsa_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS gendsa_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [args] dsaparam-file\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output the key to the specified file"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + OPT_R_OPTIONS, + {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; -int MAIN(int argc, char **argv) +int gendsa_main(int argc, char **argv) { - DSA *dsa = NULL; - int ret = 1; - char *outfile = NULL; - char *inrand = NULL, *dsaparams = NULL; - char *passargout = NULL, *passout = NULL; + ENGINE *e = NULL; BIO *out = NULL, *in = NULL; + DSA *dsa = NULL; const EVP_CIPHER *enc = NULL; - char *engine = NULL; - ENGINE *e = NULL; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; + char *dsaparams = NULL; + char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog; + OPTION_CHOICE o; + int ret = 1, private = 0; + const BIGNUM *p = NULL; - argv++; - argc--; - for (;;) { - if (argc <= 0) + prog = opt_init(argc, argv, gendsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(gendsa_options); + goto end; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto end; break; - if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-passout") == 0) { - if (--argc < 1) - goto bad; - passargout = *(++argv); - } -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); } -# endif - else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - } else if (strcmp(*argv, "-") == 0) - goto bad; -# ifndef OPENSSL_NO_DES - else if (strcmp(*argv, "-des") == 0) - enc = EVP_des_cbc(); - else if (strcmp(*argv, "-des3") == 0) - enc = EVP_des_ede3_cbc(); -# endif -# ifndef OPENSSL_NO_IDEA - else if (strcmp(*argv, "-idea") == 0) - enc = EVP_idea_cbc(); -# endif -# ifndef OPENSSL_NO_SEED - else if (strcmp(*argv, "-seed") == 0) - enc = EVP_seed_cbc(); -# endif -# ifndef OPENSSL_NO_AES - else if (strcmp(*argv, "-aes128") == 0) - enc = EVP_aes_128_cbc(); - else if (strcmp(*argv, "-aes192") == 0) - enc = EVP_aes_192_cbc(); - else if (strcmp(*argv, "-aes256") == 0) - enc = EVP_aes_256_cbc(); -# endif -# ifndef OPENSSL_NO_CAMELLIA - else if (strcmp(*argv, "-camellia128") == 0) - enc = EVP_camellia_128_cbc(); - else if (strcmp(*argv, "-camellia192") == 0) - enc = EVP_camellia_192_cbc(); - else if (strcmp(*argv, "-camellia256") == 0) - enc = EVP_camellia_256_cbc(); -# endif - else if (**argv != '-' && dsaparams == NULL) { - dsaparams = *argv; - } else - goto bad; - argv++; - argc--; } + argc = opt_num_rest(); + argv = opt_rest(); + private = 1; - if (dsaparams == NULL) { - bad: - BIO_printf(bio_err, "usage: gendsa [args] dsaparam-file\n"); - BIO_printf(bio_err, " -out file - output the key to 'file'\n"); -# ifndef OPENSSL_NO_DES - BIO_printf(bio_err, - " -des - encrypt the generated key with DES in cbc mode\n"); - BIO_printf(bio_err, - " -des3 - encrypt the generated key with DES in ede cbc mode (168 bit key)\n"); -# endif -# ifndef OPENSSL_NO_IDEA - BIO_printf(bio_err, - " -idea - encrypt the generated key with IDEA in cbc mode\n"); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, " -seed\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc seed\n"); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, " -aes128, -aes192, -aes256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc aes\n"); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, " -camellia128, -camellia192, -camellia256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc camellia\n"); -# endif -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e - use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " - load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - BIO_printf(bio_err, " dsaparam-file\n"); - BIO_printf(bio_err, - " - a DSA parameter file as generated by the dsaparam command\n"); - goto end; - } - e = setup_engine(bio_err, engine, 0); + if (argc != 1) + goto opthelp; + dsaparams = *argv; - if (!app_passwd(bio_err, NULL, passargout, NULL, &passout)) { + if (!app_passwd(NULL, passoutarg, NULL, &passout)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } - in = BIO_new(BIO_s_file()); - if (!(BIO_read_filename(in, dsaparams))) { - perror(dsaparams); - goto end; - } + in = bio_open_default(dsaparams, 'r', FORMAT_PEM); + if (in == NULL) + goto end2; if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) { BIO_printf(bio_err, "unable to load DSA parameter file\n"); @@ -225,61 +112,35 @@ int MAIN(int argc, char **argv) BIO_free(in); in = NULL; - out = BIO_new(BIO_s_file()); + out = bio_open_owner(outfile, FORMAT_PEM, private); if (out == NULL) - goto end; + goto end2; - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } + DSA_get0_pqg(dsa, &p, NULL, NULL); - if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) { + if (BN_num_bits(p) > OPENSSL_DSA_MAX_MODULUS_BITS) BIO_printf(bio_err, - "warning, not much extra random data, consider using the -rand option\n"); - } - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); + "Warning: It is not recommended to use more than %d bit for DSA keys.\n" + " Your key size is %d! Larger key size may behave not as expected.\n", + OPENSSL_DSA_MAX_MODULUS_BITS, BN_num_bits(p)); - BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(dsa->p)); + BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p)); if (!DSA_generate_key(dsa)) goto end; - app_RAND_write_file(NULL, bio_err); - + assert(private); if (!PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout)) goto end; ret = 0; end: if (ret != 0) ERR_print_errors(bio_err); - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - if (dsa != NULL) - DSA_free(dsa); + end2: + BIO_free(in); + BIO_free_all(out); + DSA_free(dsa); release_engine(e); - if (passout) - OPENSSL_free(passout); - apps_shutdown(); - OPENSSL_EXIT(ret); + OPENSSL_free(passout); + return ret; } -#else /* !OPENSSL_NO_DSA */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/genpkey.c b/apps/genpkey.c index 39dcef9ca0c9..39fa73c91cf4 100644 --- a/apps/genpkey.c +++ b/apps/genpkey.c @@ -1,64 +1,16 @@ -/* apps/genpkey.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2006 - */ -/* ==================================================================== - * Copyright (c) 2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ + #include <stdio.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/evp.h> @@ -66,159 +18,134 @@ # include <openssl/engine.h> #endif -static int init_keygen_file(BIO *err, EVP_PKEY_CTX **pctx, - const char *file, ENGINE *e); +static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e); static int genpkey_cb(EVP_PKEY_CTX *ctx); -#define PROG genpkey_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE, + OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS genpkey_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"}, + {"pass", OPT_PASS, 's', "Output file pass phrase source"}, + {"paramfile", OPT_PARAMFILE, '<', "Parameters file"}, + {"algorithm", OPT_ALGORITHM, 's', "The public key algorithm"}, + {"pkeyopt", OPT_PKEYOPT, 's', + "Set the public key algorithm option as opt:value"}, + {"genparam", OPT_GENPARAM, '-', "Generate parameters, not key"}, + {"text", OPT_TEXT, '-', "Print the in text"}, + {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + /* This is deliberately last. */ + {OPT_HELP_STR, 1, 1, + "Order of options may be important! See the documentation.\n"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int genpkey_main(int argc, char **argv) { - ENGINE *e = NULL; - char **args, *outfile = NULL; - char *passarg = NULL; BIO *in = NULL, *out = NULL; - const EVP_CIPHER *cipher = NULL; - int outformat; - int text = 0; + ENGINE *e = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; - char *pass = NULL; - int badarg = 0; - int ret = 1, rv; - - int do_param = 0; - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - - outformat = FORMAT_PEM; + char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog; + const EVP_CIPHER *cipher = NULL; + OPTION_CHOICE o; + int outformat = FORMAT_PEM, text = 0, ret = 1, rv, do_param = 0; + int private = 0; - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - args = argv + 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-outform")) { - if (args[1]) { - args++; - outformat = str2fmt(*args); - } else - badarg = 1; - } else if (!strcmp(*args, "-pass")) { - if (!args[1]) - goto bad; - passarg = *(++args); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*args, "-engine") == 0) { - if (!args[1]) - goto bad; - e = setup_engine(bio_err, *(++args), 0); - } -#endif - else if (!strcmp(*args, "-paramfile")) { - if (!args[1]) - goto bad; - args++; + prog = opt_init(argc, argv, genpkey_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(genpkey_options); + goto end; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PARAMFILE: if (do_param == 1) - goto bad; - if (!init_keygen_file(bio_err, &ctx, *args, e)) + goto opthelp; + if (!init_keygen_file(&ctx, opt_arg(), e)) goto end; - } else if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } else if (strcmp(*args, "-algorithm") == 0) { - if (!args[1]) - goto bad; - if (!init_gen_str(bio_err, &ctx, *(++args), e, do_param)) + break; + case OPT_ALGORITHM: + if (!init_gen_str(&ctx, opt_arg(), e, do_param)) goto end; - } else if (strcmp(*args, "-pkeyopt") == 0) { - if (!args[1]) - goto bad; - if (!ctx) { - BIO_puts(bio_err, "No keytype specified\n"); - goto bad; - } else if (pkey_ctrl_string(ctx, *(++args)) <= 0) { - BIO_puts(bio_err, "parameter setting error\n"); + break; + case OPT_PKEYOPT: + if (ctx == NULL) { + BIO_printf(bio_err, "%s: No keytype specified.\n", prog); + goto opthelp; + } + if (pkey_ctrl_string(ctx, opt_arg()) <= 0) { + BIO_printf(bio_err, + "%s: Error setting %s parameter:\n", + prog, opt_arg()); ERR_print_errors(bio_err); goto end; } - } else if (strcmp(*args, "-genparam") == 0) { - if (ctx) - goto bad; + break; + case OPT_GENPARAM: + if (ctx != NULL) + goto opthelp; do_param = 1; - } else if (strcmp(*args, "-text") == 0) + break; + case OPT_TEXT: text = 1; - else { - cipher = EVP_get_cipherbyname(*args + 1); - if (!cipher) { - BIO_printf(bio_err, "Unknown cipher %s\n", *args + 1); - badarg = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &cipher) + || do_param == 1) + goto opthelp; + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE || + EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE || + EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE || + EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE) { + BIO_printf(bio_err, "%s: cipher mode not supported\n", prog); + goto end; } - if (do_param == 1) - badarg = 1; } - args++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (!ctx) - badarg = 1; + private = do_param ? 0 : 1; - if (badarg) { - bad: - BIO_printf(bio_err, "Usage: genpkey [options]\n"); - BIO_printf(bio_err, "where options may be\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, - "-outform X output format (DER or PEM)\n"); - BIO_printf(bio_err, - "-pass arg output file pass phrase source\n"); - BIO_printf(bio_err, - "-<cipher> use cipher <cipher> to encrypt the key\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); -#endif - BIO_printf(bio_err, "-paramfile file parameters file\n"); - BIO_printf(bio_err, "-algorithm alg the public key algorithm\n"); - BIO_printf(bio_err, - "-pkeyopt opt:value set the public key algorithm option <opt>\n" - " to value <value>\n"); - BIO_printf(bio_err, - "-genparam generate parameters, not key\n"); - BIO_printf(bio_err, "-text print the in text\n"); - BIO_printf(bio_err, - "NB: options order may be important! See the manual page.\n"); - goto end; - } + if (ctx == NULL) + goto opthelp; - if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { + if (!app_passwd(passarg, NULL, &pass, NULL)) { BIO_puts(bio_err, "Error getting password\n"); goto end; } - if (outfile) { - if (!(out = BIO_new_file(outfile, "wb"))) { - BIO_printf(bio_err, "Can't open output file %s\n", outfile); - goto end; - } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); @@ -237,13 +164,15 @@ int MAIN(int argc, char **argv) } } - if (do_param) + if (do_param) { rv = PEM_write_bio_Parameters(out, pkey); - else if (outformat == FORMAT_PEM) + } else if (outformat == FORMAT_PEM) { + assert(private); rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass); - else if (outformat == FORMAT_ASN1) + } else if (outformat == FORMAT_ASN1) { + assert(private); rv = i2d_PrivateKey_bio(out, pkey); - else { + } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } @@ -268,33 +197,28 @@ int MAIN(int argc, char **argv) ret = 0; end: - if (pkey) - EVP_PKEY_free(pkey); - if (ctx) - EVP_PKEY_CTX_free(ctx); - if (out) - BIO_free_all(out); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + BIO_free_all(out); BIO_free(in); release_engine(e); - if (pass) - OPENSSL_free(pass); + OPENSSL_free(pass); return ret; } -static int init_keygen_file(BIO *err, EVP_PKEY_CTX **pctx, - const char *file, ENGINE *e) +static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e) { BIO *pbio; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; if (*pctx) { - BIO_puts(err, "Parameters already set!\n"); + BIO_puts(bio_err, "Parameters already set!\n"); return 0; } pbio = BIO_new_file(file, "r"); if (!pbio) { - BIO_printf(err, "Can't open parameter file %s\n", file); + BIO_printf(bio_err, "Can't open parameter file %s\n", file); return 0; } @@ -307,7 +231,7 @@ static int init_keygen_file(BIO *err, EVP_PKEY_CTX **pctx, } ctx = EVP_PKEY_CTX_new(pkey, e); - if (!ctx) + if (ctx == NULL) goto err; if (EVP_PKEY_keygen_init(ctx) <= 0) goto err; @@ -316,17 +240,15 @@ static int init_keygen_file(BIO *err, EVP_PKEY_CTX **pctx, return 1; err: - BIO_puts(err, "Error initializing context\n"); - ERR_print_errors(err); - if (ctx) - EVP_PKEY_CTX_free(ctx); - if (pkey) - EVP_PKEY_free(pkey); + BIO_puts(bio_err, "Error initializing context\n"); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); return 0; } -int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx, +int init_gen_str(EVP_PKEY_CTX **pctx, const char *algname, ENGINE *e, int do_param) { EVP_PKEY_CTX *ctx = NULL; @@ -335,7 +257,7 @@ int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx, int pkey_id; if (*pctx) { - BIO_puts(err, "Algorithm already set!\n"); + BIO_puts(bio_err, "Algorithm already set!\n"); return 0; } @@ -355,8 +277,7 @@ int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx, EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); #ifndef OPENSSL_NO_ENGINE - if (tmpeng) - ENGINE_finish(tmpeng); + ENGINE_finish(tmpeng); #endif ctx = EVP_PKEY_CTX_new_id(pkey_id, e); @@ -374,10 +295,9 @@ int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx, return 1; err: - BIO_printf(err, "Error initializing %s context\n", algname); - ERR_print_errors(err); - if (ctx) - EVP_PKEY_CTX_free(ctx); + BIO_printf(bio_err, "Error initializing %s context\n", algname); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(ctx); return 0; } @@ -398,8 +318,5 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx) c = '\n'; BIO_write(b, &c, 1); (void)BIO_flush(b); -#ifdef LINT - p = n; -#endif return 1; } diff --git a/apps/genrsa.c b/apps/genrsa.c index 51dcfcaea071..c17cd147154e 100644 --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -1,76 +1,23 @@ -/* apps/genrsa.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <openssl/opensslconf.h> -/* - * Until the key-gen callbacks are modified to use newer prototypes, we allow - * deprecated functions for openssl-internal code - */ -#ifdef OPENSSL_NO_DEPRECATED -# undef OPENSSL_NO_DEPRECATED -#endif +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else -#ifndef OPENSSL_NO_RSA # include <stdio.h> # include <string.h> # include <sys/types.h> # include <sys/stat.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/bn.h> @@ -81,243 +28,161 @@ # include <openssl/rand.h> # define DEFBITS 2048 -# undef PROG -# define PROG genrsa_main +# define DEFPRIMES 2 + +static int genrsa_cb(int p, int n, BN_GENCB *cb); -static int MS_CALLBACK genrsa_cb(int p, int n, BN_GENCB *cb); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_3, OPT_F4, OPT_ENGINE, + OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS genrsa_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"3", OPT_3, '-', "Use 3 for the E value"}, + {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, + {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, + {"out", OPT_OUT, '>', "Output the key to specified file"}, + OPT_R_OPTIONS, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {"primes", OPT_PRIMES, 'p', "Specify number of primes"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int genrsa_main(int argc, char **argv) { - BN_GENCB cb; - ENGINE *e = NULL; - int ret = 1; - int i, num = DEFBITS; - long l; - const EVP_CIPHER *enc = NULL; - unsigned long f4 = RSA_F4; - char *outfile = NULL; - char *passargout = NULL, *passout = NULL; - char *engine = NULL; - char *inrand = NULL; - BIO *out = NULL; + BN_GENCB *cb = BN_GENCB_new(); + PW_CB_DATA cb_data; + ENGINE *eng = NULL; BIGNUM *bn = BN_new(); + BIO *out = NULL; + const BIGNUM *e; RSA *rsa = NULL; + const EVP_CIPHER *enc = NULL; + int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES; + unsigned long f4 = RSA_F4; + char *outfile = NULL, *passoutarg = NULL, *passout = NULL; + char *prog, *hexe, *dece; + OPTION_CHOICE o; - if (!bn) - goto err; - - apps_startup(); - BN_GENCB_set(&cb, genrsa_cb, bio_err); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); + if (bn == NULL || cb == NULL) + goto end; - if (!load_config(bio_err, NULL)) - goto err; - if ((out = BIO_new(BIO_s_file())) == NULL) { - BIO_printf(bio_err, "unable to create BIO for output\n"); - goto err; - } + BN_GENCB_set(cb, genrsa_cb, bio_err); - argv++; - argc--; - for (;;) { - if (argc <= 0) - break; - if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-3") == 0) + prog = opt_init(argc, argv, genrsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(genrsa_options); + goto end; + case OPT_3: f4 = 3; - else if (strcmp(*argv, "-F4") == 0 || strcmp(*argv, "-f4") == 0) + break; + case OPT_F4: f4 = RSA_F4; -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -# endif - else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - } -# ifndef OPENSSL_NO_DES - else if (strcmp(*argv, "-des") == 0) - enc = EVP_des_cbc(); - else if (strcmp(*argv, "-des3") == 0) - enc = EVP_des_ede3_cbc(); -# endif -# ifndef OPENSSL_NO_IDEA - else if (strcmp(*argv, "-idea") == 0) - enc = EVP_idea_cbc(); -# endif -# ifndef OPENSSL_NO_SEED - else if (strcmp(*argv, "-seed") == 0) - enc = EVP_seed_cbc(); -# endif -# ifndef OPENSSL_NO_AES - else if (strcmp(*argv, "-aes128") == 0) - enc = EVP_aes_128_cbc(); - else if (strcmp(*argv, "-aes192") == 0) - enc = EVP_aes_192_cbc(); - else if (strcmp(*argv, "-aes256") == 0) - enc = EVP_aes_256_cbc(); -# endif -# ifndef OPENSSL_NO_CAMELLIA - else if (strcmp(*argv, "-camellia128") == 0) - enc = EVP_camellia_128_cbc(); - else if (strcmp(*argv, "-camellia192") == 0) - enc = EVP_camellia_192_cbc(); - else if (strcmp(*argv, "-camellia256") == 0) - enc = EVP_camellia_256_cbc(); -# endif - else if (strcmp(*argv, "-passout") == 0) { - if (--argc < 1) - goto bad; - passargout = *(++argv); - } else break; - argv++; - argc--; - } - if ((argc >= 1) && ((sscanf(*argv, "%d", &num) == 0) || (num < 0))) { - bad: - BIO_printf(bio_err, "usage: genrsa [args] [numbits]\n"); - BIO_printf(bio_err, - " -des encrypt the generated key with DES in cbc mode\n"); - BIO_printf(bio_err, - " -des3 encrypt the generated key with DES in ede cbc mode (168 bit key)\n"); -# ifndef OPENSSL_NO_IDEA - BIO_printf(bio_err, - " -idea encrypt the generated key with IDEA in cbc mode\n"); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, " -seed\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc seed\n"); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, " -aes128, -aes192, -aes256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc aes\n"); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, " -camellia128, -camellia192, -camellia256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc camellia\n"); -# endif - BIO_printf(bio_err, " -out file output the key to 'file\n"); - BIO_printf(bio_err, - " -passout arg output file pass phrase source\n"); - BIO_printf(bio_err, - " -f4 use F4 (0x10001) for the E value\n"); - BIO_printf(bio_err, " -3 use 3 for the E value\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - goto err; - } - - ERR_load_crypto_strings(); - - if (!app_passwd(bio_err, NULL, passargout, NULL, &passout)) { - BIO_printf(bio_err, "Error getting password\n"); - goto err; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + eng = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto end; + break; + case OPT_PRIMES: + if (!opt_int(opt_arg(), &primes)) + goto end; + break; + } } - e = setup_engine(bio_err, engine, 0); + argc = opt_num_rest(); + argv = opt_rest(); - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto err; - } + if (argc == 1) { + if (!opt_int(argv[0], &num) || num <= 0) + goto end; + if (num > OPENSSL_RSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for RSA keys.\n" + " Your key size is %d! Larger key size may behave not as expected.\n", + OPENSSL_RSA_MAX_MODULUS_BITS, num); + } else if (argc > 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; } - if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL - && !RAND_status()) { - BIO_printf(bio_err, - "warning, not much extra random data, consider using the -rand option\n"); + private = 1; + if (!app_passwd(NULL, passoutarg, NULL, &passout)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; } - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus\n", - num); -# ifdef OPENSSL_NO_ENGINE - rsa = RSA_new(); -# else - rsa = RSA_new_method(e); -# endif - if (!rsa) - goto err; + out = bio_open_owner(outfile, FORMAT_PEM, private); + if (out == NULL) + goto end; - if (!BN_set_word(bn, f4) || !RSA_generate_key_ex(rsa, num, bn, &cb)) - goto err; + BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n", + num, primes); + rsa = eng ? RSA_new_method(eng) : RSA_new(); + if (rsa == NULL) + goto end; - app_RAND_write_file(NULL, bio_err); + if (!BN_set_word(bn, f4) + || !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb)) + goto end; - /* - * We need to do the following for when the base number size is < long, - * esp windows 3.1 :-(. - */ - l = 0L; - for (i = 0; i < rsa->e->top; i++) { -# ifndef SIXTY_FOUR_BIT - l <<= BN_BITS4; - l <<= BN_BITS4; -# endif - l += rsa->e->d[i]; - } - BIO_printf(bio_err, "e is %ld (0x%lX)\n", l, l); - { - PW_CB_DATA cb_data; - cb_data.password = passout; - cb_data.prompt_info = outfile; - if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, - (pem_password_cb *)password_callback, - &cb_data)) - goto err; + RSA_get0_key(rsa, NULL, &e, NULL); + hexe = BN_bn2hex(e); + dece = BN_bn2dec(e); + if (hexe && dece) { + BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe); } + OPENSSL_free(hexe); + OPENSSL_free(dece); + cb_data.password = passout; + cb_data.prompt_info = outfile; + assert(private); + if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, + (pem_password_cb *)password_callback, + &cb_data)) + goto end; ret = 0; - err: - if (bn) - BN_free(bn); - if (rsa) - RSA_free(rsa); - if (out) - BIO_free_all(out); - release_engine(e); - if (passout) - OPENSSL_free(passout); + end: + BN_free(bn); + BN_GENCB_free(cb); + RSA_free(rsa); + BIO_free_all(out); + release_engine(eng); + OPENSSL_free(passout); if (ret != 0) ERR_print_errors(bio_err); - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } -static int MS_CALLBACK genrsa_cb(int p, int n, BN_GENCB *cb) +static int genrsa_cb(int p, int n, BN_GENCB *cb) { char c = '*'; @@ -329,17 +194,8 @@ static int MS_CALLBACK genrsa_cb(int p, int n, BN_GENCB *cb) c = '*'; if (p == 3) c = '\n'; - BIO_write(cb->arg, &c, 1); - (void)BIO_flush(cb->arg); -# ifdef LINT - p = n; -# endif + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void)BIO_flush(BN_GENCB_get_arg(cb)); return 1; } -#else /* !OPENSSL_NO_RSA */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/nseq.c b/apps/nseq.c index c3067385d2a0..a067c915926f 100644 --- a/apps/nseq.c +++ b/apps/nseq.c @@ -1,146 +1,88 @@ -/* nseq.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 1999. - */ -/* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/pem.h> #include <openssl/err.h> -#undef PROG -#define PROG nseq_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_TOSEQ, OPT_IN, OPT_OUT +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS nseq_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int nseq_main(int argc, char **argv) { - char **args, *infile = NULL, *outfile = NULL; BIO *in = NULL, *out = NULL; - int toseq = 0; X509 *x509 = NULL; NETSCAPE_CERT_SEQUENCE *seq = NULL; - int i, ret = 1; - int badarg = 0; - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - ERR_load_crypto_strings(); - args = argv + 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-toseq")) - toseq = 1; - else if (!strcmp(*args, "-in")) { - if (args[1]) { - args++; - infile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } else - badarg = 1; - args++; - } + OPTION_CHOICE o; + int toseq = 0, ret = 1, i; + char *infile = NULL, *outfile = NULL, *prog; - if (badarg) { - BIO_printf(bio_err, "Netscape certificate sequence utility\n"); - BIO_printf(bio_err, "Usage nseq [options]\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, "-toseq output NS Sequence file\n"); - OPENSSL_EXIT(1); - } - - if (infile) { - if (!(in = BIO_new_file(infile, "r"))) { - BIO_printf(bio_err, "Can't open input file %s\n", infile); + prog = opt_init(argc, argv, nseq_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; - } - } else - in = BIO_new_fp(stdin, BIO_NOCLOSE); - - if (outfile) { - if (!(out = BIO_new_file(outfile, "w"))) { - BIO_printf(bio_err, "Can't open output file %s\n", outfile); + case OPT_HELP: + ret = 0; + opt_help(nseq_options); goto end; + case OPT_TOSEQ: + toseq = 1; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + in = bio_open_default(infile, 'r', FORMAT_PEM); + if (in == NULL) + goto end; + out = bio_open_default(outfile, 'w', FORMAT_PEM); + if (out == NULL) + goto end; + if (toseq) { seq = NETSCAPE_CERT_SEQUENCE_new(); + if (seq == NULL) + goto end; seq->certs = sk_X509_new_null(); + if (seq->certs == NULL) + goto end; while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) sk_X509_push(seq->certs, x509); if (!sk_X509_num(seq->certs)) { - BIO_printf(bio_err, "Error reading certs file %s\n", infile); + BIO_printf(bio_err, "%s: Error reading certs file %s\n", + prog, infile); ERR_print_errors(bio_err); goto end; } @@ -149,8 +91,10 @@ int MAIN(int argc, char **argv) goto end; } - if (!(seq = PEM_read_bio_NETSCAPE_CERT_SEQUENCE(in, NULL, NULL, NULL))) { - BIO_printf(bio_err, "Error reading sequence file %s\n", infile); + seq = PEM_read_bio_NETSCAPE_CERT_SEQUENCE(in, NULL, NULL, NULL); + if (seq == NULL) { + BIO_printf(bio_err, "%s: Error reading sequence file %s\n", + prog, infile); ERR_print_errors(bio_err); goto end; } @@ -166,5 +110,5 @@ int MAIN(int argc, char **argv) BIO_free_all(out); NETSCAPE_CERT_SEQUENCE_free(seq); - OPENSSL_EXIT(ret); + return ret; } diff --git a/apps/ocsp.c b/apps/ocsp.c index 654eebcbfc15..eb822c2696eb 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -1,76 +1,32 @@ -/* ocsp.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2000. - */ -/* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#ifndef OPENSSL_NO_OCSP +#include <openssl/opensslconf.h> + +#ifdef OPENSSL_NO_OCSP +NON_EMPTY_TRANSLATION_UNIT +#else # ifdef OPENSSL_SYS_VMS # define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined * on OpenVMS */ # endif -# define USE_SOCKETS - # include <stdio.h> # include <stdlib.h> # include <string.h> # include <time.h> -# include "apps.h" /* needs to be included before the openssl - * headers! */ +# include <ctype.h> + +/* Needs to be included before the openssl headers */ +# include "apps.h" +# include "progs.h" +# include "internal/sockets.h" # include <openssl/e_os2.h> # include <openssl/crypto.h> # include <openssl/err.h> @@ -78,24 +34,27 @@ # include <openssl/evp.h> # include <openssl/bn.h> # include <openssl/x509v3.h> +# include <openssl/rand.h> -# if defined(NETWARE_CLIB) -# ifdef NETWARE_BSDSOCK -# include <sys/socket.h> -# include <sys/bsdskt.h> -# else -# include <novsock2.h> -# endif -# elif defined(NETWARE_LIBC) -# ifdef NETWARE_BSDSOCK -# include <sys/select.h> -# else -# include <novsock2.h> -# endif +# if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_NO_SOCK) \ + && !defined(OPENSSL_NO_POSIX_IO) +# define OCSP_DAEMON +# include <sys/types.h> +# include <sys/wait.h> +# include <syslog.h> +# include <signal.h> +# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */ +# else +# undef LOG_INFO +# undef LOG_WARNING +# undef LOG_ERR +# define LOG_INFO 0 +# define LOG_WARNING 1 +# define LOG_ERR 2 # endif /* Maximum leeway in validity period: default 5 minutes */ -# define MAX_VALIDITY_PERIOD (5 * 60) +# define MAX_VALIDITY_PERIOD (5 * 60) static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md, X509 *issuer, @@ -103,558 +62,542 @@ static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, const EVP_MD *cert_id_md, X509 *issuer, STACK_OF(OCSP_CERTID) *ids); -static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, +static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, STACK_OF(OPENSSL_STRING) *names, STACK_OF(OCSP_CERTID) *ids, long nsec, long maxage); - -static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, - CA_DB *db, X509 *ca, X509 *rcert, +static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req, + CA_DB *db, STACK_OF(X509) *ca, X509 *rcert, EVP_PKEY *rkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(X509) *rother, unsigned long flags, int nmin, int ndays, int badsig); static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser); static BIO *init_responder(const char *port); -static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, - const char *port); +static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, int timeout); static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp); -static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path, +static void log_message(int level, const char *fmt, ...); +static char *prog; +static int multi = 0; + +# ifdef OCSP_DAEMON +static int acfd = (int) INVALID_SOCKET; +static int index_changed(CA_DB *); +static void spawn_loop(void); +static int print_syslog(const char *str, size_t len, void *levPtr); +static void sock_timeout(int signum); +# endif + +# ifndef OPENSSL_NO_SOCK +static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host, + const char *path, const STACK_OF(CONF_VALUE) *headers, OCSP_REQUEST *req, int req_timeout); +# endif -# undef PROG -# define PROG ocsp_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT, + OPT_IGNORE_ERR, OPT_NOVERIFY, OPT_NONCE, OPT_NO_NONCE, + OPT_RESP_NO_CERTS, OPT_RESP_KEY_ID, OPT_NO_CERTS, + OPT_NO_SIGNATURE_VERIFY, OPT_NO_CERT_VERIFY, OPT_NO_CHAIN, + OPT_NO_CERT_CHECKS, OPT_NO_EXPLICIT, OPT_TRUST_OTHER, + OPT_NO_INTERN, OPT_BADSIG, OPT_TEXT, OPT_REQ_TEXT, OPT_RESP_TEXT, + OPT_REQIN, OPT_RESPIN, OPT_SIGNER, OPT_VAFILE, OPT_SIGN_OTHER, + OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, + OPT_VALIDITY_PERIOD, OPT_STATUS_AGE, OPT_SIGNKEY, OPT_REQOUT, + OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL, + OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER, + OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_RSIGOPT, OPT_HEADER, + OPT_V_ENUM, + OPT_MD, + OPT_MULTI +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS ocsp_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUTFILE, '>', "Output filename"}, + {"timeout", OPT_TIMEOUT, 'p', + "Connection timeout (in seconds) to the OCSP responder"}, + {"url", OPT_URL, 's', "Responder URL"}, + {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"}, + {"port", OPT_PORT, 'p', "Port to run responder on"}, + {"ignore_err", OPT_IGNORE_ERR, '-', + "Ignore error on OCSP request or response and continue running"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"}, + {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"}, + {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"}, + {"resp_no_certs", OPT_RESP_NO_CERTS, '-', + "Don't include any certificates in response"}, + {"resp_key_id", OPT_RESP_KEY_ID, '-', + "Identify response by signing certificate key ID"}, +# ifdef OCSP_DAEMON + {"multi", OPT_MULTI, 'p', "run multiple responder processes"}, +# endif + {"no_certs", OPT_NO_CERTS, '-', + "Don't include any certificates in signed request"}, + {"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-', + "Don't check signature on response"}, + {"no_cert_verify", OPT_NO_CERT_VERIFY, '-', + "Don't check signing certificate"}, + {"no_chain", OPT_NO_CHAIN, '-', "Don't chain verify response"}, + {"no_cert_checks", OPT_NO_CERT_CHECKS, '-', + "Don't do additional checks on signing certificate"}, + {"no_explicit", OPT_NO_EXPLICIT, '-', + "Do not explicitly check the chain, just verify the root"}, + {"trust_other", OPT_TRUST_OTHER, '-', + "Don't verify additional certificates"}, + {"no_intern", OPT_NO_INTERN, '-', + "Don't search certificates contained in response for signer"}, + {"badsig", OPT_BADSIG, '-', + "Corrupt last byte of loaded OSCP response signature (for test)"}, + {"text", OPT_TEXT, '-', "Print text form of request and response"}, + {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"}, + {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"}, + {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"}, + {"respin", OPT_RESPIN, 's', "File with the DER-encoded response"}, + {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"}, + {"VAfile", OPT_VAFILE, '<', "Validator certificates file"}, + {"sign_other", OPT_SIGN_OTHER, '<', + "Additional certificates to include in signed request"}, + {"verify_other", OPT_VERIFY_OTHER, '<', + "Additional certificates to search for signer"}, + {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"validity_period", OPT_VALIDITY_PERIOD, 'u', + "Maximum validity discrepancy in seconds"}, + {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"}, + {"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"}, + {"reqout", OPT_REQOUT, 's', "Output file for the DER-encoded request"}, + {"respout", OPT_RESPOUT, 's', "Output file for the DER-encoded response"}, + {"path", OPT_PATH, 's', "Path to use in OCSP request"}, + {"issuer", OPT_ISSUER, '<', "Issuer certificate"}, + {"cert", OPT_CERT, '<', "Certificate to check"}, + {"serial", OPT_SERIAL, 's', "Serial number to check"}, + {"index", OPT_INDEX, '<', "Certificate status index file"}, + {"CA", OPT_CA, '<', "CA certificate"}, + {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"}, + {"nrequest", OPT_REQUEST, 'p', + "Number of requests to accept (default unlimited)"}, + {"ndays", OPT_NDAYS, 'p', "Number of days before next update"}, + {"rsigner", OPT_RSIGNER, '<', + "Responder certificate to sign responses with"}, + {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"}, + {"rother", OPT_ROTHER, '<', "Other certificates to include in response"}, + {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"}, + {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"}, + {"header", OPT_HEADER, 's', "key=value header to add"}, + {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"}, + OPT_V_OPTIONS, + {NULL} +}; -int MAIN(int argc, char **argv) +int ocsp_main(int argc, char **argv) { - ENGINE *e = NULL; - char **args; - char *host = NULL, *port = NULL, *path = "/"; - char *thost = NULL, *tport = NULL, *tpath = NULL; - char *reqin = NULL, *respin = NULL; - char *reqout = NULL, *respout = NULL; - char *signfile = NULL, *keyfile = NULL; - char *rsignfile = NULL, *rkeyfile = NULL; - char *outfile = NULL; - int add_nonce = 1, noverify = 0, use_ssl = -1; - STACK_OF(CONF_VALUE) *headers = NULL; + BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL; + const EVP_MD *cert_id_md = NULL, *rsign_md = NULL; + STACK_OF(OPENSSL_STRING) *rsign_sigopts = NULL; + int trailing_md = 0; + CA_DB *rdb = NULL; + EVP_PKEY *key = NULL, *rkey = NULL; + OCSP_BASICRESP *bs = NULL; OCSP_REQUEST *req = NULL; OCSP_RESPONSE *resp = NULL; - OCSP_BASICRESP *bs = NULL; + STACK_OF(CONF_VALUE) *headers = NULL; + STACK_OF(OCSP_CERTID) *ids = NULL; + STACK_OF(OPENSSL_STRING) *reqnames = NULL; + STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL; + STACK_OF(X509) *issuers = NULL; X509 *issuer = NULL, *cert = NULL; + STACK_OF(X509) *rca_cert = NULL; X509 *signer = NULL, *rsigner = NULL; - EVP_PKEY *key = NULL, *rkey = NULL; - BIO *acbio = NULL, *cbio = NULL; - BIO *derbio = NULL; - BIO *out = NULL; - int req_timeout = -1; - int req_text = 0, resp_text = 0; - long nsec = MAX_VALIDITY_PERIOD, maxage = -1; - char *CAfile = NULL, *CApath = NULL; X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; - STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL; + const char *CAfile = NULL, *CApath = NULL; + char *header, *value; + char *host = NULL, *port = NULL, *path = "/", *outfile = NULL; + char *rca_filename = NULL, *reqin = NULL, *respin = NULL; + char *reqout = NULL, *respout = NULL, *ridx_filename = NULL; + char *rsignfile = NULL, *rkeyfile = NULL; char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL; + char *signfile = NULL, *keyfile = NULL; + char *thost = NULL, *tport = NULL, *tpath = NULL; + int noCAfile = 0, noCApath = 0; + int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1; + int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1; + int req_text = 0, resp_text = 0, ret = 1; + int req_timeout = -1; + long nsec = MAX_VALIDITY_PERIOD, maxage = -1; unsigned long sign_flags = 0, verify_flags = 0, rflags = 0; - int ret = 1; - int accept_count = -1; - int badarg = 0; - int badsig = 0; - int i; - int ignore_err = 0; - STACK_OF(OPENSSL_STRING) *reqnames = NULL; - STACK_OF(OCSP_CERTID) *ids = NULL; - - X509 *rca_cert = NULL; - char *ridx_filename = NULL; - char *rca_filename = NULL; - CA_DB *rdb = NULL; - int nmin = 0, ndays = -1; - const EVP_MD *cert_id_md = NULL, *rsign_md = NULL; + OPTION_CHOICE o; - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); - args = argv + 1; reqnames = sk_OPENSSL_STRING_new_null(); + if (reqnames == NULL) + goto end; ids = sk_OCSP_CERTID_new_null(); - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-timeout")) { - if (args[1]) { - args++; - req_timeout = atol(*args); - if (req_timeout < 0) { - BIO_printf(bio_err, "Illegal timeout value %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-url")) { - if (thost) - OPENSSL_free(thost); - if (tport) - OPENSSL_free(tport); - if (tpath) - OPENSSL_free(tpath); + if (ids == NULL) + goto end; + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + return 1; + + prog = opt_init(argc, argv, ocsp_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(ocsp_options); + goto end; + case OPT_OUTFILE: + outfile = opt_arg(); + break; + case OPT_TIMEOUT: +#ifndef OPENSSL_NO_SOCK + req_timeout = atoi(opt_arg()); +#endif + break; + case OPT_URL: + OPENSSL_free(thost); + OPENSSL_free(tport); + OPENSSL_free(tpath); thost = tport = tpath = NULL; - if (args[1]) { - args++; - if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl)) { - BIO_printf(bio_err, "Error parsing URL\n"); - badarg = 1; - } - thost = host; - tport = port; - tpath = path; - } else - badarg = 1; - } else if (!strcmp(*args, "-host")) { - if (args[1]) { - args++; - host = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-port")) { - if (args[1]) { - args++; - port = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-header")) { - if (args[1] && args[2]) { - if (!X509V3_add_value(args[1], args[2], &headers)) - goto end; - args += 2; - } else - badarg = 1; - } else if (!strcmp(*args, "-ignore_err")) + if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) { + BIO_printf(bio_err, "%s Error parsing URL\n", prog); + goto end; + } + thost = host; + tport = port; + tpath = path; + break; + case OPT_HOST: + host = opt_arg(); + break; + case OPT_PORT: + port = opt_arg(); + break; + case OPT_IGNORE_ERR: ignore_err = 1; - else if (!strcmp(*args, "-noverify")) + break; + case OPT_NOVERIFY: noverify = 1; - else if (!strcmp(*args, "-nonce")) + break; + case OPT_NONCE: add_nonce = 2; - else if (!strcmp(*args, "-no_nonce")) + break; + case OPT_NO_NONCE: add_nonce = 0; - else if (!strcmp(*args, "-resp_no_certs")) + break; + case OPT_RESP_NO_CERTS: rflags |= OCSP_NOCERTS; - else if (!strcmp(*args, "-resp_key_id")) + break; + case OPT_RESP_KEY_ID: rflags |= OCSP_RESPID_KEY; - else if (!strcmp(*args, "-no_certs")) + break; + case OPT_NO_CERTS: sign_flags |= OCSP_NOCERTS; - else if (!strcmp(*args, "-no_signature_verify")) + break; + case OPT_NO_SIGNATURE_VERIFY: verify_flags |= OCSP_NOSIGS; - else if (!strcmp(*args, "-no_cert_verify")) + break; + case OPT_NO_CERT_VERIFY: verify_flags |= OCSP_NOVERIFY; - else if (!strcmp(*args, "-no_chain")) + break; + case OPT_NO_CHAIN: verify_flags |= OCSP_NOCHAIN; - else if (!strcmp(*args, "-no_cert_checks")) + break; + case OPT_NO_CERT_CHECKS: verify_flags |= OCSP_NOCHECKS; - else if (!strcmp(*args, "-no_explicit")) + break; + case OPT_NO_EXPLICIT: verify_flags |= OCSP_NOEXPLICIT; - else if (!strcmp(*args, "-trust_other")) + break; + case OPT_TRUST_OTHER: verify_flags |= OCSP_TRUSTOTHER; - else if (!strcmp(*args, "-no_intern")) + break; + case OPT_NO_INTERN: verify_flags |= OCSP_NOINTERN; - else if (!strcmp(*args, "-badsig")) + break; + case OPT_BADSIG: badsig = 1; - else if (!strcmp(*args, "-text")) { - req_text = 1; - resp_text = 1; - } else if (!strcmp(*args, "-req_text")) + break; + case OPT_TEXT: + req_text = resp_text = 1; + break; + case OPT_REQ_TEXT: req_text = 1; - else if (!strcmp(*args, "-resp_text")) + break; + case OPT_RESP_TEXT: resp_text = 1; - else if (!strcmp(*args, "-reqin")) { - if (args[1]) { - args++; - reqin = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-respin")) { - if (args[1]) { - args++; - respin = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-signer")) { - if (args[1]) { - args++; - signfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-VAfile")) { - if (args[1]) { - args++; - verify_certfile = *args; - verify_flags |= OCSP_TRUSTOTHER; - } else - badarg = 1; - } else if (!strcmp(*args, "-sign_other")) { - if (args[1]) { - args++; - sign_certfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-verify_other")) { - if (args[1]) { - args++; - verify_certfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-CAfile")) { - if (args[1]) { - args++; - CAfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-CApath")) { - if (args[1]) { - args++; - CApath = *args; - } else - badarg = 1; - } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) { - if (badarg) + break; + case OPT_REQIN: + reqin = opt_arg(); + break; + case OPT_RESPIN: + respin = opt_arg(); + break; + case OPT_SIGNER: + signfile = opt_arg(); + break; + case OPT_VAFILE: + verify_certfile = opt_arg(); + verify_flags |= OCSP_TRUSTOTHER; + break; + case OPT_SIGN_OTHER: + sign_certfile = opt_arg(); + break; + case OPT_VERIFY_OTHER: + verify_certfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) goto end; - continue; - } else if (!strcmp(*args, "-validity_period")) { - if (args[1]) { - args++; - nsec = atol(*args); - if (nsec < 0) { - BIO_printf(bio_err, - "Illegal validity period %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-status_age")) { - if (args[1]) { - args++; - maxage = atol(*args); - if (maxage < 0) { - BIO_printf(bio_err, "Illegal validity age %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-signkey")) { - if (args[1]) { - args++; - keyfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-reqout")) { - if (args[1]) { - args++; - reqout = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-respout")) { - if (args[1]) { - args++; - respout = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-path")) { - if (args[1]) { - args++; - path = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-issuer")) { - if (args[1]) { - args++; - X509_free(issuer); - issuer = load_cert(bio_err, *args, FORMAT_PEM, - NULL, e, "issuer certificate"); - if (!issuer) - goto end; - } else - badarg = 1; - } else if (!strcmp(*args, "-cert")) { - if (args[1]) { - args++; - X509_free(cert); - cert = load_cert(bio_err, *args, FORMAT_PEM, - NULL, e, "certificate"); - if (!cert) - goto end; - if (!cert_id_md) - cert_id_md = EVP_sha1(); - if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids)) - goto end; - if (!sk_OPENSSL_STRING_push(reqnames, *args)) - goto end; - } else - badarg = 1; - } else if (!strcmp(*args, "-serial")) { - if (args[1]) { - args++; - if (!cert_id_md) - cert_id_md = EVP_sha1(); - if (!add_ocsp_serial(&req, *args, cert_id_md, issuer, ids)) - goto end; - if (!sk_OPENSSL_STRING_push(reqnames, *args)) + vpmtouched++; + break; + case OPT_VALIDITY_PERIOD: + opt_long(opt_arg(), &nsec); + break; + case OPT_STATUS_AGE: + opt_long(opt_arg(), &maxage); + break; + case OPT_SIGNKEY: + keyfile = opt_arg(); + break; + case OPT_REQOUT: + reqout = opt_arg(); + break; + case OPT_RESPOUT: + respout = opt_arg(); + break; + case OPT_PATH: + path = opt_arg(); + break; + case OPT_ISSUER: + issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate"); + if (issuer == NULL) + goto end; + if (issuers == NULL) { + if ((issuers = sk_X509_new_null()) == NULL) goto end; - } else - badarg = 1; - } else if (!strcmp(*args, "-index")) { - if (args[1]) { - args++; - ridx_filename = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-CA")) { - if (args[1]) { - args++; - rca_filename = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-nmin")) { - if (args[1]) { - args++; - nmin = atol(*args); - if (nmin < 0) { - BIO_printf(bio_err, "Illegal update period %s\n", *args); - badarg = 1; - } } + sk_X509_push(issuers, issuer); + break; + case OPT_CERT: + X509_free(cert); + cert = load_cert(opt_arg(), FORMAT_PEM, "certificate"); + if (cert == NULL) + goto end; + if (cert_id_md == NULL) + cert_id_md = EVP_sha1(); + if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids)) + goto end; + if (!sk_OPENSSL_STRING_push(reqnames, opt_arg())) + goto end; + trailing_md = 0; + break; + case OPT_SERIAL: + if (cert_id_md == NULL) + cert_id_md = EVP_sha1(); + if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids)) + goto end; + if (!sk_OPENSSL_STRING_push(reqnames, opt_arg())) + goto end; + trailing_md = 0; + break; + case OPT_INDEX: + ridx_filename = opt_arg(); + break; + case OPT_CA: + rca_filename = opt_arg(); + break; + case OPT_NMIN: + opt_int(opt_arg(), &nmin); if (ndays == -1) ndays = 0; - else - badarg = 1; - } else if (!strcmp(*args, "-nrequest")) { - if (args[1]) { - args++; - accept_count = atol(*args); - if (accept_count < 0) { - BIO_printf(bio_err, "Illegal accept count %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-ndays")) { - if (args[1]) { - args++; - ndays = atol(*args); - if (ndays < 0) { - BIO_printf(bio_err, "Illegal update period %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-rsigner")) { - if (args[1]) { - args++; - rsignfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-rkey")) { - if (args[1]) { - args++; - rkeyfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-rother")) { - if (args[1]) { - args++; - rcertfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-rmd")) { - if (args[1]) { - args++; - rsign_md = EVP_get_digestbyname(*args); - if (!rsign_md) - badarg = 1; - } else - badarg = 1; - } else if ((cert_id_md = EVP_get_digestbyname((*args) + 1)) == NULL) { - badarg = 1; + break; + case OPT_REQUEST: + opt_int(opt_arg(), &accept_count); + break; + case OPT_NDAYS: + ndays = atoi(opt_arg()); + break; + case OPT_RSIGNER: + rsignfile = opt_arg(); + break; + case OPT_RKEY: + rkeyfile = opt_arg(); + break; + case OPT_ROTHER: + rcertfile = opt_arg(); + break; + case OPT_RMD: /* Response MessageDigest */ + if (!opt_md(opt_arg(), &rsign_md)) + goto end; + break; + case OPT_RSIGOPT: + if (rsign_sigopts == NULL) + rsign_sigopts = sk_OPENSSL_STRING_new_null(); + if (rsign_sigopts == NULL || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg())) + goto end; + break; + case OPT_HEADER: + header = opt_arg(); + value = strchr(header, '='); + if (value == NULL) { + BIO_printf(bio_err, "Missing = in header key=value\n"); + goto opthelp; + } + *value++ = '\0'; + if (!X509V3_add_value(header, value, &headers)) + goto end; + break; + case OPT_MD: + if (trailing_md) { + BIO_printf(bio_err, + "%s: Digest must be before -cert or -serial\n", + prog); + goto opthelp; + } + if (!opt_md(opt_unknown(), &cert_id_md)) + goto opthelp; + trailing_md = 1; + break; + case OPT_MULTI: +# ifdef OCSP_DAEMON + multi = atoi(opt_arg()); +# endif + break; } - args++; } - - /* Have we anything to do? */ - if (!req && !reqin && !respin && !(port && ridx_filename)) - badarg = 1; - - if (badarg) { - BIO_printf(bio_err, "OCSP utility\n"); - BIO_printf(bio_err, "Usage ocsp [options]\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-out file output filename\n"); - BIO_printf(bio_err, "-issuer file issuer certificate\n"); - BIO_printf(bio_err, "-cert file certificate to check\n"); - BIO_printf(bio_err, "-serial n serial number to check\n"); - BIO_printf(bio_err, - "-signer file certificate to sign OCSP request with\n"); - BIO_printf(bio_err, - "-signkey file private key to sign OCSP request with\n"); - BIO_printf(bio_err, - "-sign_other file additional certificates to include in signed request\n"); - BIO_printf(bio_err, - "-no_certs don't include any certificates in signed request\n"); - BIO_printf(bio_err, - "-req_text print text form of request\n"); - BIO_printf(bio_err, - "-resp_text print text form of response\n"); - BIO_printf(bio_err, - "-text print text form of request and response\n"); - BIO_printf(bio_err, - "-reqout file write DER encoded OCSP request to \"file\"\n"); - BIO_printf(bio_err, - "-respout file write DER encoded OCSP reponse to \"file\"\n"); - BIO_printf(bio_err, - "-reqin file read DER encoded OCSP request from \"file\"\n"); - BIO_printf(bio_err, - "-respin file read DER encoded OCSP reponse from \"file\"\n"); - BIO_printf(bio_err, - "-nonce add OCSP nonce to request\n"); - BIO_printf(bio_err, - "-no_nonce don't add OCSP nonce to request\n"); - BIO_printf(bio_err, "-url URL OCSP responder URL\n"); - BIO_printf(bio_err, - "-host host:n send OCSP request to host on port n\n"); - BIO_printf(bio_err, - "-path path to use in OCSP request\n"); - BIO_printf(bio_err, - "-CApath dir trusted certificates directory\n"); - BIO_printf(bio_err, - "-CAfile file trusted certificates file\n"); - BIO_printf(bio_err, - "-no_alt_chains only ever use the first certificate chain found\n"); - BIO_printf(bio_err, - "-VAfile file validator certificates file\n"); - BIO_printf(bio_err, - "-validity_period n maximum validity discrepancy in seconds\n"); - BIO_printf(bio_err, - "-status_age n maximum status age in seconds\n"); - BIO_printf(bio_err, - "-noverify don't verify response at all\n"); - BIO_printf(bio_err, - "-verify_other file additional certificates to search for signer\n"); - BIO_printf(bio_err, - "-trust_other don't verify additional certificates\n"); - BIO_printf(bio_err, - "-no_intern don't search certificates contained in response for signer\n"); - BIO_printf(bio_err, - "-no_signature_verify don't check signature on response\n"); - BIO_printf(bio_err, - "-no_cert_verify don't check signing certificate\n"); - BIO_printf(bio_err, - "-no_chain don't chain verify response\n"); - BIO_printf(bio_err, - "-no_cert_checks don't do additional checks on signing certificate\n"); - BIO_printf(bio_err, - "-port num port to run responder on\n"); - BIO_printf(bio_err, - "-index file certificate status index file\n"); - BIO_printf(bio_err, "-CA file CA certificate\n"); - BIO_printf(bio_err, - "-rsigner file responder certificate to sign responses with\n"); - BIO_printf(bio_err, - "-rkey file responder key to sign responses with\n"); - BIO_printf(bio_err, - "-rother file other certificates to include in response\n"); - BIO_printf(bio_err, - "-resp_no_certs don't include any certificates in response\n"); - BIO_printf(bio_err, - "-nmin n number of minutes before next update\n"); - BIO_printf(bio_err, - "-ndays n number of days before next update\n"); - BIO_printf(bio_err, - "-resp_key_id identify reponse by signing certificate key ID\n"); - BIO_printf(bio_err, - "-nrequest n number of requests to accept (default unlimited)\n"); - BIO_printf(bio_err, - "-<dgst alg> use specified digest in the request\n"); - BIO_printf(bio_err, - "-timeout n timeout connection to OCSP responder after n seconds\n"); - goto end; + if (trailing_md) { + BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n", + prog); + goto opthelp; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (outfile) - out = BIO_new_file(outfile, "w"); - else - out = BIO_new_fp(stdout, BIO_NOCLOSE); + /* Have we anything to do? */ + if (req == NULL && reqin == NULL + && respin == NULL && !(port != NULL && ridx_filename != NULL)) + goto opthelp; - if (!out) { - BIO_printf(bio_err, "Error opening output file\n"); + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) goto end; - } - if (!req && (add_nonce != 2)) + if (req == NULL && (add_nonce != 2)) add_nonce = 0; - if (!req && reqin) { - if (!strcmp(reqin, "-")) - derbio = BIO_new_fp(stdin, BIO_NOCLOSE); - else - derbio = BIO_new_file(reqin, "rb"); - if (!derbio) { - BIO_printf(bio_err, "Error Opening OCSP request file\n"); + if (req == NULL && reqin != NULL) { + derbio = bio_open_default(reqin, 'r', FORMAT_ASN1); + if (derbio == NULL) goto end; - } req = d2i_OCSP_REQUEST_bio(derbio, NULL); BIO_free(derbio); - if (!req) { + if (req == NULL) { BIO_printf(bio_err, "Error reading OCSP request\n"); goto end; } } - if (!req && port) { + if (req == NULL && port != NULL) { acbio = init_responder(port); - if (!acbio) + if (acbio == NULL) goto end; } - if (rsignfile && !rdb) { - if (!rkeyfile) + if (rsignfile != NULL) { + if (rkeyfile == NULL) rkeyfile = rsignfile; - rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM, - NULL, e, "responder certificate"); - if (!rsigner) { + rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate"); + if (rsigner == NULL) { BIO_printf(bio_err, "Error loading responder certificate\n"); goto end; } - rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM, - NULL, e, "CA certificate"); - if (rcertfile) { - rother = load_certs(bio_err, rcertfile, FORMAT_PEM, - NULL, e, "responder other certificates"); - if (!rother) + if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM, + NULL, "CA certificate")) + goto end; + if (rcertfile != NULL) { + if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL, + "responder other certificates")) goto end; } - rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL, + rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL, "responder private key"); - if (!rkey) + if (rkey == NULL) goto end; } - if (acbio) - BIO_printf(bio_err, "Waiting for OCSP client connections...\n"); - redo_accept: + if (ridx_filename != NULL + && (rkey == NULL || rsigner == NULL || rca_cert == NULL)) { + BIO_printf(bio_err, + "Responder mode requires certificate, key, and CA.\n"); + goto end; + } - if (acbio) { - if (!do_responder(&req, &cbio, acbio, port)) + if (ridx_filename != NULL) { + rdb = load_index(ridx_filename, NULL); + if (rdb == NULL || index_index(rdb) <= 0) { + ret = 1; goto end; - if (!req) { + } + } + +# ifdef OCSP_DAEMON + if (multi && acbio != NULL) + spawn_loop(); + if (acbio != NULL && req_timeout > 0) + signal(SIGALRM, sock_timeout); +#endif + + if (acbio != NULL) + log_message(LOG_INFO, "waiting for OCSP client connections..."); + +redo_accept: + + if (acbio != NULL) { +# ifdef OCSP_DAEMON + if (index_changed(rdb)) { + CA_DB *newrdb = load_index(ridx_filename, NULL); + + if (newrdb != NULL && index_index(newrdb) > 0) { + free_index(rdb); + rdb = newrdb; + } else { + free_index(newrdb); + log_message(LOG_ERR, "error reloading updated index: %s", + ridx_filename); + } + } +# endif + + req = NULL; + if (!do_responder(&req, &cbio, acbio, req_timeout)) + goto redo_accept; + + if (req == NULL) { resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); @@ -663,32 +606,32 @@ int MAIN(int argc, char **argv) } } - if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) { + if (req == NULL + && (signfile != NULL || reqout != NULL + || host != NULL || add_nonce || ridx_filename != NULL)) { BIO_printf(bio_err, "Need an OCSP request for this operation!\n"); goto end; } - if (req && add_nonce) + if (req != NULL && add_nonce) OCSP_request_add1_nonce(req, NULL, -1); - if (signfile) { - if (!keyfile) + if (signfile != NULL) { + if (keyfile == NULL) keyfile = signfile; - signer = load_cert(bio_err, signfile, FORMAT_PEM, - NULL, e, "signer certificate"); - if (!signer) { + signer = load_cert(signfile, FORMAT_PEM, "signer certificate"); + if (signer == NULL) { BIO_printf(bio_err, "Error loading signer certificate\n"); goto end; } - if (sign_certfile) { - sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM, - NULL, e, "signer certificates"); - if (!sign_other) + if (sign_certfile != NULL) { + if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL, + "signer certificates")) goto end; } - key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL, + key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL, "signer private key"); - if (!key) + if (key == NULL) goto end; if (!OCSP_request_sign @@ -698,68 +641,43 @@ int MAIN(int argc, char **argv) } } - if (req_text && req) + if (req_text && req != NULL) OCSP_REQUEST_print(out, req, 0); - if (reqout) { - if (!strcmp(reqout, "-")) - derbio = BIO_new_fp(stdout, BIO_NOCLOSE); - else - derbio = BIO_new_file(reqout, "wb"); - if (!derbio) { - BIO_printf(bio_err, "Error opening file %s\n", reqout); + if (reqout != NULL) { + derbio = bio_open_default(reqout, 'w', FORMAT_ASN1); + if (derbio == NULL) goto end; - } i2d_OCSP_REQUEST_bio(derbio, req); BIO_free(derbio); } - if (ridx_filename && (!rkey || !rsigner || !rca_cert)) { - BIO_printf(bio_err, - "Need a responder certificate, key and CA for this operation!\n"); - goto end; - } - - if (ridx_filename && !rdb) { - rdb = load_index(ridx_filename, NULL); - if (!rdb) - goto end; - if (!index_index(rdb)) - goto end; - } - - if (rdb) { - i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, - rsign_md, rother, rflags, nmin, ndays, badsig); - if (cbio) + if (rdb != NULL) { + make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey, + rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig); + if (cbio != NULL) send_ocsp_response(cbio, resp); - } else if (host) { + } else if (host != NULL) { # ifndef OPENSSL_NO_SOCK - resp = process_responder(bio_err, req, host, path, + resp = process_responder(req, host, path, port, use_ssl, headers, req_timeout); - if (!resp) + if (resp == NULL) goto end; # else BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n"); goto end; # endif - } else if (respin) { - if (!strcmp(respin, "-")) - derbio = BIO_new_fp(stdin, BIO_NOCLOSE); - else - derbio = BIO_new_file(respin, "rb"); - if (!derbio) { - BIO_printf(bio_err, "Error Opening OCSP response file\n"); + } else if (respin != NULL) { + derbio = bio_open_default(respin, 'r', FORMAT_ASN1); + if (derbio == NULL) goto end; - } resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); BIO_free(derbio); - if (!resp) { + if (resp == NULL) { BIO_printf(bio_err, "Error reading OCSP response\n"); goto end; } - } else { ret = 0; goto end; @@ -767,70 +685,60 @@ int MAIN(int argc, char **argv) done_resp: - if (respout) { - if (!strcmp(respout, "-")) - derbio = BIO_new_fp(stdout, BIO_NOCLOSE); - else - derbio = BIO_new_file(respout, "wb"); - if (!derbio) { - BIO_printf(bio_err, "Error opening file %s\n", respout); + if (respout != NULL) { + derbio = bio_open_default(respout, 'w', FORMAT_ASN1); + if (derbio == NULL) goto end; - } i2d_OCSP_RESPONSE_bio(derbio, resp); BIO_free(derbio); } i = OCSP_response_status(resp); - if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) { BIO_printf(out, "Responder Error: %s (%d)\n", OCSP_response_status_str(i), i); - if (ignore_err) - goto redo_accept; - ret = 0; - goto end; + if (!ignore_err) + goto end; } if (resp_text) OCSP_RESPONSE_print(out, resp, 0); /* If running as responder don't verify our own response */ - if (cbio) { - if (accept_count > 0) - accept_count--; - /* Redo if more connections needed */ - if (accept_count) { - BIO_free_all(cbio); - cbio = NULL; - OCSP_REQUEST_free(req); - req = NULL; - OCSP_RESPONSE_free(resp); - resp = NULL; - goto redo_accept; + if (cbio != NULL) { + /* If not unlimited, see if we took all we should. */ + if (accept_count != -1 && --accept_count <= 0) { + ret = 0; + goto end; } - ret = 0; - goto end; - } else if (ridx_filename) { + BIO_free_all(cbio); + cbio = NULL; + OCSP_REQUEST_free(req); + req = NULL; + OCSP_RESPONSE_free(resp); + resp = NULL; + goto redo_accept; + } + if (ridx_filename != NULL) { ret = 0; goto end; } - if (!store) - store = setup_verify(bio_err, CAfile, CApath); - if (!store) - goto end; - if (vpm) + if (store == NULL) { + store = setup_verify(CAfile, CApath, noCAfile, noCApath); + if (!store) + goto end; + } + if (vpmtouched) X509_STORE_set1_param(store, vpm); - if (verify_certfile) { - verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM, - NULL, e, "validator certificate"); - if (!verify_other) + if (verify_certfile != NULL) { + if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL, + "validator certificate")) goto end; } bs = OCSP_response_get1_basic(resp); - - if (!bs) { + if (bs == NULL) { BIO_printf(bio_err, "Error parsing response\n"); goto end; } @@ -838,7 +746,7 @@ int MAIN(int argc, char **argv) ret = 0; if (!noverify) { - if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) { + if (req != NULL && ((i = OCSP_check_nonce(req, bs)) <= 0)) { if (i == -1) BIO_printf(bio_err, "WARNING: no nonce in response\n"); else { @@ -849,34 +757,38 @@ int MAIN(int argc, char **argv) } i = OCSP_basic_verify(bs, verify_other, store, verify_flags); + if (i <= 0 && issuers) { + i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER); + if (i > 0) + ERR_clear_error(); + } if (i <= 0) { BIO_printf(bio_err, "Response Verify Failure\n"); ERR_print_errors(bio_err); ret = 1; - } else + } else { BIO_printf(bio_err, "Response verify OK\n"); - + } } - if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage)) - ret = 1; + print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage); end: ERR_print_errors(bio_err); X509_free(signer); X509_STORE_free(store); - if (vpm) - X509_VERIFY_PARAM_free(vpm); + X509_VERIFY_PARAM_free(vpm); + sk_OPENSSL_STRING_free(rsign_sigopts); EVP_PKEY_free(key); EVP_PKEY_free(rkey); - X509_free(issuer); X509_free(cert); + sk_X509_pop_free(issuers, X509_free); X509_free(rsigner); - X509_free(rca_cert); + sk_X509_pop_free(rca_cert, X509_free); free_index(rdb); BIO_free_all(cbio); BIO_free_all(acbio); - BIO_free(out); + BIO_free_all(out); OCSP_REQUEST_free(req); OCSP_RESPONSE_free(resp); OCSP_BASICRESP_free(bs); @@ -885,32 +797,206 @@ int MAIN(int argc, char **argv) sk_X509_pop_free(sign_other, X509_free); sk_X509_pop_free(verify_other, X509_free); sk_CONF_VALUE_pop_free(headers, X509V3_conf_free); + OPENSSL_free(thost); + OPENSSL_free(tport); + OPENSSL_free(tpath); + + return ret; +} + +static void +log_message(int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); +# ifdef OCSP_DAEMON + if (multi) { + char buf[1024]; + if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) { + syslog(level, "%s", buf); + } + if (level >= LOG_ERR) + ERR_print_errors_cb(print_syslog, &level); + } +# endif + if (!multi) { + BIO_printf(bio_err, "%s: ", prog); + BIO_vprintf(bio_err, fmt, ap); + BIO_printf(bio_err, "\n"); + } + va_end(ap); +} + +# ifdef OCSP_DAEMON + +static int print_syslog(const char *str, size_t len, void *levPtr) +{ + int level = *(int *)levPtr; + int ilen = (len > MAXERRLEN) ? MAXERRLEN : len; + + syslog(level, "%.*s", ilen, str); + + return ilen; +} + +static int index_changed(CA_DB *rdb) +{ + struct stat sb; + + if (rdb != NULL && stat(rdb->dbfname, &sb) != -1) { + if (rdb->dbst.st_mtime != sb.st_mtime + || rdb->dbst.st_ctime != sb.st_ctime + || rdb->dbst.st_ino != sb.st_ino + || rdb->dbst.st_dev != sb.st_dev) { + syslog(LOG_INFO, "index file changed, reloading"); + return 1; + } + } + return 0; +} + +static void killall(int ret, pid_t *kidpids) +{ + int i; + + for (i = 0; i < multi; ++i) + if (kidpids[i] != 0) + (void)kill(kidpids[i], SIGTERM); + sleep(1); + exit(ret); +} - if (thost) - OPENSSL_free(thost); - if (tport) - OPENSSL_free(tport); - if (tpath) - OPENSSL_free(tpath); +static int termsig = 0; + +static void noteterm (int sig) +{ + termsig = sig; +} + +/* + * Loop spawning up to `multi` child processes, only child processes return + * from this function. The parent process loops until receiving a termination + * signal, kills extant children and exits without returning. + */ +static void spawn_loop(void) +{ + pid_t *kidpids = NULL; + int status; + int procs = 0; + int i; + + openlog(prog, LOG_PID, LOG_DAEMON); + + if (setpgid(0, 0)) { + syslog(LOG_ERR, "fatal: error detaching from parent process group: %s", + strerror(errno)); + exit(1); + } + kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array"); + for (i = 0; i < multi; ++i) + kidpids[i] = 0; + + signal(SIGINT, noteterm); + signal(SIGTERM, noteterm); + + while (termsig == 0) { + pid_t fpid; + + /* + * Wait for a child to replace when we're at the limit. + * Slow down if a child exited abnormally or waitpid() < 0 + */ + while (termsig == 0 && procs >= multi) { + if ((fpid = waitpid(-1, &status, 0)) > 0) { + for (i = 0; i < procs; ++i) { + if (kidpids[i] == fpid) { + kidpids[i] = 0; + --procs; + break; + } + } + if (i >= multi) { + syslog(LOG_ERR, "fatal: internal error: " + "no matching child slot for pid: %ld", + (long) fpid); + killall(1, kidpids); + } + if (status != 0) { + if (WIFEXITED(status)) + syslog(LOG_WARNING, "child process: %ld, exit status: %d", + (long)fpid, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + syslog(LOG_WARNING, "child process: %ld, term signal %d%s", + (long)fpid, WTERMSIG(status), +#ifdef WCOREDUMP + WCOREDUMP(status) ? " (core dumped)" : +#endif + ""); + sleep(1); + } + break; + } else if (errno != EINTR) { + syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno)); + killall(1, kidpids); + } + } + if (termsig) + break; + + switch(fpid = fork()) { + case -1: /* error */ + /* System critically low on memory, pause and try again later */ + sleep(30); + break; + case 0: /* child */ + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + if (termsig) + _exit(0); + if (RAND_poll() <= 0) { + syslog(LOG_ERR, "fatal: RAND_poll() failed"); + _exit(1); + } + return; + default: /* parent */ + for (i = 0; i < multi; ++i) { + if (kidpids[i] == 0) { + kidpids[i] = fpid; + procs++; + break; + } + } + if (i >= multi) { + syslog(LOG_ERR, "fatal: internal error: no free child slots"); + killall(1, kidpids); + } + break; + } + } - OPENSSL_EXIT(ret); + /* The loop above can only break on termsig */ + syslog(LOG_INFO, "terminating on signal: %d", termsig); + killall(0, kidpids); } +# endif static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md, X509 *issuer, STACK_OF(OCSP_CERTID) *ids) { OCSP_CERTID *id; - if (!issuer) { + + if (issuer == NULL) { BIO_printf(bio_err, "No issuer certificate specified\n"); return 0; } - if (!*req) + if (*req == NULL) *req = OCSP_REQUEST_new(); - if (!*req) + if (*req == NULL) goto err; id = OCSP_cert_to_id(cert_id_md, cert, issuer); - if (!id || !sk_OCSP_CERTID_push(ids, id)) + if (id == NULL || !sk_OCSP_CERTID_push(ids, id)) goto err; if (!OCSP_request_add0_id(*req, id)) goto err; @@ -929,24 +1015,25 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509_NAME *iname; ASN1_BIT_STRING *ikey; ASN1_INTEGER *sno; - if (!issuer) { + + if (issuer == NULL) { BIO_printf(bio_err, "No issuer certificate specified\n"); return 0; } - if (!*req) + if (*req == NULL) *req = OCSP_REQUEST_new(); - if (!*req) + if (*req == NULL) goto err; iname = X509_get_subject_name(issuer); ikey = X509_get0_pubkey_bitstr(issuer); sno = s2i_ASN1_INTEGER(NULL, serial); - if (!sno) { + if (sno == NULL) { BIO_printf(bio_err, "Error converting serial number %s\n", serial); return 0; } id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno); ASN1_INTEGER_free(sno); - if (!id || !sk_OCSP_CERTID_push(ids, id)) + if (id == NULL || !sk_OCSP_CERTID_push(ids, id)) goto err; if (!OCSP_request_add0_id(*req, id)) goto err; @@ -957,22 +1044,19 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, return 0; } -static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, +static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, STACK_OF(OPENSSL_STRING) *names, STACK_OF(OCSP_CERTID) *ids, long nsec, long maxage) { OCSP_CERTID *id; - char *name; - int i; - - int status, reason; - + const char *name; + int i, status, reason; ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; - if (!bs || !req || !sk_OPENSSL_STRING_num(names) + if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names) || !sk_OCSP_CERTID_num(ids)) - return 1; + return; for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) { id = sk_OCSP_CERTID_value(ids, i); @@ -1015,20 +1099,21 @@ static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, ASN1_GENERALIZEDTIME_print(out, rev); BIO_puts(out, "\n"); } - - return 1; } -static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, - CA_DB *db, X509 *ca, X509 *rcert, +static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req, + CA_DB *db, STACK_OF(X509) *ca, X509 *rcert, EVP_PKEY *rkey, const EVP_MD *rmd, + STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(X509) *rother, unsigned long flags, int nmin, int ndays, int badsig) { ASN1_TIME *thisupd = NULL, *nextupd = NULL; - OCSP_CERTID *cid, *ca_id = NULL; + OCSP_CERTID *cid; OCSP_BASICRESP *bs = NULL; - int i, id_count, ret = 1; + int i, id_count; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pkctx = NULL; id_count = OCSP_request_onereq_count(req); @@ -1048,6 +1133,8 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, OCSP_ONEREQ *one; ASN1_INTEGER *serial; char **inf; + int jj; + int found = 0; ASN1_OBJECT *cert_id_md_oid; const EVP_MD *cert_id_md; one = OCSP_request_onereq_get0(req, i); @@ -1056,17 +1143,22 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid); cert_id_md = EVP_get_digestbyobj(cert_id_md_oid); - if (!cert_id_md) { + if (cert_id_md == NULL) { *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); goto end; } - if (ca_id) + for (jj = 0; jj < sk_X509_num(ca) && !found; jj++) { + X509 *ca_cert = sk_X509_value(ca, jj); + OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert); + + if (OCSP_id_issuer_cmp(ca_id, cid) == 0) + found = 1; + OCSP_CERTID_free(ca_id); - ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca); + } - /* Is this request about our CA? */ - if (OCSP_id_issuer_cmp(ca_id, cid)) { + if (!found) { OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_UNKNOWN, 0, NULL, thisupd, nextupd); @@ -1074,15 +1166,15 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, } OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); inf = lookup_serial(db, serial); - if (!inf) + if (inf == NULL) { OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_UNKNOWN, 0, NULL, thisupd, nextupd); - else if (inf[DB_type][0] == DB_TYPE_VAL) + } else if (inf[DB_type][0] == DB_TYPE_VAL) { OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_GOOD, 0, NULL, thisupd, nextupd); - else if (inf[DB_type][0] == DB_TYPE_REV) { + } else if (inf[DB_type][0] == DB_TYPE_REV) { ASN1_OBJECT *inst = NULL; ASN1_TIME *revtm = NULL; ASN1_GENERALIZEDTIME *invtm = NULL; @@ -1092,10 +1184,10 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, single = OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_REVOKED, reason, revtm, thisupd, nextupd); - if (invtm) + if (invtm != NULL) OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0); - else if (inst) + else if (inst != NULL) OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0); @@ -1107,20 +1199,36 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, OCSP_copy_nonce(bs, req); - OCSP_basic_sign(bs, rcert, rkey, rmd, rother, flags); + mctx = EVP_MD_CTX_new(); + if ( mctx == NULL || !EVP_DigestSignInit(mctx, &pkctx, rmd, NULL, rkey)) { + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); + goto end; + } + for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); - if (badsig) - bs->signature->data[bs->signature->length - 1] ^= 0x1; + if (pkey_ctrl_string(pkctx, sigopt) <= 0) { + BIO_printf(err, "parameter error \"%s\"\n", sigopt); + ERR_print_errors(bio_err); + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, + NULL); + goto end; + } + } + OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags); + + if (badsig) { + const ASN1_OCTET_STRING *sig = OCSP_resp_get0_signature(bs); + corrupt_signature(sig); + } *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs); end: + EVP_MD_CTX_free(mctx); ASN1_TIME_free(thisupd); ASN1_TIME_free(nextupd); - OCSP_CERTID_free(ca_id); OCSP_BASICRESP_free(bs); - return ret; - } static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) @@ -1134,7 +1242,7 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) OPENSSL_assert(bn); /* FIXME: should report an error at this * point and abort */ if (BN_is_zero(bn)) - itmp = BUF_strdup("00"); + itmp = OPENSSL_strdup("00"); else itmp = BN_bn2hex(bn); row[DB_serial] = itmp; @@ -1148,24 +1256,28 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) static BIO *init_responder(const char *port) { +# ifdef OPENSSL_NO_SOCK + BIO_printf(bio_err, + "Error setting up accept BIO - sockets not supported.\n"); + return NULL; +# else BIO *acbio = NULL, *bufbio = NULL; + bufbio = BIO_new(BIO_f_buffer()); - if (!bufbio) + if (bufbio == NULL) goto err; -# ifndef OPENSSL_NO_SOCK - acbio = BIO_new_accept(port); -# else - BIO_printf(bio_err, - "Error setting up accept BIO - sockets not supported.\n"); -# endif - if (!acbio) + acbio = BIO_new(BIO_s_accept()); + if (acbio == NULL + || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0 + || BIO_set_accept_port(acbio, port) < 0) { + log_message(LOG_ERR, "Error setting up accept BIO"); goto err; + } + BIO_set_accept_bios(acbio, bufbio); bufbio = NULL; - if (BIO_do_accept(acbio) <= 0) { - BIO_printf(bio_err, "Error setting up accept BIO\n"); - ERR_print_errors(bio_err); + log_message(LOG_ERR, "Error starting accept"); goto err; } @@ -1175,55 +1287,159 @@ static BIO *init_responder(const char *port) BIO_free_all(acbio); BIO_free(bufbio); return NULL; +# endif +} + +# ifndef OPENSSL_NO_SOCK +/* + * Decode %xx URL-decoding in-place. Ignores mal-formed sequences. + */ +static int urldecode(char *p) +{ + unsigned char *out = (unsigned char *)p; + unsigned char *save = out; + + for (; *p; p++) { + if (*p != '%') + *out++ = *p; + else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) { + /* Don't check, can't fail because of ixdigit() call. */ + *out++ = (OPENSSL_hexchar2int(p[1]) << 4) + | OPENSSL_hexchar2int(p[2]); + p += 2; + } + else + return -1; + } + *out = '\0'; + return (int)(out - save); } +# endif + +# ifdef OCSP_DAEMON +static void sock_timeout(int signum) +{ + if (acfd != (int)INVALID_SOCKET) + (void)shutdown(acfd, SHUT_RD); +} +# endif static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, - const char *port) + int timeout) { - int have_post = 0, len; +# ifdef OPENSSL_NO_SOCK + return 0; +# else + int len; OCSP_REQUEST *req = NULL; - char inbuf[1024]; - BIO *cbio = NULL; + char inbuf[2048], reqbuf[2048]; + char *p, *q; + BIO *cbio = NULL, *getbio = NULL, *b64 = NULL; + const char *client; - if (BIO_do_accept(acbio) <= 0) { - BIO_printf(bio_err, "Error accepting connection\n"); - ERR_print_errors(bio_err); + *preq = NULL; + + /* Connection loss before accept() is routine, ignore silently */ + if (BIO_do_accept(acbio) <= 0) return 0; - } cbio = BIO_pop(acbio); *pcbio = cbio; + client = BIO_get_peer_name(cbio); +# ifdef OCSP_DAEMON + if (timeout > 0) { + (void) BIO_get_fd(cbio, &acfd); + alarm(timeout); + } +# endif + + /* Read the request line. */ + len = BIO_gets(cbio, reqbuf, sizeof(reqbuf)); + if (len <= 0) + goto out; + + if (strncmp(reqbuf, "GET ", 4) == 0) { + /* Expecting GET {sp} /URL {sp} HTTP/1.x */ + for (p = reqbuf + 4; *p == ' '; ++p) + continue; + if (*p != '/') { + log_message(LOG_INFO, "Invalid request -- bad URL: %s", client); + goto out; + } + p++; + + /* Splice off the HTTP version identifier. */ + for (q = p; *q; q++) + if (*q == ' ') + break; + if (strncmp(q, " HTTP/1.", 8) != 0) { + log_message(LOG_INFO, + "Invalid request -- bad HTTP version: %s", client); + goto out; + } + *q = '\0'; + + /* + * Skip "GET / HTTP..." requests often used by load-balancers + */ + if (p[1] == '\0') + goto out; + + len = urldecode(p); + if (len <= 0) { + log_message(LOG_INFO, + "Invalid request -- bad URL encoding: %s", client); + goto out; + } + if ((getbio = BIO_new_mem_buf(p, len)) == NULL + || (b64 = BIO_new(BIO_f_base64())) == NULL) { + log_message(LOG_ERR, "Could not allocate base64 bio: %s", client); + goto out; + } + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + getbio = BIO_push(b64, getbio); + } else if (strncmp(reqbuf, "POST ", 5) != 0) { + log_message(LOG_INFO, "Invalid request -- bad HTTP verb: %s", client); + goto out; + } + + /* Read and skip past the headers. */ for (;;) { len = BIO_gets(cbio, inbuf, sizeof(inbuf)); if (len <= 0) - return 1; - /* Look for "POST" signalling start of query */ - if (!have_post) { - if (strncmp(inbuf, "POST", 4)) { - BIO_printf(bio_err, "Invalid request\n"); - return 1; - } - have_post = 1; - } - /* Look for end of headers */ + goto out; if ((inbuf[0] == '\r') || (inbuf[0] == '\n')) break; } - /* Try to read OCSP request */ - - req = d2i_OCSP_REQUEST_bio(cbio, NULL); +# ifdef OCSP_DAEMON + /* Clear alarm before we close the client socket */ + alarm(0); + timeout = 0; +# endif - if (!req) { - BIO_printf(bio_err, "Error parsing OCSP request\n"); - ERR_print_errors(bio_err); + /* Try to read OCSP request */ + if (getbio != NULL) { + req = d2i_OCSP_REQUEST_bio(getbio, NULL); + BIO_free_all(getbio); + } else { + req = d2i_OCSP_REQUEST_bio(cbio, NULL); } + if (req == NULL) + log_message(LOG_ERR, "Error parsing OCSP request"); + *preq = req; +out: +# ifdef OCSP_DAEMON + if (timeout > 0) + alarm(0); + acfd = (int)INVALID_SOCKET; +# endif return 1; - +# endif } static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) @@ -1231,7 +1447,7 @@ static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) char http_resp[] = "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n" "Content-Length: %d\r\n\r\n"; - if (!cbio) + if (cbio == NULL) return 0; BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL)); i2d_OCSP_RESPONSE_bio(cbio, resp); @@ -1239,13 +1455,16 @@ static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) return 1; } -static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path, +# ifndef OPENSSL_NO_SOCK +static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host, + const char *path, const STACK_OF(CONF_VALUE) *headers, OCSP_REQUEST *req, int req_timeout) { int fd; int rv; int i; + int add_host = 1; OCSP_REQ_CTX *ctx = NULL; OCSP_RESPONSE *rsp = NULL; fd_set confds; @@ -1257,7 +1476,7 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path, rv = BIO_do_connect(cbio); if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) { - BIO_puts(err, "Error connecting BIO\n"); + BIO_puts(bio_err, "Error connecting BIO\n"); return NULL; } @@ -1273,21 +1492,26 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path, tv.tv_sec = req_timeout; rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); if (rv == 0) { - BIO_puts(err, "Timeout on connect\n"); + BIO_puts(bio_err, "Timeout on connect\n"); return NULL; } } ctx = OCSP_sendreq_new(cbio, path, NULL, -1); - if (!ctx) + if (ctx == NULL) return NULL; for (i = 0; i < sk_CONF_VALUE_num(headers); i++) { CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i); + if (add_host == 1 && strcasecmp("host", hdr->name) == 0) + add_host = 0; if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value)) goto err; } + if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0) + goto err; + if (!OCSP_REQ_CTX_set1_req(ctx, req)) goto err; @@ -1301,67 +1525,67 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path, openssl_fdset(fd, &confds); tv.tv_usec = 0; tv.tv_sec = req_timeout; - if (BIO_should_read(cbio)) + if (BIO_should_read(cbio)) { rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv); - else if (BIO_should_write(cbio)) + } else if (BIO_should_write(cbio)) { rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); - else { - BIO_puts(err, "Unexpected retry condition\n"); + } else { + BIO_puts(bio_err, "Unexpected retry condition\n"); goto err; } if (rv == 0) { - BIO_puts(err, "Timeout on request\n"); + BIO_puts(bio_err, "Timeout on request\n"); break; } if (rv == -1) { - BIO_puts(err, "Select error\n"); + BIO_puts(bio_err, "Select error\n"); break; } } err: - if (ctx) - OCSP_REQ_CTX_free(ctx); + OCSP_REQ_CTX_free(ctx); return rsp; } -OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req, +OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host, const char *path, const char *port, int use_ssl, - const STACK_OF(CONF_VALUE) *headers, + STACK_OF(CONF_VALUE) *headers, int req_timeout) { BIO *cbio = NULL; SSL_CTX *ctx = NULL; OCSP_RESPONSE *resp = NULL; + cbio = BIO_new_connect(host); - if (!cbio) { - BIO_printf(err, "Error creating connect BIO\n"); + if (cbio == NULL) { + BIO_printf(bio_err, "Error creating connect BIO\n"); goto end; } - if (port) + if (port != NULL) BIO_set_conn_port(cbio, port); if (use_ssl == 1) { BIO *sbio; - ctx = SSL_CTX_new(SSLv23_client_method()); + ctx = SSL_CTX_new(TLS_client_method()); if (ctx == NULL) { - BIO_printf(err, "Error creating SSL context.\n"); + BIO_printf(bio_err, "Error creating SSL context.\n"); goto end; } SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); sbio = BIO_new_ssl(ctx, 1); cbio = BIO_push(sbio, cbio); } - resp = query_responder(err, cbio, path, headers, req, req_timeout); - if (!resp) + + resp = query_responder(cbio, host, path, headers, req, req_timeout); + if (resp == NULL) BIO_printf(bio_err, "Error querying OCSP responder\n"); end: - if (cbio) - BIO_free_all(cbio); - if (ctx) - SSL_CTX_free(ctx); + BIO_free_all(cbio); + SSL_CTX_free(ctx); return resp; } +# endif #endif diff --git a/apps/oid.cnf b/apps/oid.cnf deleted file mode 100644 index faf425a156bd..000000000000 --- a/apps/oid.cnf +++ /dev/null @@ -1,6 +0,0 @@ -2.99999.1 SET.ex1 SET x509v3 extension 1 -2.99999.2 SET.ex2 SET x509v3 extension 2 -2.99999.3 SET.ex3 SET x509v3 extension 3 -2.99999.4 SET.ex4 SET x509v3 extension 4 -2.99999.5 SET.ex5 SET x509v3 extension 5 -2.99999.6 SET.ex6 SET x509v3 extension 6 diff --git a/apps/openssl.c b/apps/openssl.c index c3da5d6cd0e9..a872e2c5eeec 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -1,123 +1,18 @@ -/* apps/openssl.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ +#include <internal/cryptlib.h> #include <stdio.h> #include <string.h> #include <stdlib.h> -#define OPENSSL_C /* tells apps.h to use complete - * apps_startup() */ -#include "apps.h" #include <openssl/bio.h> #include <openssl/crypto.h> -#include <openssl/rand.h> #include <openssl/lhash.h> #include <openssl/conf.h> #include <openssl/x509.h> @@ -126,14 +21,26 @@ #ifndef OPENSSL_NO_ENGINE # include <openssl/engine.h> #endif -#define USE_SOCKETS /* needed for the _O_BINARY defs in the MS - * world */ -#include "progs.h" -#include "s_apps.h" #include <openssl/err.h> -#ifdef OPENSSL_FIPS -# include <openssl/fips.h> +#include "s_apps.h" +/* Needed to get the other O_xxx flags. */ +#ifdef OPENSSL_SYS_VMS +# include <unixio.h> #endif +#include "apps.h" +#define INCLUDE_FUNCTION_TABLE +#include "progs.h" + +/* Structure to hold the number of columns to be displayed and the + * field width used to display them. + */ +typedef struct { + int columns; + int width; +} DISPLAY_COLUMNS; + +/* Special sentinel to exit the program. */ +#define EXIT_THE_PROGRAM (-1) /* * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with @@ -141,252 +48,152 @@ * required type of "FUNCTION*"). This removes the necessity for * macro-generated wrapper functions. */ - static LHASH_OF(FUNCTION) *prog_init(void); static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]); -static void list_pkey(BIO *out); -static void list_cipher(BIO *out); -static void list_md(BIO *out); +static void list_pkey(void); +static void list_pkey_meth(void); +static void list_type(FUNC_TYPE ft, int one); +static void list_disabled(void); char *default_config_file = NULL; -/* Make sure there is only one when MONOLITH is defined */ -#ifdef MONOLITH -CONF *config = NULL; +BIO *bio_in = NULL; +BIO *bio_out = NULL; BIO *bio_err = NULL; -#endif -static void lock_dbg_cb(int mode, int type, const char *file, int line) +static void calculate_columns(DISPLAY_COLUMNS *dc) { - static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */ - const char *errstr = NULL; - int rw; + FUNCTION *f; + int len, maxlen = 0; - rw = mode & (CRYPTO_READ | CRYPTO_WRITE); - if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE))) { - errstr = "invalid mode"; - goto err; - } + for (f = functions; f->name != NULL; ++f) + if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher) + if ((len = strlen(f->name)) > maxlen) + maxlen = len; - if (type < 0 || type >= CRYPTO_NUM_LOCKS) { - errstr = "type out of bounds"; - goto err; - } + dc->width = maxlen + 2; + dc->columns = (80 - 1) / dc->width; +} - if (mode & CRYPTO_LOCK) { - if (modes[type]) { - errstr = "already locked"; - /* - * must not happen in a single-threaded program (would deadlock) - */ - goto err; - } +static int apps_startup(void) +{ +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif - modes[type] = rw; - } else if (mode & CRYPTO_UNLOCK) { - if (!modes[type]) { - errstr = "not locked"; - goto err; - } + /* Set non-default library initialisation settings */ + if (!OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN + | OPENSSL_INIT_LOAD_CONFIG, NULL)) + return 0; - if (modes[type] != rw) { - errstr = (rw == CRYPTO_READ) ? - "CRYPTO_r_unlock on write lock" : - "CRYPTO_w_unlock on read lock"; - } + setup_ui_method(); - modes[type] = 0; - } else { - errstr = "invalid mode"; - goto err; - } + return 1; +} - err: - if (errstr) { - /* we cannot use bio_err here */ - fprintf(stderr, - "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n", - errstr, mode, type, file, line); - } +static void apps_shutdown(void) +{ + destroy_ui_method(); + destroy_prefix_method(); } -#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64) -# define ARGV _Argv -#else -# define ARGV Argv +static char *make_config_name(void) +{ + const char *t; + size_t len; + char *p; + + if ((t = getenv("OPENSSL_CONF")) != NULL) + return OPENSSL_strdup(t); + + t = X509_get_default_cert_area(); + len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1; + p = app_malloc(len, "config filename buffer"); + strcpy(p, t); +#ifndef OPENSSL_SYS_VMS + strcat(p, "/"); #endif + strcat(p, OPENSSL_CONF); + + return p; +} -int main(int Argc, char *ARGV[]) +int main(int argc, char *argv[]) { - ARGS arg; -#define PROG_NAME_SIZE 39 - char pname[PROG_NAME_SIZE + 1]; FUNCTION f, *fp; - MS_STATIC const char *prompt; - MS_STATIC char buf[1024]; - char *to_free = NULL; - int n, i, ret = 0; - int argc; - char **argv, *p; LHASH_OF(FUNCTION) *prog = NULL; - long errline; - -#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64) - /*- - * 2011-03-22 SMS. - * If we have 32-bit pointers everywhere, then we're safe, and - * we bypass this mess, as on non-VMS systems. (See ARGV, - * above.) - * Problem 1: Compaq/HP C before V7.3 always used 32-bit - * pointers for argv[]. - * Fix 1: For a 32-bit argv[], when we're using 64-bit pointers - * everywhere else, we always allocate and use a 64-bit - * duplicate of argv[]. - * Problem 2: Compaq/HP C V7.3 (Alpha, IA64) before ECO1 failed - * to NULL-terminate a 64-bit argv[]. (As this was written, the - * compiler ECO was available only on IA64.) - * Fix 2: Unless advised not to (VMS_TRUST_ARGV), we test a - * 64-bit argv[argc] for NULL, and, if necessary, use a - * (properly) NULL-terminated (64-bit) duplicate of argv[]. - * The same code is used in either case to duplicate argv[]. - * Some of these decisions could be handled in preprocessing, - * but the code tends to get even uglier, and the penalty for - * deciding at compile- or run-time is tiny. - */ - char **Argv = NULL; - int free_Argv = 0; + char **copied_argv = NULL; + char *p, *pname; + char buf[1024]; + const char *prompt; + ARGS arg; + int first, n, i, ret = 0; - if ((sizeof(_Argv) < 8) /* 32-bit argv[]. */ -# if !defined( VMS_TRUST_ARGV) - || (_Argv[Argc] != NULL) /* Untrusted argv[argc] not NULL. */ -# endif - ) { - int i; - Argv = OPENSSL_malloc((Argc + 1) * sizeof(char *)); - if (Argv == NULL) { - ret = -1; - goto end; - } - for (i = 0; i < Argc; i++) - Argv[i] = _Argv[i]; - Argv[Argc] = NULL; /* Certain NULL termination. */ - free_Argv = 1; - } else { - /* - * Use the known-good 32-bit argv[] (which needs the type cast to - * satisfy the compiler), or the trusted or tested-good 64-bit argv[] - * as-is. - */ - Argv = (char **)_Argv; - } -#endif /* defined( OPENSSL_SYS_VMS) && - * (__INITIAL_POINTER_SIZE == 64) */ + arg.argv = NULL; + arg.size = 0; - arg.data = NULL; - arg.count = 0; + /* Set up some of the environment. */ + default_config_file = make_config_name(); + bio_in = dup_bio_in(FORMAT_TEXT); + bio_out = dup_bio_out(FORMAT_TEXT); + bio_err = dup_bio_err(FORMAT_TEXT); - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) + copied_argv = argv = copy_argv(&argc, argv); +#elif defined(_WIN32) + /* + * Replace argv[] with UTF-8 encoded strings. + */ + win32_utf8argv(&argc, &argv); +#endif - if (getenv("OPENSSL_DEBUG_MEMORY") != NULL) { /* if not defined, use - * compiled-in library - * defaults */ - if (!(0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))) { - CRYPTO_malloc_debug_init(); - CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); - } else { - /* OPENSSL_DEBUG_MEMORY=off */ - CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); - } - } + p = getenv("OPENSSL_DEBUG_MEMORY"); + if (p != NULL && strcmp(p, "on") == 0) + CRYPTO_set_mem_debug(1); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); -#if 0 - if (getenv("OPENSSL_DEBUG_LOCKING") != NULL) -#endif - { - CRYPTO_set_locking_callback(lock_dbg_cb); - } - if (getenv("OPENSSL_FIPS")) { -#ifdef OPENSSL_FIPS - if (!FIPS_mode_set(1)) { - ERR_load_crypto_strings(); - ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE)); - EXIT(1); - } -#else - fprintf(stderr, "FIPS mode not supported.\n"); - EXIT(1); -#endif + BIO_printf(bio_err, "FIPS mode not supported.\n"); + return 1; } - apps_startup(); - - /* Lets load up our environment a little */ - p = getenv("OPENSSL_CONF"); - if (p == NULL) - p = getenv("SSLEAY_CONF"); - if (p == NULL) - p = to_free = make_config_name(); - - default_config_file = p; - - config = NCONF_new(NULL); - i = NCONF_load(config, p, &errline); - if (i == 0) { - if (ERR_GET_REASON(ERR_peek_last_error()) - == CONF_R_NO_SUCH_FILE) { - BIO_printf(bio_err, "WARNING: can't open config file: %s\n", p); - ERR_clear_error(); - NCONF_free(config); - config = NULL; - } else { - ERR_print_errors(bio_err); - NCONF_free(config); - exit(1); - } + if (!apps_startup()) { + BIO_printf(bio_err, + "FATAL: Startup failure (dev note: apps_startup() failed)\n"); + ERR_print_errors(bio_err); + ret = 1; + goto end; } prog = prog_init(); + pname = opt_progname(argv[0]); /* first check the program name */ - program_name(Argv[0], pname, sizeof(pname)); - f.name = pname; fp = lh_FUNCTION_retrieve(prog, &f); if (fp != NULL) { - Argv[0] = pname; - ret = fp->func(Argc, Argv); + argv[0] = pname; + ret = fp->func(argc, argv); goto end; } - /* - * ok, now check that there are not arguments, if there are, run with - * them, shifting the ssleay off the front - */ - if (Argc != 1) { - Argc--; - Argv++; - ret = do_cmd(prog, Argc, Argv); + /* If there is stuff on the command line, run with that. */ + if (argc != 1) { + argc--; + argv++; + ret = do_cmd(prog, argc, argv); if (ret < 0) ret = 0; goto end; } - /* ok, lets enter the old 'OpenSSL>' mode */ - + /* ok, lets enter interactive mode */ for (;;) { ret = 0; - p = buf; - n = sizeof(buf); - i = 0; - for (;;) { + /* Read a line, continue reading if line ends with \ */ + for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) { + prompt = first ? "OpenSSL> " : "> "; p[0] = '\0'; - if (i++) - prompt = ">"; - else - prompt = "OpenSSL> "; +#ifndef READLINE fputs(prompt, stdout); fflush(stdout); if (!fgets(p, n, stdin)) @@ -401,205 +208,388 @@ int main(int Argc, char *ARGV[]) i -= 2; p += i; n -= i; +#else + { + extern char *readline(const char *); + extern void add_history(const char *cp); + char *text; + + text = readline(prompt); + if (text == NULL) + goto end; + i = strlen(text); + if (i == 0 || i > n) + break; + if (text[i - 1] != '\\') { + p += strlen(strcpy(p, text)); + free(text); + add_history(buf); + break; + } + + text[i - 1] = '\0'; + p += strlen(strcpy(p, text)); + free(text); + n -= i; + } +#endif } - if (!chopup_args(&arg, buf, &argc, &argv)) + + if (!chopup_args(&arg, buf)) { + BIO_printf(bio_err, "Can't parse (no memory?)\n"); break; + } - ret = do_cmd(prog, argc, argv); - if (ret < 0) { + ret = do_cmd(prog, arg.argc, arg.argv); + if (ret == EXIT_THE_PROGRAM) { ret = 0; goto end; } if (ret != 0) - BIO_printf(bio_err, "error in %s\n", argv[0]); + BIO_printf(bio_err, "error in %s\n", arg.argv[0]); + (void)BIO_flush(bio_out); (void)BIO_flush(bio_err); } - BIO_printf(bio_err, "bad exit\n"); ret = 1; end: - if (to_free) - OPENSSL_free(to_free); - if (config != NULL) { - NCONF_free(config); - config = NULL; + OPENSSL_free(copied_argv); + OPENSSL_free(default_config_file); + lh_FUNCTION_free(prog); + OPENSSL_free(arg.argv); + app_RAND_write(); + + BIO_free(bio_in); + BIO_free_all(bio_out); + apps_shutdown(); +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (CRYPTO_mem_leaks(bio_err) <= 0) + ret = 1; +#endif + BIO_free(bio_err); + EXIT(ret); +} + +static void list_cipher_fn(const EVP_CIPHER *c, + const char *from, const char *to, void *arg) +{ + if (c != NULL) { + BIO_printf(arg, "%s\n", EVP_CIPHER_name(c)); + } else { + if (from == NULL) + from = "<undefined>"; + if (to == NULL) + to = "<undefined>"; + BIO_printf(arg, "%s => %s\n", from, to); } - if (prog != NULL) - lh_FUNCTION_free(prog); - if (arg.data != NULL) - OPENSSL_free(arg.data); +} -#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64) - /* Free any duplicate Argv[] storage. */ - if (free_Argv) { - OPENSSL_free(Argv); +static void list_md_fn(const EVP_MD *m, + const char *from, const char *to, void *arg) +{ + if (m != NULL) { + BIO_printf(arg, "%s\n", EVP_MD_name(m)); + } else { + if (from == NULL) + from = "<undefined>"; + if (to == NULL) + to = "<undefined>"; + BIO_printf((BIO *)arg, "%s => %s\n", from, to); } -#endif - apps_shutdown(); - CRYPTO_mem_leaks(bio_err); - if (bio_err != NULL) { - BIO_free(bio_err); - bio_err = NULL; +} + +static void list_missing_help(void) +{ + const FUNCTION *fp; + const OPTIONS *o; + + for (fp = functions; fp->name != NULL; fp++) { + if ((o = fp->help) != NULL) { + /* If there is help, list what flags are not documented. */ + for ( ; o->name != NULL; o++) { + if (o->helpstr == NULL) + BIO_printf(bio_out, "%s %s\n", fp->name, o->name); + } + } else if (fp->func != dgst_main) { + /* If not aliased to the dgst command, */ + BIO_printf(bio_out, "%s *\n", fp->name); + } } +} + +static void list_options_for_command(const char *command) +{ + const FUNCTION *fp; + const OPTIONS *o; - OPENSSL_EXIT(ret); + for (fp = functions; fp->name != NULL; fp++) + if (strcmp(fp->name, command) == 0) + break; + if (fp->name == NULL) { + BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", + command); + return; + } + + if ((o = fp->help) == NULL) + return; + + for ( ; o->name != NULL; o++) { + if (o->name == OPT_HELP_STR + || o->name == OPT_MORE_STR + || o->name[0] == '\0') + continue; + BIO_printf(bio_out, "%s %c\n", o->name, o->valtype); + } } -#define LIST_STANDARD_COMMANDS "list-standard-commands" -#define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands" -#define LIST_MESSAGE_DIGEST_ALGORITHMS "list-message-digest-algorithms" -#define LIST_CIPHER_COMMANDS "list-cipher-commands" -#define LIST_CIPHER_ALGORITHMS "list-cipher-algorithms" -#define LIST_PUBLIC_KEY_ALGORITHMS "list-public-key-algorithms" + +/* Unified enum for help and list commands. */ +typedef enum HELPLIST_CHOICE { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ONE, + OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_OPTIONS, + OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS, + OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, OPT_MISSING_HELP +} HELPLIST_CHOICE; + +const OPTIONS list_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"1", OPT_ONE, '-', "List in one column"}, + {"commands", OPT_COMMANDS, '-', "List of standard commands"}, + {"digest-commands", OPT_DIGEST_COMMANDS, '-', + "List of message digest commands"}, + {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-', + "List of message digest algorithms"}, + {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"}, + {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-', + "List of cipher algorithms"}, + {"public-key-algorithms", OPT_PK_ALGORITHMS, '-', + "List of public key algorithms"}, + {"public-key-methods", OPT_PK_METHOD, '-', + "List of public key methods"}, + {"disabled", OPT_DISABLED, '-', + "List of disabled features"}, + {"missing-help", OPT_MISSING_HELP, '-', + "List missing detailed help strings"}, + {"options", OPT_OPTIONS, 's', + "List options for specified command"}, + {NULL} +}; + +int list_main(int argc, char **argv) +{ + char *prog; + HELPLIST_CHOICE o; + int one = 0, done = 0; + + prog = opt_init(argc, argv, list_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: /* Never hit, but suppresses warning */ + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + return 1; + case OPT_HELP: + opt_help(list_options); + break; + case OPT_ONE: + one = 1; + break; + case OPT_COMMANDS: + list_type(FT_general, one); + break; + case OPT_DIGEST_COMMANDS: + list_type(FT_md, one); + break; + case OPT_DIGEST_ALGORITHMS: + EVP_MD_do_all_sorted(list_md_fn, bio_out); + break; + case OPT_CIPHER_COMMANDS: + list_type(FT_cipher, one); + break; + case OPT_CIPHER_ALGORITHMS: + EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out); + break; + case OPT_PK_ALGORITHMS: + list_pkey(); + break; + case OPT_PK_METHOD: + list_pkey_meth(); + break; + case OPT_DISABLED: + list_disabled(); + break; + case OPT_MISSING_HELP: + list_missing_help(); + break; + case OPT_OPTIONS: + list_options_for_command(opt_arg()); + break; + } + done = 1; + } + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } + + if (!done) + goto opthelp; + + return 0; +} + +typedef enum HELP_CHOICE { + OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP +} HELP_CHOICE; + +const OPTIONS help_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: help [options]\n"}, + {OPT_HELP_STR, 1, '-', " help [command]\n"}, + {"help", OPT_hHELP, '-', "Display this summary"}, + {NULL} +}; + + +int help_main(int argc, char **argv) +{ + FUNCTION *fp; + int i, nl; + FUNC_TYPE tp; + char *prog; + HELP_CHOICE o; + DISPLAY_COLUMNS dc; + + prog = opt_init(argc, argv, help_options); + while ((o = opt_next()) != OPT_hEOF) { + switch (o) { + case OPT_hERR: + case OPT_hEOF: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + return 1; + case OPT_hHELP: + opt_help(help_options); + return 0; + } + } + + if (opt_num_rest() == 1) { + char *new_argv[3]; + + new_argv[0] = opt_rest()[0]; + new_argv[1] = "--help"; + new_argv[2] = NULL; + return do_cmd(prog_init(), 2, new_argv); + } + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Usage: %s\n", prog); + return 1; + } + + calculate_columns(&dc); + BIO_printf(bio_err, "Standard commands"); + i = 0; + tp = FT_none; + for (fp = functions; fp->name != NULL; fp++) { + nl = 0; + if (i++ % dc.columns == 0) { + BIO_printf(bio_err, "\n"); + nl = 1; + } + if (fp->type != tp) { + tp = fp->type; + if (!nl) + BIO_printf(bio_err, "\n"); + if (tp == FT_md) { + i = 1; + BIO_printf(bio_err, + "\nMessage Digest commands (see the `dgst' command for more details)\n"); + } else if (tp == FT_cipher) { + i = 1; + BIO_printf(bio_err, + "\nCipher commands (see the `enc' command for more details)\n"); + } + } + BIO_printf(bio_err, "%-*s", dc.width, fp->name); + } + BIO_printf(bio_err, "\n\n"); + return 0; +} + +static void list_type(FUNC_TYPE ft, int one) +{ + FUNCTION *fp; + int i = 0; + DISPLAY_COLUMNS dc = {0}; + + if (!one) + calculate_columns(&dc); + + for (fp = functions; fp->name != NULL; fp++) { + if (fp->type != ft) + continue; + if (one) { + BIO_printf(bio_out, "%s\n", fp->name); + } else { + if (i % dc.columns == 0 && i > 0) + BIO_printf(bio_out, "\n"); + BIO_printf(bio_out, "%-*s", dc.width, fp->name); + i++; + } + } + if (!one) + BIO_printf(bio_out, "\n\n"); +} static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) { FUNCTION f, *fp; - int i, ret = 1, tp, nl; - if ((argc <= 0) || (argv[0] == NULL)) { - ret = 0; - goto end; - } + if (argc <= 0 || argv[0] == NULL) + return 0; f.name = argv[0]; fp = lh_FUNCTION_retrieve(prog, &f); if (fp == NULL) { if (EVP_get_digestbyname(argv[0])) { - f.type = FUNC_TYPE_MD; + f.type = FT_md; f.func = dgst_main; fp = &f; } else if (EVP_get_cipherbyname(argv[0])) { - f.type = FUNC_TYPE_CIPHER; + f.type = FT_cipher; f.func = enc_main; fp = &f; } } if (fp != NULL) { - ret = fp->func(argc, argv); - } else if ((strncmp(argv[0], "no-", 3)) == 0) { - BIO *bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - bio_stdout = BIO_push(tmpbio, bio_stdout); - } -#endif + return fp->func(argc, argv); + } + if ((strncmp(argv[0], "no-", 3)) == 0) { + /* + * User is asking if foo is unsupported, by trying to "run" the + * no-foo command. Strange. + */ f.name = argv[0] + 3; - ret = (lh_FUNCTION_retrieve(prog, &f) != NULL); - if (!ret) - BIO_printf(bio_stdout, "%s\n", argv[0]); - else - BIO_printf(bio_stdout, "%s\n", argv[0] + 3); - BIO_free_all(bio_stdout); - goto end; - } else if ((strcmp(argv[0], "quit") == 0) || - (strcmp(argv[0], "q") == 0) || - (strcmp(argv[0], "exit") == 0) || - (strcmp(argv[0], "bye") == 0)) { - ret = -1; - goto end; - } else if ((strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0) || - (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0) || - (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0) || - (strcmp(argv[0], LIST_CIPHER_COMMANDS) == 0) || - (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0) || - (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)) { - int list_type; - BIO *bio_stdout; - - if (strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0) - list_type = FUNC_TYPE_GENERAL; - else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0) - list_type = FUNC_TYPE_MD; - else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0) - list_type = FUNC_TYPE_MD_ALG; - else if (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0) - list_type = FUNC_TYPE_PKEY; - else if (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0) - list_type = FUNC_TYPE_CIPHER_ALG; - else /* strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0 */ - list_type = FUNC_TYPE_CIPHER; - bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - bio_stdout = BIO_push(tmpbio, bio_stdout); - } -#endif - - if (!load_config(bio_err, NULL)) - goto end; - - if (list_type == FUNC_TYPE_PKEY) - list_pkey(bio_stdout); - if (list_type == FUNC_TYPE_MD_ALG) - list_md(bio_stdout); - if (list_type == FUNC_TYPE_CIPHER_ALG) - list_cipher(bio_stdout); - else { - for (fp = functions; fp->name != NULL; fp++) - if (fp->type == list_type) - BIO_printf(bio_stdout, "%s\n", fp->name); - } - BIO_free_all(bio_stdout); - ret = 0; - goto end; - } else { - BIO_printf(bio_err, "openssl:Error: '%s' is an invalid command.\n", - argv[0]); - BIO_printf(bio_err, "\nStandard commands"); - i = 0; - tp = 0; - for (fp = functions; fp->name != NULL; fp++) { - nl = 0; -#ifdef OPENSSL_NO_CAMELLIA - if (((i++) % 5) == 0) -#else - if (((i++) % 4) == 0) -#endif - { - BIO_printf(bio_err, "\n"); - nl = 1; - } - if (fp->type != tp) { - tp = fp->type; - if (!nl) - BIO_printf(bio_err, "\n"); - if (tp == FUNC_TYPE_MD) { - i = 1; - BIO_printf(bio_err, - "\nMessage Digest commands (see the `dgst' command for more details)\n"); - } else if (tp == FUNC_TYPE_CIPHER) { - i = 1; - BIO_printf(bio_err, - "\nCipher commands (see the `enc' command for more details)\n"); - } - } -#ifdef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, "%-15s", fp->name); -#else - BIO_printf(bio_err, "%-18s", fp->name); -#endif + if (lh_FUNCTION_retrieve(prog, &f) == NULL) { + BIO_printf(bio_out, "%s\n", argv[0]); + return 0; } - BIO_printf(bio_err, "\n\n"); - ret = 0; + BIO_printf(bio_out, "%s\n", argv[0] + 3); + return 1; } - end: - return (ret); -} + if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 || + strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0) + /* Special value to mean "exit the program. */ + return EXIT_THE_PROGRAM; -static int SortFnByName(const void *_f1, const void *_f2) -{ - const FUNCTION *f1 = _f1; - const FUNCTION *f2 = _f2; - - if (f1->type != f2->type) - return f1->type - f2->type; - return strcmp(f1->name, f2->name); + BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", + argv[0]); + return 1; } -static void list_pkey(BIO *out) +static void list_pkey(void) { int i; + for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { const EVP_PKEY_ASN1_METHOD *ameth; int pkey_id, pkey_base_id, pkey_flags; @@ -608,89 +598,229 @@ static void list_pkey(BIO *out) EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, &pinfo, &pem_str, ameth); if (pkey_flags & ASN1_PKEY_ALIAS) { - BIO_printf(out, "Name: %s\n", OBJ_nid2ln(pkey_id)); - BIO_printf(out, "\tType: Alias to %s\n", + BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id)); + BIO_printf(bio_out, "\tAlias for: %s\n", OBJ_nid2ln(pkey_base_id)); } else { - BIO_printf(out, "Name: %s\n", pinfo); - BIO_printf(out, "\tType: %s Algorithm\n", + BIO_printf(bio_out, "Name: %s\n", pinfo); + BIO_printf(bio_out, "\tType: %s Algorithm\n", pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin"); - BIO_printf(out, "\tOID: %s\n", OBJ_nid2ln(pkey_id)); + BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id)); if (pem_str == NULL) pem_str = "(none)"; - BIO_printf(out, "\tPEM string: %s\n", pem_str); + BIO_printf(bio_out, "\tPEM string: %s\n", pem_str); } } } -static void list_cipher_fn(const EVP_CIPHER *c, - const char *from, const char *to, void *arg) +static void list_pkey_meth(void) { - if (c) - BIO_printf(arg, "%s\n", EVP_CIPHER_name(c)); - else { - if (!from) - from = "<undefined>"; - if (!to) - to = "<undefined>"; - BIO_printf(arg, "%s => %s\n", from, to); + size_t i; + size_t meth_count = EVP_PKEY_meth_get_count(); + + for (i = 0; i < meth_count; i++) { + const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i); + int pkey_id, pkey_flags; + + EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth); + BIO_printf(bio_out, "%s\n", OBJ_nid2ln(pkey_id)); + BIO_printf(bio_out, "\tType: %s Algorithm\n", + pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin"); } } -static void list_cipher(BIO *out) +static int function_cmp(const FUNCTION * a, const FUNCTION * b) { - EVP_CIPHER_do_all_sorted(list_cipher_fn, out); + return strncmp(a->name, b->name, 8); } -static void list_md_fn(const EVP_MD *m, - const char *from, const char *to, void *arg) +static unsigned long function_hash(const FUNCTION * a) { - if (m) - BIO_printf(arg, "%s\n", EVP_MD_name(m)); - else { - if (!from) - from = "<undefined>"; - if (!to) - to = "<undefined>"; - BIO_printf(arg, "%s => %s\n", from, to); - } + return OPENSSL_LH_strhash(a->name); } -static void list_md(BIO *out) +static int SortFnByName(const void *_f1, const void *_f2) { - EVP_MD_do_all_sorted(list_md_fn, out); -} + const FUNCTION *f1 = _f1; + const FUNCTION *f2 = _f2; -static int MS_CALLBACK function_cmp(const FUNCTION * a, const FUNCTION * b) -{ - return strncmp(a->name, b->name, 8); + if (f1->type != f2->type) + return f1->type - f2->type; + return strcmp(f1->name, f2->name); } -static IMPLEMENT_LHASH_COMP_FN(function, FUNCTION) - -static unsigned long MS_CALLBACK function_hash(const FUNCTION * a) +static void list_disabled(void) { - return lh_strhash(a->name); + BIO_puts(bio_out, "Disabled algorithms:\n"); +#ifdef OPENSSL_NO_ARIA + BIO_puts(bio_out, "ARIA\n"); +#endif +#ifdef OPENSSL_NO_BF + BIO_puts(bio_out, "BF\n"); +#endif +#ifdef OPENSSL_NO_BLAKE2 + BIO_puts(bio_out, "BLAKE2\n"); +#endif +#ifdef OPENSSL_NO_CAMELLIA + BIO_puts(bio_out, "CAMELLIA\n"); +#endif +#ifdef OPENSSL_NO_CAST + BIO_puts(bio_out, "CAST\n"); +#endif +#ifdef OPENSSL_NO_CMAC + BIO_puts(bio_out, "CMAC\n"); +#endif +#ifdef OPENSSL_NO_CMS + BIO_puts(bio_out, "CMS\n"); +#endif +#ifdef OPENSSL_NO_COMP + BIO_puts(bio_out, "COMP\n"); +#endif +#ifdef OPENSSL_NO_DES + BIO_puts(bio_out, "DES\n"); +#endif +#ifdef OPENSSL_NO_DGRAM + BIO_puts(bio_out, "DGRAM\n"); +#endif +#ifdef OPENSSL_NO_DH + BIO_puts(bio_out, "DH\n"); +#endif +#ifdef OPENSSL_NO_DSA + BIO_puts(bio_out, "DSA\n"); +#endif +#if defined(OPENSSL_NO_DTLS) + BIO_puts(bio_out, "DTLS\n"); +#endif +#if defined(OPENSSL_NO_DTLS1) + BIO_puts(bio_out, "DTLS1\n"); +#endif +#if defined(OPENSSL_NO_DTLS1_2) + BIO_puts(bio_out, "DTLS1_2\n"); +#endif +#ifdef OPENSSL_NO_EC + BIO_puts(bio_out, "EC\n"); +#endif +#ifdef OPENSSL_NO_EC2M + BIO_puts(bio_out, "EC2M\n"); +#endif +#ifdef OPENSSL_NO_ENGINE + BIO_puts(bio_out, "ENGINE\n"); +#endif +#ifdef OPENSSL_NO_GOST + BIO_puts(bio_out, "GOST\n"); +#endif +#ifdef OPENSSL_NO_HEARTBEATS + BIO_puts(bio_out, "HEARTBEATS\n"); +#endif +#ifdef OPENSSL_NO_IDEA + BIO_puts(bio_out, "IDEA\n"); +#endif +#ifdef OPENSSL_NO_MD2 + BIO_puts(bio_out, "MD2\n"); +#endif +#ifdef OPENSSL_NO_MD4 + BIO_puts(bio_out, "MD4\n"); +#endif +#ifdef OPENSSL_NO_MD5 + BIO_puts(bio_out, "MD5\n"); +#endif +#ifdef OPENSSL_NO_MDC2 + BIO_puts(bio_out, "MDC2\n"); +#endif +#ifdef OPENSSL_NO_OCB + BIO_puts(bio_out, "OCB\n"); +#endif +#ifdef OPENSSL_NO_OCSP + BIO_puts(bio_out, "OCSP\n"); +#endif +#ifdef OPENSSL_NO_PSK + BIO_puts(bio_out, "PSK\n"); +#endif +#ifdef OPENSSL_NO_RC2 + BIO_puts(bio_out, "RC2\n"); +#endif +#ifdef OPENSSL_NO_RC4 + BIO_puts(bio_out, "RC4\n"); +#endif +#ifdef OPENSSL_NO_RC5 + BIO_puts(bio_out, "RC5\n"); +#endif +#ifdef OPENSSL_NO_RMD160 + BIO_puts(bio_out, "RMD160\n"); +#endif +#ifdef OPENSSL_NO_RSA + BIO_puts(bio_out, "RSA\n"); +#endif +#ifdef OPENSSL_NO_SCRYPT + BIO_puts(bio_out, "SCRYPT\n"); +#endif +#ifdef OPENSSL_NO_SCTP + BIO_puts(bio_out, "SCTP\n"); +#endif +#ifdef OPENSSL_NO_SEED + BIO_puts(bio_out, "SEED\n"); +#endif +#ifdef OPENSSL_NO_SM2 + BIO_puts(bio_out, "SM2\n"); +#endif +#ifdef OPENSSL_NO_SM3 + BIO_puts(bio_out, "SM3\n"); +#endif +#ifdef OPENSSL_NO_SM4 + BIO_puts(bio_out, "SM4\n"); +#endif +#ifdef OPENSSL_NO_SOCK + BIO_puts(bio_out, "SOCK\n"); +#endif +#ifdef OPENSSL_NO_SRP + BIO_puts(bio_out, "SRP\n"); +#endif +#ifdef OPENSSL_NO_SRTP + BIO_puts(bio_out, "SRTP\n"); +#endif +#ifdef OPENSSL_NO_SSL3 + BIO_puts(bio_out, "SSL3\n"); +#endif +#ifdef OPENSSL_NO_TLS1 + BIO_puts(bio_out, "TLS1\n"); +#endif +#ifdef OPENSSL_NO_TLS1_1 + BIO_puts(bio_out, "TLS1_1\n"); +#endif +#ifdef OPENSSL_NO_TLS1_2 + BIO_puts(bio_out, "TLS1_2\n"); +#endif +#ifdef OPENSSL_NO_WHIRLPOOL + BIO_puts(bio_out, "WHIRLPOOL\n"); +#endif +#ifndef ZLIB + BIO_puts(bio_out, "ZLIB\n"); +#endif } -static IMPLEMENT_LHASH_HASH_FN(function, FUNCTION) - static LHASH_OF(FUNCTION) *prog_init(void) { - LHASH_OF(FUNCTION) *ret; + static LHASH_OF(FUNCTION) *ret = NULL; + static int prog_inited = 0; FUNCTION *f; size_t i; - /* Purely so it looks nice when the user hits ? */ - for (i = 0, f = functions; f->name != NULL; ++f, ++i) ; + if (prog_inited) + return ret; + + prog_inited = 1; + + /* Sort alphabetically within category. For nicer help displays. */ + for (i = 0, f = functions; f->name != NULL; ++f, ++i) + ; qsort(functions, i, sizeof(*functions), SortFnByName); - if ((ret = lh_FUNCTION_new()) == NULL) - return (NULL); + if ((ret = lh_FUNCTION_new(function_hash, function_cmp)) == NULL) + return NULL; for (f = functions; f->name != NULL; f++) (void)lh_FUNCTION_insert(ret, f); - return (ret); + return ret; } diff --git a/apps/openssl.cnf b/apps/openssl.cnf index 1eb86c401263..7d1a8bb6e7f0 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -3,6 +3,10 @@ # This is mostly being used for generation of certificate requests. # +# Note that you can include other files from the main configuration +# file using the .include directive. +#.include filename + # This definition stops the following lines choking if HOME isn't # defined. HOME = . @@ -44,7 +48,7 @@ certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. #unique_subject = no # Set to 'no' to allow creation of - # several ctificates with same subject. + # several certs with same subject. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cacert.pem # The CA certificate @@ -55,7 +59,7 @@ crl = $dir/crl.pem # The current CRL private_key = $dir/private/cakey.pem# The private key RANDFILE = $dir/private/.rand # private random number file -x509_extensions = usr_cert # The extentions to add to the cert +x509_extensions = usr_cert # The extensions to add to the cert # Comment out the following two lines for the "traditional" # (and highly broken) format. @@ -107,7 +111,7 @@ default_bits = 2048 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes -x509_extensions = v3_ca # The extentions to add to the self signed cert +x509_extensions = v3_ca # The extensions to add to the self signed cert # Passwords for private keys if not present they will be prompted for # input_password = secret @@ -233,11 +237,7 @@ subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer -# This is what PKIX recommends but some broken software chokes on critical -# extensions. -#basicConstraints = critical,CA:true -# So we do this instead. -basicConstraints = CA:true +basicConstraints = critical,CA:true # Key usage: this is typical for a CA certificate. However since it will # prevent it being used as an test self-signed certificate it is best @@ -335,11 +335,11 @@ signer_cert = $dir/tsacert.pem # The TSA signing certificate certs = $dir/cacert.pem # Certificate chain to include in reply # (optional) signer_key = $dir/private/tsakey.pem # The TSA private key (optional) - +signer_digest = sha256 # Signing digest to use. (Optional) default_policy = tsa_policy1 # Policy if request did not specify it # (optional) other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) -digests = md5, sha1 # Acceptable message digests (mandatory) +digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory) accuracy = secs:1, millisecs:500, microsecs:100 # (optional) clock_precision_digits = 0 # number of digits after dot. (optional) ordering = yes # Is ordering defined for timestamps? @@ -348,3 +348,5 @@ tsa_name = yes # Must the TSA name be included in the reply? # (optional, default: no) ess_cert_id_chain = no # Must the ESS cert id chain be included? # (optional, default: no) +ess_cert_id_alg = sha1 # algorithm to compute certificate + # identifier (optional, default: sha1) diff --git a/apps/opt.c b/apps/opt.c new file mode 100644 index 000000000000..cc1418449e29 --- /dev/null +++ b/apps/opt.c @@ -0,0 +1,899 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include "apps.h" +#include <string.h> +#if !defined(OPENSSL_SYS_MSDOS) +# include OPENSSL_UNISTD +#endif + +#include <stdlib.h> +#include <errno.h> +#include <ctype.h> +#include <limits.h> +#include <openssl/bio.h> +#include <openssl/x509v3.h> + +#define MAX_OPT_HELP_WIDTH 30 +const char OPT_HELP_STR[] = "--"; +const char OPT_MORE_STR[] = "---"; + +/* Our state */ +static char **argv; +static int argc; +static int opt_index; +static char *arg; +static char *flag; +static char *dunno; +static const OPTIONS *unknown; +static const OPTIONS *opts; +static char prog[40]; + +/* + * Return the simple name of the program; removing various platform gunk. + */ +#if defined(OPENSSL_SYS_WIN32) +char *opt_progname(const char *argv0) +{ + size_t i, n; + const char *p; + char *q; + + /* find the last '/', '\' or ':' */ + for (p = argv0 + strlen(argv0); --p > argv0;) + if (*p == '/' || *p == '\\' || *p == ':') { + p++; + break; + } + + /* Strip off trailing nonsense. */ + n = strlen(p); + if (n > 4 && + (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0)) + n -= 4; + + /* Copy over the name, in lowercase. */ + if (n > sizeof(prog) - 1) + n = sizeof(prog) - 1; + for (q = prog, i = 0; i < n; i++, p++) + *q++ = tolower((unsigned char)*p); + *q = '\0'; + return prog; +} + +#elif defined(OPENSSL_SYS_VMS) + +char *opt_progname(const char *argv0) +{ + const char *p, *q; + + /* Find last special character sys:[foo.bar]openssl */ + for (p = argv0 + strlen(argv0); --p > argv0;) + if (*p == ':' || *p == ']' || *p == '>') { + p++; + break; + } + + q = strrchr(p, '.'); + strncpy(prog, p, sizeof(prog) - 1); + prog[sizeof(prog) - 1] = '\0'; + if (q != NULL && q - p < sizeof(prog)) + prog[q - p] = '\0'; + return prog; +} + +#else + +char *opt_progname(const char *argv0) +{ + const char *p; + + /* Could use strchr, but this is like the ones above. */ + for (p = argv0 + strlen(argv0); --p > argv0;) + if (*p == '/') { + p++; + break; + } + strncpy(prog, p, sizeof(prog) - 1); + prog[sizeof(prog) - 1] = '\0'; + return prog; +} +#endif + +char *opt_getprog(void) +{ + return prog; +} + +/* Set up the arg parsing. */ +char *opt_init(int ac, char **av, const OPTIONS *o) +{ + /* Store state. */ + argc = ac; + argv = av; + opt_index = 1; + opts = o; + opt_progname(av[0]); + unknown = NULL; + + for (; o->name; ++o) { +#ifndef NDEBUG + const OPTIONS *next; + int duplicated, i; +#endif + + if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR) + continue; +#ifndef NDEBUG + i = o->valtype; + + /* Make sure options are legit. */ + assert(o->name[0] != '-'); + assert(o->retval > 0); + switch (i) { + case 0: case '-': case '/': case '<': case '>': case 'E': case 'F': + case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': + case 'u': case 'c': + break; + default: + assert(0); + } + + /* Make sure there are no duplicates. */ + for (next = o + 1; next->name; ++next) { + /* + * Some compilers inline strcmp and the assert string is too long. + */ + duplicated = strcmp(o->name, next->name) == 0; + assert(!duplicated); + } +#endif + if (o->name[0] == '\0') { + assert(unknown == NULL); + unknown = o; + assert(unknown->valtype == 0 || unknown->valtype == '-'); + } + } + return prog; +} + +static OPT_PAIR formats[] = { + {"PEM/DER", OPT_FMT_PEMDER}, + {"pkcs12", OPT_FMT_PKCS12}, + {"smime", OPT_FMT_SMIME}, + {"engine", OPT_FMT_ENGINE}, + {"msblob", OPT_FMT_MSBLOB}, + {"netscape", OPT_FMT_NETSCAPE}, + {"nss", OPT_FMT_NSS}, + {"text", OPT_FMT_TEXT}, + {"http", OPT_FMT_HTTP}, + {"pvk", OPT_FMT_PVK}, + {NULL} +}; + +/* Print an error message about a failed format parse. */ +int opt_format_error(const char *s, unsigned long flags) +{ + OPT_PAIR *ap; + + if (flags == OPT_FMT_PEMDER) { + BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n", + prog, s); + } else { + BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n", + prog, s); + for (ap = formats; ap->name; ap++) + if (flags & ap->retval) + BIO_printf(bio_err, " %s\n", ap->name); + } + return 0; +} + +/* Parse a format string, put it into *result; return 0 on failure, else 1. */ +int opt_format(const char *s, unsigned long flags, int *result) +{ + switch (*s) { + default: + return 0; + case 'D': + case 'd': + if ((flags & OPT_FMT_PEMDER) == 0) + return opt_format_error(s, flags); + *result = FORMAT_ASN1; + break; + case 'T': + case 't': + if ((flags & OPT_FMT_TEXT) == 0) + return opt_format_error(s, flags); + *result = FORMAT_TEXT; + break; + case 'N': + case 'n': + if ((flags & OPT_FMT_NSS) == 0) + return opt_format_error(s, flags); + if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0) + return opt_format_error(s, flags); + *result = FORMAT_NSS; + break; + case 'S': + case 's': + if ((flags & OPT_FMT_SMIME) == 0) + return opt_format_error(s, flags); + *result = FORMAT_SMIME; + break; + case 'M': + case 'm': + if ((flags & OPT_FMT_MSBLOB) == 0) + return opt_format_error(s, flags); + *result = FORMAT_MSBLOB; + break; + case 'E': + case 'e': + if ((flags & OPT_FMT_ENGINE) == 0) + return opt_format_error(s, flags); + *result = FORMAT_ENGINE; + break; + case 'H': + case 'h': + if ((flags & OPT_FMT_HTTP) == 0) + return opt_format_error(s, flags); + *result = FORMAT_HTTP; + break; + case '1': + if ((flags & OPT_FMT_PKCS12) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PKCS12; + break; + case 'P': + case 'p': + if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) { + if ((flags & OPT_FMT_PEMDER) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PEM; + } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) { + if ((flags & OPT_FMT_PVK) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PVK; + } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0 + || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) { + if ((flags & OPT_FMT_PKCS12) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PKCS12; + } else { + return 0; + } + break; + } + return 1; +} + +/* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */ +int opt_cipher(const char *name, const EVP_CIPHER **cipherp) +{ + *cipherp = EVP_get_cipherbyname(name); + if (*cipherp != NULL) + return 1; + BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); + return 0; +} + +/* + * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1. + */ +int opt_md(const char *name, const EVP_MD **mdp) +{ + *mdp = EVP_get_digestbyname(name); + if (*mdp != NULL) + return 1; + BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); + return 0; +} + +/* Look through a list of name/value pairs. */ +int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) +{ + const OPT_PAIR *pp; + + for (pp = pairs; pp->name; pp++) + if (strcmp(pp->name, name) == 0) { + *result = pp->retval; + return 1; + } + BIO_printf(bio_err, "%s: Value must be one of:\n", prog); + for (pp = pairs; pp->name; pp++) + BIO_printf(bio_err, "\t%s\n", pp->name); + return 0; +} + +/* Parse an int, put it into *result; return 0 on failure, else 1. */ +int opt_int(const char *value, int *result) +{ + long l; + + if (!opt_long(value, &l)) + return 0; + *result = (int)l; + if (*result != l) { + BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n", + prog, value); + return 0; + } + return 1; +} + +static void opt_number_error(const char *v) +{ + size_t i = 0; + struct strstr_pair_st { + char *prefix; + char *name; + } b[] = { + {"0x", "a hexadecimal"}, + {"0X", "a hexadecimal"}, + {"0", "an octal"} + }; + + for (i = 0; i < OSSL_NELEM(b); i++) { + if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) { + BIO_printf(bio_err, + "%s: Can't parse \"%s\" as %s number\n", + prog, v, b[i].name); + return; + } + } + BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v); + return; +} + +/* Parse a long, put it into *result; return 0 on failure, else 1. */ +int opt_long(const char *value, long *result) +{ + int oerrno = errno; + long l; + char *endp; + + errno = 0; + l = strtol(value, &endp, 0); + if (*endp + || endp == value + || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE) + || (l == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = l; + errno = oerrno; + return 1; +} + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) + +/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */ +int opt_imax(const char *value, intmax_t *result) +{ + int oerrno = errno; + intmax_t m; + char *endp; + + errno = 0; + m = strtoimax(value, &endp, 0); + if (*endp + || endp == value + || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE) + || (m == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = m; + errno = oerrno; + return 1; +} + +/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */ +int opt_umax(const char *value, uintmax_t *result) +{ + int oerrno = errno; + uintmax_t m; + char *endp; + + errno = 0; + m = strtoumax(value, &endp, 0); + if (*endp + || endp == value + || (m == UINTMAX_MAX && errno == ERANGE) + || (m == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = m; + errno = oerrno; + return 1; +} +#endif + +/* + * Parse an unsigned long, put it into *result; return 0 on failure, else 1. + */ +int opt_ulong(const char *value, unsigned long *result) +{ + int oerrno = errno; + char *endptr; + unsigned long l; + + errno = 0; + l = strtoul(value, &endptr, 0); + if (*endptr + || endptr == value + || ((l == ULONG_MAX) && errno == ERANGE) + || (l == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = l; + errno = oerrno; + return 1; +} + +/* + * We pass opt as an int but cast it to "enum range" so that all the + * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch + * in gcc do the right thing. + */ +enum range { OPT_V_ENUM }; + +int opt_verify(int opt, X509_VERIFY_PARAM *vpm) +{ + int i; + ossl_intmax_t t = 0; + ASN1_OBJECT *otmp; + X509_PURPOSE *xptmp; + const X509_VERIFY_PARAM *vtmp; + + assert(vpm != NULL); + assert(opt > OPT_V__FIRST); + assert(opt < OPT_V__LAST); + + switch ((enum range)opt) { + case OPT_V__FIRST: + case OPT_V__LAST: + return 0; + case OPT_V_POLICY: + otmp = OBJ_txt2obj(opt_arg(), 0); + if (otmp == NULL) { + BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_add0_policy(vpm, otmp); + break; + case OPT_V_PURPOSE: + /* purpose name -> purpose index */ + i = X509_PURPOSE_get_by_sname(opt_arg()); + if (i < 0) { + BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg()); + return 0; + } + + /* purpose index -> purpose object */ + xptmp = X509_PURPOSE_get0(i); + + /* purpose object -> purpose value */ + i = X509_PURPOSE_get_id(xptmp); + + if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { + BIO_printf(bio_err, + "%s: Internal error setting purpose %s\n", + prog, opt_arg()); + return 0; + } + break; + case OPT_V_VERIFY_NAME: + vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); + if (vtmp == NULL) { + BIO_printf(bio_err, "%s: Invalid verify name %s\n", + prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_set1(vpm, vtmp); + break; + case OPT_V_VERIFY_DEPTH: + i = atoi(opt_arg()); + if (i >= 0) + X509_VERIFY_PARAM_set_depth(vpm, i); + break; + case OPT_V_VERIFY_AUTH_LEVEL: + i = atoi(opt_arg()); + if (i >= 0) + X509_VERIFY_PARAM_set_auth_level(vpm, i); + break; + case OPT_V_ATTIME: + if (!opt_imax(opt_arg(), &t)) + return 0; + if (t != (time_t)t) { + BIO_printf(bio_err, "%s: epoch time out of range %s\n", + prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_set_time(vpm, (time_t)t); + break; + case OPT_V_VERIFY_HOSTNAME: + if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) + return 0; + break; + case OPT_V_VERIFY_EMAIL: + if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0)) + return 0; + break; + case OPT_V_VERIFY_IP: + if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg())) + return 0; + break; + case OPT_V_IGNORE_CRITICAL: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL); + break; + case OPT_V_ISSUER_CHECKS: + /* NOP, deprecated */ + break; + case OPT_V_CRL_CHECK: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK); + break; + case OPT_V_CRL_CHECK_ALL: + X509_VERIFY_PARAM_set_flags(vpm, + X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL); + break; + case OPT_V_POLICY_CHECK: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK); + break; + case OPT_V_EXPLICIT_POLICY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY); + break; + case OPT_V_INHIBIT_ANY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY); + break; + case OPT_V_INHIBIT_MAP: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP); + break; + case OPT_V_X509_STRICT: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT); + break; + case OPT_V_EXTENDED_CRL: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT); + break; + case OPT_V_USE_DELTAS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS); + break; + case OPT_V_POLICY_PRINT: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY); + break; + case OPT_V_CHECK_SS_SIG: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE); + break; + case OPT_V_TRUSTED_FIRST: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST); + break; + case OPT_V_SUITEB_128_ONLY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY); + break; + case OPT_V_SUITEB_128: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS); + break; + case OPT_V_SUITEB_192: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS); + break; + case OPT_V_PARTIAL_CHAIN: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); + break; + case OPT_V_NO_ALT_CHAINS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS); + break; + case OPT_V_NO_CHECK_TIME: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME); + break; + case OPT_V_ALLOW_PROXY_CERTS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS); + break; + } + return 1; + +} + +/* + * Parse the next flag (and value if specified), return 0 if done, -1 on + * error, otherwise the flag's retval. + */ +int opt_next(void) +{ + char *p; + const OPTIONS *o; + int ival; + long lval; + unsigned long ulval; + ossl_intmax_t imval; + ossl_uintmax_t umval; + + /* Look at current arg; at end of the list? */ + arg = NULL; + p = argv[opt_index]; + if (p == NULL) + return 0; + + /* If word doesn't start with a -, we're done. */ + if (*p != '-') + return 0; + + /* Hit "--" ? We're done. */ + opt_index++; + if (strcmp(p, "--") == 0) + return 0; + + /* Allow -nnn and --nnn */ + if (*++p == '-') + p++; + flag = p - 1; + + /* If we have --flag=foo, snip it off */ + if ((arg = strchr(p, '=')) != NULL) + *arg++ = '\0'; + for (o = opts; o->name; ++o) { + /* If not this option, move on to the next one. */ + if (strcmp(p, o->name) != 0) + continue; + + /* If it doesn't take a value, make sure none was given. */ + if (o->valtype == 0 || o->valtype == '-') { + if (arg) { + BIO_printf(bio_err, + "%s: Option -%s does not take a value\n", prog, p); + return -1; + } + return o->retval; + } + + /* Want a value; get the next param if =foo not used. */ + if (arg == NULL) { + if (argv[opt_index] == NULL) { + BIO_printf(bio_err, + "%s: Option -%s needs a value\n", prog, o->name); + return -1; + } + arg = argv[opt_index++]; + } + + /* Syntax-check value. */ + switch (o->valtype) { + default: + case 's': + /* Just a string. */ + break; + case '/': + if (app_isdir(arg) > 0) + break; + BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg); + return -1; + case '<': + /* Input file. */ + break; + case '>': + /* Output file. */ + break; + case 'p': + case 'n': + if (!opt_int(arg, &ival) + || (o->valtype == 'p' && ival <= 0)) { + BIO_printf(bio_err, + "%s: Non-positive number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'M': + if (!opt_imax(arg, &imval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'U': + if (!opt_umax(arg, &umval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'l': + if (!opt_long(arg, &lval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'u': + if (!opt_ulong(arg, &ulval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'c': + case 'E': + case 'F': + case 'f': + if (opt_format(arg, + o->valtype == 'c' ? OPT_FMT_PDS : + o->valtype == 'E' ? OPT_FMT_PDE : + o->valtype == 'F' ? OPT_FMT_PEMDER + : OPT_FMT_ANY, &ival)) + break; + BIO_printf(bio_err, + "%s: Invalid format \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + + /* Return the flag value. */ + return o->retval; + } + if (unknown != NULL) { + dunno = p; + return unknown->retval; + } + BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p); + return -1; +} + +/* Return the most recent flag parameter. */ +char *opt_arg(void) +{ + return arg; +} + +/* Return the most recent flag. */ +char *opt_flag(void) +{ + return flag; +} + +/* Return the unknown option. */ +char *opt_unknown(void) +{ + return dunno; +} + +/* Return the rest of the arguments after parsing flags. */ +char **opt_rest(void) +{ + return &argv[opt_index]; +} + +/* How many items in remaining args? */ +int opt_num_rest(void) +{ + int i = 0; + char **pp; + + for (pp = opt_rest(); *pp; pp++, i++) + continue; + return i; +} + +/* Return a string describing the parameter type. */ +static const char *valtype2param(const OPTIONS *o) +{ + switch (o->valtype) { + case 0: + case '-': + return ""; + case 's': + return "val"; + case '/': + return "dir"; + case '<': + return "infile"; + case '>': + return "outfile"; + case 'p': + return "+int"; + case 'n': + return "int"; + case 'l': + return "long"; + case 'u': + return "ulong"; + case 'E': + return "PEM|DER|ENGINE"; + case 'F': + return "PEM|DER"; + case 'f': + return "format"; + case 'M': + return "intmax"; + case 'U': + return "uintmax"; + } + return "parm"; +} + +void opt_help(const OPTIONS *list) +{ + const OPTIONS *o; + int i; + int standard_prolog; + int width = 5; + char start[80 + 1]; + char *p; + const char *help; + + /* Starts with its own help message? */ + standard_prolog = list[0].name != OPT_HELP_STR; + + /* Find the widest help. */ + for (o = list; o->name; o++) { + if (o->name == OPT_MORE_STR) + continue; + i = 2 + (int)strlen(o->name); + if (o->valtype != '-') + i += 1 + strlen(valtype2param(o)); + if (i < MAX_OPT_HELP_WIDTH && i > width) + width = i; + assert(i < (int)sizeof(start)); + } + + if (standard_prolog) + BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n", + prog); + + /* Now let's print. */ + for (o = list; o->name; o++) { + help = o->helpstr ? o->helpstr : "(No additional info)"; + if (o->name == OPT_HELP_STR) { + BIO_printf(bio_err, help, prog); + continue; + } + + /* Pad out prefix */ + memset(start, ' ', sizeof(start) - 1); + start[sizeof(start) - 1] = '\0'; + + if (o->name == OPT_MORE_STR) { + /* Continuation of previous line; pad and print. */ + start[width] = '\0'; + BIO_printf(bio_err, "%s %s\n", start, help); + continue; + } + + /* Build up the "-flag [param]" part. */ + p = start; + *p++ = ' '; + *p++ = '-'; + if (o->name[0]) + p += strlen(strcpy(p, o->name)); + else + *p++ = '*'; + if (o->valtype != '-') { + *p++ = ' '; + p += strlen(strcpy(p, valtype2param(o))); + } + *p = ' '; + if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { + *p = '\0'; + BIO_printf(bio_err, "%s\n", start); + memset(start, ' ', sizeof(start)); + } + start[width] = '\0'; + BIO_printf(bio_err, "%s %s\n", start, help); + } +} diff --git a/apps/passwd.c b/apps/passwd.c index 56e10ad3d8f1..aa516c874e65 100644 --- a/apps/passwd.c +++ b/apps/passwd.c @@ -1,29 +1,26 @@ -/* apps/passwd.c */ - -#if defined OPENSSL_NO_MD5 || defined CHARSET_EBCDIC -# define NO_MD5CRYPT_1 -#endif - -#if !defined(OPENSSL_NO_DES) || !defined(NO_MD5CRYPT_1) +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ -# include <assert.h> -# include <string.h> +#include <string.h> -# include "apps.h" +#include "apps.h" +#include "progs.h" -# include <openssl/bio.h> -# include <openssl/err.h> -# include <openssl/evp.h> -# include <openssl/rand.h> -# ifndef OPENSSL_NO_DES -# include <openssl/des.h> -# endif -# ifndef NO_MD5CRYPT_1 -# include <openssl/md5.h> -# endif - -# undef PROG -# define PROG passwd_main +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/rand.h> +#ifndef OPENSSL_NO_DES +# include <openssl/des.h> +#endif +#include <openssl/md5.h> +#include <openssl/sha.h> static unsigned const char cov_2char[64] = { /* from crypto/des/fcrypt.c */ @@ -37,191 +34,220 @@ static unsigned const char cov_2char[64] = { 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A }; +static const char ascii_dollar[] = { 0x24, 0x00 }; + +typedef enum { + passwd_unset = 0, + passwd_crypt, + passwd_md5, + passwd_apr1, + passwd_sha256, + passwd_sha512, + passwd_aixmd5 +} passwd_modes; + static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, char *passwd, BIO *out, int quiet, int table, - int reverse, size_t pw_maxlen, int usecrypt, int use1, - int useapr1); + int reverse, size_t pw_maxlen, passwd_modes mode); -/*- - * -crypt - standard Unix password algorithm (default) - * -1 - MD5-based password algorithm - * -apr1 - MD5-based password algorithm, Apache variant - * -salt string - salt - * -in file - read passwords from file - * -stdin - read passwords from stdin - * -noverify - never verify when reading password from terminal - * -quiet - no warnings - * -table - format output as table - * -reverse - switch table columns - */ +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_IN, + OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1, + OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS passwd_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Read passwords from file"}, + {"noverify", OPT_NOVERIFY, '-', + "Never verify when reading password from terminal"}, + {"quiet", OPT_QUIET, '-', "No warnings"}, + {"table", OPT_TABLE, '-', "Format output as table"}, + {"reverse", OPT_REVERSE, '-', "Switch table columns"}, + {"salt", OPT_SALT, 's', "Use provided salt"}, + {"stdin", OPT_STDIN, '-', "Read passwords from stdin"}, + {"6", OPT_6, '-', "SHA512-based password algorithm"}, + {"5", OPT_5, '-', "SHA256-based password algorithm"}, + {"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"}, + {"1", OPT_1, '-', "MD5-based password algorithm"}, + {"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"}, +#ifndef OPENSSL_NO_DES + {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"}, +#endif + OPT_R_OPTIONS, + {NULL} +}; -int MAIN(int argc, char **argv) +int passwd_main(int argc, char **argv) { - int ret = 1; - char *infile = NULL; - int in_stdin = 0; + BIO *in = NULL; + char *infile = NULL, *salt = NULL, *passwd = NULL, **passwds = NULL; + char *salt_malloc = NULL, *passwd_malloc = NULL, *prog; + OPTION_CHOICE o; + int in_stdin = 0, pw_source_defined = 0; +#ifndef OPENSSL_NO_UI_CONSOLE int in_noverify = 0; - char *salt = NULL, *passwd = NULL, **passwds = NULL; - char *salt_malloc = NULL, *passwd_malloc = NULL; - size_t passwd_malloc_size = 0; - int pw_source_defined = 0; - BIO *in = NULL, *out = NULL; - int i, badopt, opt_done; +#endif int passed_salt = 0, quiet = 0, table = 0, reverse = 0; - int usecrypt = 0, use1 = 0, useapr1 = 0; - size_t pw_maxlen = 0; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto err; - out = BIO_new(BIO_s_file()); - if (out == NULL) - goto err; - BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif + int ret = 1; + passwd_modes mode = passwd_unset; + size_t passwd_malloc_size = 0; + size_t pw_maxlen = 256; /* arbitrary limit, should be enough for most + * passwords */ - badopt = 0, opt_done = 0; - i = 0; - while (!badopt && !opt_done && argv[++i] != NULL) { - if (strcmp(argv[i], "-crypt") == 0) - usecrypt = 1; - else if (strcmp(argv[i], "-1") == 0) - use1 = 1; - else if (strcmp(argv[i], "-apr1") == 0) - useapr1 = 1; - else if (strcmp(argv[i], "-salt") == 0) { - if ((argv[i + 1] != NULL) && (salt == NULL)) { - passed_salt = 1; - salt = argv[++i]; - } else - badopt = 1; - } else if (strcmp(argv[i], "-in") == 0) { - if ((argv[i + 1] != NULL) && !pw_source_defined) { - pw_source_defined = 1; - infile = argv[++i]; - } else - badopt = 1; - } else if (strcmp(argv[i], "-stdin") == 0) { - if (!pw_source_defined) { - pw_source_defined = 1; - in_stdin = 1; - } else - badopt = 1; - } else if (strcmp(argv[i], "-noverify") == 0) + prog = opt_init(argc, argv, passwd_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(passwd_options); + ret = 0; + goto end; + case OPT_IN: + if (pw_source_defined) + goto opthelp; + infile = opt_arg(); + pw_source_defined = 1; + break; + case OPT_NOVERIFY: +#ifndef OPENSSL_NO_UI_CONSOLE in_noverify = 1; - else if (strcmp(argv[i], "-quiet") == 0) +#endif + break; + case OPT_QUIET: quiet = 1; - else if (strcmp(argv[i], "-table") == 0) + break; + case OPT_TABLE: table = 1; - else if (strcmp(argv[i], "-reverse") == 0) + break; + case OPT_REVERSE: reverse = 1; - else if (argv[i][0] == '-') - badopt = 1; - else if (!pw_source_defined) - /* non-option arguments, use as passwords */ - { + break; + case OPT_1: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_md5; + break; + case OPT_5: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_sha256; + break; + case OPT_6: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_sha512; + break; + case OPT_APR1: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_apr1; + break; + case OPT_AIXMD5: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_aixmd5; + break; + case OPT_CRYPT: +#ifndef OPENSSL_NO_DES + if (mode != passwd_unset) + goto opthelp; + mode = passwd_crypt; +#endif + break; + case OPT_SALT: + passed_salt = 1; + salt = opt_arg(); + break; + case OPT_STDIN: + if (pw_source_defined) + goto opthelp; + in_stdin = 1; pw_source_defined = 1; - passwds = &argv[i]; - opt_done = 1; - } else - badopt = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + } } + argc = opt_num_rest(); + argv = opt_rest(); - if (!usecrypt && !use1 && !useapr1) /* use default */ - usecrypt = 1; - if (usecrypt + use1 + useapr1 > 1) /* conflict */ - badopt = 1; + if (*argv != NULL) { + if (pw_source_defined) + goto opthelp; + pw_source_defined = 1; + passwds = argv; + } - /* reject unsupported algorithms */ -# ifdef OPENSSL_NO_DES - if (usecrypt) - badopt = 1; -# endif -# ifdef NO_MD5CRYPT_1 - if (use1 || useapr1) - badopt = 1; -# endif + if (mode == passwd_unset) { + /* use default */ + mode = passwd_crypt; + } - if (badopt) { - BIO_printf(bio_err, "Usage: passwd [options] [passwords]\n"); - BIO_printf(bio_err, "where options are\n"); -# ifndef OPENSSL_NO_DES - BIO_printf(bio_err, - "-crypt standard Unix password algorithm (default)\n"); -# endif -# ifndef NO_MD5CRYPT_1 - BIO_printf(bio_err, - "-1 MD5-based password algorithm\n"); - BIO_printf(bio_err, - "-apr1 MD5-based password algorithm, Apache variant\n"); -# endif - BIO_printf(bio_err, "-salt string use provided salt\n"); - BIO_printf(bio_err, "-in file read passwords from file\n"); - BIO_printf(bio_err, "-stdin read passwords from stdin\n"); - BIO_printf(bio_err, - "-noverify never verify when reading password from terminal\n"); - BIO_printf(bio_err, "-quiet no warnings\n"); - BIO_printf(bio_err, "-table format output as table\n"); - BIO_printf(bio_err, "-reverse switch table columns\n"); +#ifdef OPENSSL_NO_DES + if (mode == passwd_crypt) + goto opthelp; +#endif - goto err; + if (infile != NULL && in_stdin) { + BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog); + goto end; } - if ((infile != NULL) || in_stdin) { - in = BIO_new(BIO_s_file()); + if (infile != NULL || in_stdin) { + /* + * If in_stdin is true, we know that infile is NULL, and that + * bio_open_default() will give us back an alias for stdin. + */ + in = bio_open_default(infile, 'r', FORMAT_TEXT); if (in == NULL) - goto err; - if (infile != NULL) { - assert(in_stdin == 0); - if (BIO_read_filename(in, infile) <= 0) - goto err; - } else { - assert(in_stdin); - BIO_set_fp(in, stdin, BIO_NOCLOSE); - } + goto end; } - if (usecrypt) + if (mode == passwd_crypt) pw_maxlen = 8; - else if (use1 || useapr1) - pw_maxlen = 256; /* arbitrary limit, should be enough for most - * passwords */ if (passwds == NULL) { /* no passwords on the command line */ passwd_malloc_size = pw_maxlen + 2; - /* - * longer than necessary so that we can warn about truncation - */ - passwd = passwd_malloc = OPENSSL_malloc(passwd_malloc_size); - if (passwd_malloc == NULL) - goto err; + /* longer than necessary so that we can warn about truncation */ + passwd = passwd_malloc = + app_malloc(passwd_malloc_size, "password buffer"); } if ((in == NULL) && (passwds == NULL)) { - /* build a null-terminated list */ - static char *passwds_static[2] = { NULL, NULL }; + /* + * we use the following method to make sure what + * in the 'else' section is always compiled, to + * avoid rot of not-frequently-used code. + */ + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + /* build a null-terminated list */ + static char *passwds_static[2] = { NULL, NULL }; - passwds = passwds_static; - if (in == NULL) - if (EVP_read_pw_string - (passwd_malloc, passwd_malloc_size, "Password: ", - !(passed_salt || in_noverify)) != 0) - goto err; - passwds[0] = passwd_malloc; + passwds = passwds_static; + if (in == NULL) { + if (EVP_read_pw_string + (passwd_malloc, passwd_malloc_size, "Password: ", + !(passed_salt || in_noverify)) != 0) + goto end; + } + passwds[0] = passwd_malloc; + } else { +#endif + BIO_printf(bio_err, "password required\n"); + goto end; + } } if (in == NULL) { @@ -230,15 +256,12 @@ int MAIN(int argc, char **argv) do { /* loop over list of passwords */ passwd = *passwds++; - if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out, - quiet, table, reverse, pw_maxlen, usecrypt, use1, - useapr1)) - goto err; - } - while (*passwds != NULL); - } else + if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, bio_out, + quiet, table, reverse, pw_maxlen, mode)) + goto end; + } while (*passwds != NULL); + } else { /* in != NULL */ - { int done; assert(passwd != NULL); @@ -246,9 +269,9 @@ int MAIN(int argc, char **argv) int r = BIO_gets(in, passwd, pw_maxlen + 1); if (r > 0) { char *c = (strchr(passwd, '\n')); - if (c != NULL) + if (c != NULL) { *c = 0; /* truncate at newline */ - else { + } else { /* ignore rest of line */ char trash[BUFSIZ]; do @@ -256,32 +279,26 @@ int MAIN(int argc, char **argv) while ((r > 0) && (!strchr(trash, '\n'))); } - if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out, - quiet, table, reverse, pw_maxlen, usecrypt, - use1, useapr1)) - goto err; + if (!do_passwd + (passed_salt, &salt, &salt_malloc, passwd, bio_out, quiet, + table, reverse, pw_maxlen, mode)) + goto end; } done = (r <= 0); - } - while (!done); + } while (!done); } ret = 0; - err: + end: +#if 0 ERR_print_errors(bio_err); - if (salt_malloc) - OPENSSL_free(salt_malloc); - if (passwd_malloc) - OPENSSL_free(passwd_malloc); - if (in) - BIO_free(in); - if (out) - BIO_free_all(out); - apps_shutdown(); - OPENSSL_EXIT(ret); +#endif + OPENSSL_free(salt_malloc); + OPENSSL_free(passwd_malloc); + BIO_free(in); + return ret; } -# ifndef NO_MD5CRYPT_1 /* * MD5-based password algorithm (should probably be available as a library * function; then the static buffer would not be acceptable). For magic @@ -296,67 +313,131 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt) /* "$apr1$..salt..$.......md5hash..........\0" */ static char out_buf[6 + 9 + 24 + 2]; unsigned char buf[MD5_DIGEST_LENGTH]; + char ascii_magic[5]; /* "apr1" plus '\0' */ + char ascii_salt[9]; /* Max 8 chars plus '\0' */ + char *ascii_passwd = NULL; char *salt_out; int n; unsigned int i; - EVP_MD_CTX md, md2; - size_t passwd_len, salt_len; + EVP_MD_CTX *md = NULL, *md2 = NULL; + size_t passwd_len, salt_len, magic_len; passwd_len = strlen(passwd); - out_buf[0] = '$'; - out_buf[1] = 0; - assert(strlen(magic) <= 4); /* "1" or "apr1" */ - strncat(out_buf, magic, 4); - strncat(out_buf, "$", 1); - strncat(out_buf, salt, 8); - assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */ - salt_out = out_buf + 2 + strlen(magic); - salt_len = strlen(salt_out); - assert(salt_len <= 8); - EVP_MD_CTX_init(&md); - EVP_DigestInit_ex(&md, EVP_md5(), NULL); - EVP_DigestUpdate(&md, passwd, passwd_len); - EVP_DigestUpdate(&md, "$", 1); - EVP_DigestUpdate(&md, magic, strlen(magic)); - EVP_DigestUpdate(&md, "$", 1); - EVP_DigestUpdate(&md, salt_out, salt_len); + out_buf[0] = 0; + magic_len = strlen(magic); + OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic)); +#ifdef CHARSET_EBCDIC + if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */ + ebcdic2ascii(ascii_magic, ascii_magic, magic_len); +#endif + + /* The salt gets truncated to 8 chars */ + OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt)); + salt_len = strlen(ascii_salt); +#ifdef CHARSET_EBCDIC + ebcdic2ascii(ascii_salt, ascii_salt, salt_len); +#endif + +#ifdef CHARSET_EBCDIC + ascii_passwd = OPENSSL_strdup(passwd); + if (ascii_passwd == NULL) + return NULL; + ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len); + passwd = ascii_passwd; +#endif + + if (magic_len > 0) { + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + + if (magic_len > 4) /* assert it's "1" or "apr1" */ + goto err; + + OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + } + + OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf)); - EVP_MD_CTX_init(&md2); - EVP_DigestInit_ex(&md2, EVP_md5(), NULL); - EVP_DigestUpdate(&md2, passwd, passwd_len); - EVP_DigestUpdate(&md2, salt_out, salt_len); - EVP_DigestUpdate(&md2, passwd, passwd_len); - EVP_DigestFinal_ex(&md2, buf, NULL); + if (strlen(out_buf) > 6 + 8) /* assert "$apr1$..salt.." */ + goto err; + + salt_out = out_buf; + if (magic_len > 0) + salt_out += 2 + magic_len; + + if (salt_len > 8) + goto err; + + md = EVP_MD_CTX_new(); + if (md == NULL + || !EVP_DigestInit_ex(md, EVP_md5(), NULL) + || !EVP_DigestUpdate(md, passwd, passwd_len)) + goto err; - for (i = passwd_len; i > sizeof(buf); i -= sizeof(buf)) - EVP_DigestUpdate(&md, buf, sizeof(buf)); - EVP_DigestUpdate(&md, buf, i); + if (magic_len > 0) + if (!EVP_DigestUpdate(md, ascii_dollar, 1) + || !EVP_DigestUpdate(md, ascii_magic, magic_len) + || !EVP_DigestUpdate(md, ascii_dollar, 1)) + goto err; + + if (!EVP_DigestUpdate(md, ascii_salt, salt_len)) + goto err; + + md2 = EVP_MD_CTX_new(); + if (md2 == NULL + || !EVP_DigestInit_ex(md2, EVP_md5(), NULL) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestUpdate(md2, ascii_salt, salt_len) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + + for (i = passwd_len; i > sizeof(buf); i -= sizeof(buf)) { + if (!EVP_DigestUpdate(md, buf, sizeof(buf))) + goto err; + } + if (!EVP_DigestUpdate(md, buf, i)) + goto err; n = passwd_len; while (n) { - EVP_DigestUpdate(&md, (n & 1) ? "\0" : passwd, 1); + if (!EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1)) + goto err; n >>= 1; } - EVP_DigestFinal_ex(&md, buf, NULL); + if (!EVP_DigestFinal_ex(md, buf, NULL)) + return NULL; for (i = 0; i < 1000; i++) { - EVP_DigestInit_ex(&md2, EVP_md5(), NULL); - EVP_DigestUpdate(&md2, (i & 1) ? (unsigned const char *)passwd : buf, - (i & 1) ? passwd_len : sizeof(buf)); - if (i % 3) - EVP_DigestUpdate(&md2, salt_out, salt_len); - if (i % 7) - EVP_DigestUpdate(&md2, passwd, passwd_len); - EVP_DigestUpdate(&md2, (i & 1) ? buf : (unsigned const char *)passwd, - (i & 1) ? sizeof(buf) : passwd_len); - EVP_DigestFinal_ex(&md2, buf, NULL); + if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(md2, + (i & 1) ? (unsigned const char *)passwd : buf, + (i & 1) ? passwd_len : sizeof(buf))) + goto err; + if (i % 3) { + if (!EVP_DigestUpdate(md2, ascii_salt, salt_len)) + goto err; + } + if (i % 7) { + if (!EVP_DigestUpdate(md2, passwd, passwd_len)) + goto err; + } + if (!EVP_DigestUpdate(md2, + (i & 1) ? buf : (unsigned const char *)passwd, + (i & 1) ? sizeof(buf) : passwd_len)) + goto err; + if (!EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; } - EVP_MD_CTX_cleanup(&md2); + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + md2 = NULL; + md = NULL; { /* transform buf into output string */ - unsigned char buf_perm[sizeof(buf)]; int dest, source; char *output; @@ -367,15 +448,15 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt) buf_perm[dest] = buf[source]; buf_perm[14] = buf[5]; buf_perm[15] = buf[11]; -# ifndef PEDANTIC /* Unfortunately, this generates a "no +# ifndef PEDANTIC /* Unfortunately, this generates a "no * effect" warning */ assert(16 == sizeof(buf_perm)); -# endif +# endif output = salt_out + salt_len; assert(output == out_buf + strlen(out_buf)); - *output++ = '$'; + *output++ = ascii_dollar[0]; for (i = 0; i < 15; i += 3) { *output++ = cov_2char[buf_perm[i + 2] & 0x3f]; @@ -390,17 +471,309 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt) *output++ = cov_2char[buf_perm[i] >> 6]; *output = 0; assert(strlen(out_buf) < sizeof(out_buf)); +#ifdef CHARSET_EBCDIC + ascii2ebcdic(out_buf, out_buf, strlen(out_buf)); +#endif } - EVP_MD_CTX_cleanup(&md); return out_buf; + + err: + OPENSSL_free(ascii_passwd); + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + return NULL; +} + +/* + * SHA based password algorithm, describe by Ulrich Drepper here: + * https://www.akkadia.org/drepper/SHA-crypt.txt + * (note that it's in the public domain) + */ +static char *shacrypt(const char *passwd, const char *magic, const char *salt) +{ + /* Prefix for optional rounds specification. */ + static const char rounds_prefix[] = "rounds="; + /* Maximum salt string length. */ +# define SALT_LEN_MAX 16 + /* Default number of rounds if not explicitly specified. */ +# define ROUNDS_DEFAULT 5000 + /* Minimum number of rounds. */ +# define ROUNDS_MIN 1000 + /* Maximum number of rounds. */ +# define ROUNDS_MAX 999999999 + + /* "$6$rounds=<N>$......salt......$...shahash(up to 86 chars)...\0" */ + static char out_buf[3 + 17 + 17 + 86 + 1]; + unsigned char buf[SHA512_DIGEST_LENGTH]; + unsigned char temp_buf[SHA512_DIGEST_LENGTH]; + size_t buf_size = 0; + char ascii_magic[2]; + char ascii_salt[17]; /* Max 16 chars plus '\0' */ + char *ascii_passwd = NULL; + size_t n; + EVP_MD_CTX *md = NULL, *md2 = NULL; + const EVP_MD *sha = NULL; + size_t passwd_len, salt_len, magic_len; + unsigned int rounds = 5000; /* Default */ + char rounds_custom = 0; + char *p_bytes = NULL; + char *s_bytes = NULL; + char *cp = NULL; + + passwd_len = strlen(passwd); + magic_len = strlen(magic); + + /* assert it's "5" or "6" */ + if (magic_len != 1) + return NULL; + + switch (magic[0]) { + case '5': + sha = EVP_sha256(); + buf_size = 32; + break; + case '6': + sha = EVP_sha512(); + buf_size = 64; + break; + default: + return NULL; + } + + if (strncmp(salt, rounds_prefix, sizeof(rounds_prefix) - 1) == 0) { + const char *num = salt + sizeof(rounds_prefix) - 1; + char *endp; + unsigned long int srounds = strtoul (num, &endp, 10); + if (*endp == '$') { + salt = endp + 1; + if (srounds > ROUNDS_MAX) + rounds = ROUNDS_MAX; + else if (srounds < ROUNDS_MIN) + rounds = ROUNDS_MIN; + else + rounds = (unsigned int)srounds; + rounds_custom = 1; + } else { + return NULL; + } + } + + OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic)); +#ifdef CHARSET_EBCDIC + if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */ + ebcdic2ascii(ascii_magic, ascii_magic, magic_len); +#endif + + /* The salt gets truncated to 16 chars */ + OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt)); + salt_len = strlen(ascii_salt); +#ifdef CHARSET_EBCDIC + ebcdic2ascii(ascii_salt, ascii_salt, salt_len); +#endif + +#ifdef CHARSET_EBCDIC + ascii_passwd = OPENSSL_strdup(passwd); + if (ascii_passwd == NULL) + return NULL; + ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len); + passwd = ascii_passwd; +#endif + + out_buf[0] = 0; + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + if (rounds_custom) { + char tmp_buf[80]; /* "rounds=999999999" */ + sprintf(tmp_buf, "rounds=%u", rounds); +#ifdef CHARSET_EBCDIC + /* In case we're really on a ASCII based platform and just pretend */ + if (tmp_buf[0] != 0x72) /* ASCII 'r' */ + ebcdic2ascii(tmp_buf, tmp_buf, strlen(tmp_buf)); +#endif + OPENSSL_strlcat(out_buf, tmp_buf, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + } + OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf)); + + /* assert "$5$rounds=999999999$......salt......" */ + if (strlen(out_buf) > 3 + 17 * rounds_custom + salt_len ) + goto err; + + md = EVP_MD_CTX_new(); + if (md == NULL + || !EVP_DigestInit_ex(md, sha, NULL) + || !EVP_DigestUpdate(md, passwd, passwd_len) + || !EVP_DigestUpdate(md, ascii_salt, salt_len)) + goto err; + + md2 = EVP_MD_CTX_new(); + if (md2 == NULL + || !EVP_DigestInit_ex(md2, sha, NULL) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestUpdate(md2, ascii_salt, salt_len) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + + for (n = passwd_len; n > buf_size; n -= buf_size) { + if (!EVP_DigestUpdate(md, buf, buf_size)) + goto err; + } + if (!EVP_DigestUpdate(md, buf, n)) + goto err; + + n = passwd_len; + while (n) { + if (!EVP_DigestUpdate(md, + (n & 1) ? buf : (unsigned const char *)passwd, + (n & 1) ? buf_size : passwd_len)) + goto err; + n >>= 1; + } + if (!EVP_DigestFinal_ex(md, buf, NULL)) + return NULL; + + /* P sequence */ + if (!EVP_DigestInit_ex(md2, sha, NULL)) + goto err; + + for (n = passwd_len; n > 0; n--) + if (!EVP_DigestUpdate(md2, passwd, passwd_len)) + goto err; + + if (!EVP_DigestFinal_ex(md2, temp_buf, NULL)) + return NULL; + + if ((p_bytes = OPENSSL_zalloc(passwd_len)) == NULL) + goto err; + for (cp = p_bytes, n = passwd_len; n > buf_size; n -= buf_size, cp += buf_size) + memcpy(cp, temp_buf, buf_size); + memcpy(cp, temp_buf, n); + + /* S sequence */ + if (!EVP_DigestInit_ex(md2, sha, NULL)) + goto err; + + for (n = 16 + buf[0]; n > 0; n--) + if (!EVP_DigestUpdate(md2, ascii_salt, salt_len)) + goto err; + + if (!EVP_DigestFinal_ex(md2, temp_buf, NULL)) + return NULL; + + if ((s_bytes = OPENSSL_zalloc(salt_len)) == NULL) + goto err; + for (cp = s_bytes, n = salt_len; n > buf_size; n -= buf_size, cp += buf_size) + memcpy(cp, temp_buf, buf_size); + memcpy(cp, temp_buf, n); + + for (n = 0; n < rounds; n++) { + if (!EVP_DigestInit_ex(md2, sha, NULL)) + goto err; + if (!EVP_DigestUpdate(md2, + (n & 1) ? (unsigned const char *)p_bytes : buf, + (n & 1) ? passwd_len : buf_size)) + goto err; + if (n % 3) { + if (!EVP_DigestUpdate(md2, s_bytes, salt_len)) + goto err; + } + if (n % 7) { + if (!EVP_DigestUpdate(md2, p_bytes, passwd_len)) + goto err; + } + if (!EVP_DigestUpdate(md2, + (n & 1) ? buf : (unsigned const char *)p_bytes, + (n & 1) ? buf_size : passwd_len)) + goto err; + if (!EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + } + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + md2 = NULL; + md = NULL; + OPENSSL_free(p_bytes); + OPENSSL_free(s_bytes); + p_bytes = NULL; + s_bytes = NULL; + + cp = out_buf + strlen(out_buf); + *cp++ = ascii_dollar[0]; + +# define b64_from_24bit(B2, B1, B0, N) \ + do { \ + unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ + int i = (N); \ + while (i-- > 0) \ + { \ + *cp++ = cov_2char[w & 0x3f]; \ + w >>= 6; \ + } \ + } while (0) + + switch (magic[0]) { + case '5': + b64_from_24bit (buf[0], buf[10], buf[20], 4); + b64_from_24bit (buf[21], buf[1], buf[11], 4); + b64_from_24bit (buf[12], buf[22], buf[2], 4); + b64_from_24bit (buf[3], buf[13], buf[23], 4); + b64_from_24bit (buf[24], buf[4], buf[14], 4); + b64_from_24bit (buf[15], buf[25], buf[5], 4); + b64_from_24bit (buf[6], buf[16], buf[26], 4); + b64_from_24bit (buf[27], buf[7], buf[17], 4); + b64_from_24bit (buf[18], buf[28], buf[8], 4); + b64_from_24bit (buf[9], buf[19], buf[29], 4); + b64_from_24bit (0, buf[31], buf[30], 3); + break; + case '6': + b64_from_24bit (buf[0], buf[21], buf[42], 4); + b64_from_24bit (buf[22], buf[43], buf[1], 4); + b64_from_24bit (buf[44], buf[2], buf[23], 4); + b64_from_24bit (buf[3], buf[24], buf[45], 4); + b64_from_24bit (buf[25], buf[46], buf[4], 4); + b64_from_24bit (buf[47], buf[5], buf[26], 4); + b64_from_24bit (buf[6], buf[27], buf[48], 4); + b64_from_24bit (buf[28], buf[49], buf[7], 4); + b64_from_24bit (buf[50], buf[8], buf[29], 4); + b64_from_24bit (buf[9], buf[30], buf[51], 4); + b64_from_24bit (buf[31], buf[52], buf[10], 4); + b64_from_24bit (buf[53], buf[11], buf[32], 4); + b64_from_24bit (buf[12], buf[33], buf[54], 4); + b64_from_24bit (buf[34], buf[55], buf[13], 4); + b64_from_24bit (buf[56], buf[14], buf[35], 4); + b64_from_24bit (buf[15], buf[36], buf[57], 4); + b64_from_24bit (buf[37], buf[58], buf[16], 4); + b64_from_24bit (buf[59], buf[17], buf[38], 4); + b64_from_24bit (buf[18], buf[39], buf[60], 4); + b64_from_24bit (buf[40], buf[61], buf[19], 4); + b64_from_24bit (buf[62], buf[20], buf[41], 4); + b64_from_24bit (0, 0, buf[63], 2); + break; + default: + goto err; + } + *cp = '\0'; +#ifdef CHARSET_EBCDIC + ascii2ebcdic(out_buf, out_buf, strlen(out_buf)); +#endif + + return out_buf; + + err: + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + OPENSSL_free(p_bytes); + OPENSSL_free(s_bytes); + OPENSSL_free(ascii_passwd); + return NULL; } -# endif static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, char *passwd, BIO *out, int quiet, int table, - int reverse, size_t pw_maxlen, int usecrypt, int use1, - int useapr1) + int reverse, size_t pw_maxlen, passwd_modes mode) { char *hash = NULL; @@ -409,42 +782,34 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, /* first make sure we have a salt */ if (!passed_salt) { -# ifndef OPENSSL_NO_DES - if (usecrypt) { - if (*salt_malloc_p == NULL) { - *salt_p = *salt_malloc_p = OPENSSL_malloc(3); - if (*salt_malloc_p == NULL) - goto err; - } - if (RAND_bytes((unsigned char *)*salt_p, 2) <= 0) - goto err; - (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */ - (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */ - (*salt_p)[2] = 0; -# ifdef CHARSET_EBCDIC - ascii2ebcdic(*salt_p, *salt_p, 2); /* des_crypt will convert back - * to ASCII */ -# endif - } -# endif /* !OPENSSL_NO_DES */ + size_t saltlen = 0; + size_t i; -# ifndef NO_MD5CRYPT_1 - if (use1 || useapr1) { - int i; +#ifndef OPENSSL_NO_DES + if (mode == passwd_crypt) + saltlen = 2; +#endif /* !OPENSSL_NO_DES */ - if (*salt_malloc_p == NULL) { - *salt_p = *salt_malloc_p = OPENSSL_malloc(9); - if (*salt_malloc_p == NULL) - goto err; - } - if (RAND_bytes((unsigned char *)*salt_p, 8) <= 0) - goto err; + if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5) + saltlen = 8; - for (i = 0; i < 8; i++) - (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */ - (*salt_p)[8] = 0; - } -# endif /* !NO_MD5CRYPT_1 */ + if (mode == passwd_sha256 || mode == passwd_sha512) + saltlen = 16; + + assert(saltlen != 0); + + if (*salt_malloc_p == NULL) + *salt_p = *salt_malloc_p = app_malloc(saltlen + 1, "salt buffer"); + if (RAND_bytes((unsigned char *)*salt_p, saltlen) <= 0) + goto end; + + for (i = 0; i < saltlen; i++) + (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */ + (*salt_p)[i] = 0; +# ifdef CHARSET_EBCDIC + /* The password encryption funtion will convert back to ASCII */ + ascii2ebcdic(*salt_p, *salt_p, saltlen); +# endif } assert(*salt_p != NULL); @@ -463,14 +828,16 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, assert(strlen(passwd) <= pw_maxlen); /* now compute password hash */ -# ifndef OPENSSL_NO_DES - if (usecrypt) +#ifndef OPENSSL_NO_DES + if (mode == passwd_crypt) hash = DES_crypt(passwd, *salt_p); -# endif -# ifndef NO_MD5CRYPT_1 - if (use1 || useapr1) - hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p); -# endif +#endif + if (mode == passwd_md5 || mode == passwd_apr1) + hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p); + if (mode == passwd_aixmd5) + hash = md5crypt(passwd, "", *salt_p); + if (mode == passwd_sha256 || mode == passwd_sha512) + hash = shacrypt(passwd, (mode == passwd_sha256 ? "5" : "6"), *salt_p); assert(hash != NULL); if (table && !reverse) @@ -481,14 +848,6 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, BIO_printf(out, "%s\n", hash); return 1; - err: + end: return 0; } -#else - -int MAIN(int argc, char **argv) -{ - fputs("Program not available.\n", stderr) - OPENSSL_EXIT(1); -} -#endif diff --git a/apps/pca-key.pem b/apps/pca-key.pem index 20029ab779f2..c6ad0e92d53b 100644 --- a/apps/pca-key.pem +++ b/apps/pca-key.pem @@ -1,15 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQCdoWk/3+WcMlfjIrkg40ketmnQaEogQe1LLcuOJV6rKfUSAsPg -wgsabJ/wn8TxA1yy3eKJbFl3OiUXMRsp22Jp85PmemiDzyUIStwk72qhp1imbANZ -vlmlCFKiQrjUyuDfu4TABmn+kkt3vR1YBEOGt+IFye1UBVSATVdRJ2UVhwIDAQAB -AoGAba4fTtuap5l7/8ZsbE7Z1O32KJY4ZcOZukLOLUUhXxXduT+FTgGWujc0/rgc -z9qYCLlNZHOouMYTgtSfYvuMuLZ11VIt0GYH+nRioLShE59Yy+zCRyC+gPigS1kz -xvo14AsOIPYV14Tk/SsHyq6E0eTk7VzaIE197giiINUERPECQQDSKmtPTh/lRKw7 -HSZSM0I1mFWn/1zqrAbontRQY5w98QWIOe5qmzYyFbPXYT3d9BzlsMyhgiRNoBbD -yvohSHXJAkEAwAHx6ezAZeWWzD5yXD36nyjpkVCw7Tk7TSmOceLJMWt1QcrCfqlS -xA5jjpQ6Z8suU5DdtWAryM2sAir1WisYzwJAd6Zcx56jvAQ3xcPXsE6scBTVFzrj -7FqZ6E+cclPzfLQ+QQsyOBE7bpI6e/FJppY26XGZXo3YGzV8IGXrt40oOQJALETG -h86EFXo3qGOFbmsDy4pdP5nBERCu8X1xUCSfintiD4c2DInxgS5oGclnJeMcjTvL -QjQoJCX3UJCi/OUO1QJBAKgcDHWjMvt+l1pjJBsSEZ0HX9AAIIVx0RQmbFGS+F2Q -hhu5l77WnnZOQ9vvhV5u7NPCUF9nhU3jh60qWWO8mkc= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALYYjjtpLs/lfkPF +xAFZ4V3He5mZFbsEakK9bA2fQaryreRwyfhbXbDJHyBV+c4xI5fbmmVd2t/us4k4 +rMhGsBtL89SqCEHhPJpLFywiQVmJTAjANYrWkZK5uR/++YmZyzuLfPHLButuK6cF +GKXw3NNToxjYooMf0mad2rPX3cKTAgMBAAECgYBvrJ+Nz/Pli9jjt2V9bqHH4Y7r +o/avuwVv6Ltbn0+mhy4d6w3yQhYzVSTBr/iDe59YglUt1WFl8/4nKZrNOIzHJlav +Sw4hd3fYBHxbT+DgZMQ9ikjHECWRdDffrnlTLsSJAcxnpMJBPe3dKCRDMUrqWUvB +IIKaxyqmXJms5Y/wAQJBAPFL9NMKJcWBftMKXCasxsV0ZGjgqHGZODYjtGFN9jJO +6AbZrxfCcapTWG4RCC2o/EDEMN8aArEhfdrYY3lhXGsCQQDBMRzFevkD7SYXTw5G +NA/gJOAsFMYbt7tebcCRsHT7t3ymVfO2QwK7ZF0f/SYvi7cMAPraHvO7s3kFdGTB +kDx5AkAHBICASsFCdzurA5gef9PgFjx9WFtNwnkCChPK6KuKVwUkfdw7wqnvnDDs +Mo6cVVfQwmPxeR4u7JxuavCprQ01AkEAp5ZGAh1J9Jj9CQ1AMbAp8WOrvzGKJTM9 +641Dll4/LLif/d7j2kDJFuvaSMyeGnKVqGkVMq/U+QeYPR4Z5TuM6QJAWK05qFed +wYgTZyVN0MY53ZOMAIWwjz0cr24TvDfmsZqIvguGL616GKQZKdKDZQyQHg+dCzqJ +HgIoacuFDKz5CA== +-----END PRIVATE KEY----- diff --git a/apps/pca-req.pem b/apps/pca-req.pem index 33f155337b34..5a8c5cbf13d7 100644 --- a/apps/pca-req.pem +++ b/apps/pca-req.pem @@ -1,11 +1,11 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBmjCCAQMCAQAwXDELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQx -GjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYDVQQDExNUZXN0IFBDQSAo -MTAyNCBiaXQpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdoWk/3+WcMlfj -Irkg40ketmnQaEogQe1LLcuOJV6rKfUSAsPgwgsabJ/wn8TxA1yy3eKJbFl3OiUX -MRsp22Jp85PmemiDzyUIStwk72qhp1imbANZvlmlCFKiQrjUyuDfu4TABmn+kkt3 -vR1YBEOGt+IFye1UBVSATVdRJ2UVhwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAEzz -IG8NnfpnPTQSCN5zJhOfy6p9AcDyQzuJirYv1HR/qoYWalPh/U2uiK0lAim7qMcv -wOlK3I7A8B7/4dLqvIqgtUj9b1WT8zIrnwdvJI4osLI2BY+c1pVlp174DHLMol1L -Cl1e3N5BTm7lCitTYjuUhsw6hiA8IcdNKDo6sktV +MIIBnDCCAQUCAQAwXDELMAkGA1UEBhMCQVUxEzARBgNVBAgMClF1ZWVuc2xhbmQx +GjAYBgNVBAoMEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYDVQQDDBNUZXN0IFBDQSAo +MTAyNCBiaXQpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2GI47aS7P5X5D +xcQBWeFdx3uZmRW7BGpCvWwNn0Gq8q3kcMn4W12wyR8gVfnOMSOX25plXdrf7rOJ +OKzIRrAbS/PUqghB4TyaSxcsIkFZiUwIwDWK1pGSubkf/vmJmcs7i3zxywbrbiun +BRil8NzTU6MY2KKDH9Jmndqz193CkwIDAQABoAAwDQYJKoZIhvcNAQELBQADgYEA +eJdCB0nHnFK0hek4biAxX0GuJXkknuUy46NKEhv3GBwt4gtO29bfkbQTGOsBBKNs +KptlnkItscOXY+0lSva9K3XlwD9do7k2IZFtXJVayZVw1GcKybIY0l7B6kcSxG7T +f3CsO+ifdrsJKtyoZNs96lBMrtXyGybt3mgQNdZauQU= -----END CERTIFICATE REQUEST----- diff --git a/apps/pkcs12.c b/apps/pkcs12.c index 0ba4c9a8076a..c8fc452ec6d2 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -1,431 +1,314 @@ -/* pkcs12.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project. - */ -/* ==================================================================== - * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <openssl/opensslconf.h> -#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) +#if defined(OPENSSL_NO_DES) +NON_EMPTY_TRANSLATION_UNIT +#else # include <stdio.h> # include <stdlib.h> # include <string.h> # include "apps.h" +# include "progs.h" # include <openssl/crypto.h> # include <openssl/err.h> # include <openssl/pem.h> # include <openssl/pkcs12.h> -# define PROG pkcs12_main - -const EVP_CIPHER *enc; - # define NOKEYS 0x1 # define NOCERTS 0x2 # define INFO 0x4 # define CLCERTS 0x8 # define CACERTS 0x10 +#define PASSWD_BUF_SIZE 2048 + static int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain); -int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, - int options, char *pempass); -int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, - char *pass, int passlen, int options, - char *pempass); -int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, - int passlen, int options, char *pempass); -int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, +int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc); +int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc); +int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bags, + const char *pass, int passlen, + int options, char *pempass, const EVP_CIPHER *enc); +int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name); void hex_prin(BIO *out, unsigned char *buf, int len); -int alg_print(BIO *x, X509_ALGOR *alg); +static int alg_print(const X509_ALGOR *alg); int cert_load(BIO *in, STACK_OF(X509) *sk); -static int set_pbe(BIO *err, int *ppbe, const char *str); +static int set_pbe(int *ppbe, const char *str); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS, + OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER, + OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER, + OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE, + OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME, + OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH, + OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS pkcs12_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"}, + {"keyex", OPT_KEYEX, '-', "Set MS key exchange type"}, + {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"}, + {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"}, + {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"}, + {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"}, + {"noout", OPT_NOOUT, '-', "Don't output anything, just verify"}, + {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"}, + {"chain", OPT_CHAIN, '-', "Add certificate chain"}, + {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"}, + {"nomacver", OPT_NOMACVER, '-', "Don't verify MAC"}, +# ifndef OPENSSL_NO_RC2 + {"descert", OPT_DESCERT, '-', + "Encrypt output with 3DES (default RC2-40)"}, + {"certpbe", OPT_CERTPBE, 's', + "Certificate PBE algorithm (default RC2-40)"}, +# else + {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"}, + {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"}, +# endif + {"export", OPT_EXPORT, '-', "Output PKCS12 file"}, + {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"}, + {"maciter", OPT_MACITER, '-', "Use MAC iteration"}, + {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration"}, + {"nomac", OPT_NOMAC, '-', "Don't generate MAC"}, + {"LMK", OPT_LMK, '-', + "Add local machine keyset attribute to private key"}, + {"nodes", OPT_NODES, '-', "Don't encrypt private keys"}, + {"macalg", OPT_MACALG, 's', + "Digest algorithm used in MAC (default SHA1)"}, + {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"}, + OPT_R_OPTIONS, + {"inkey", OPT_INKEY, 's', "Private key if not infile"}, + {"certfile", OPT_CERTFILE, '<', "Load certs from file"}, + {"name", OPT_NAME, 's', "Use name as friendly name"}, + {"CSP", OPT_CSP, 's', "Microsoft CSP name"}, + {"caname", OPT_CANAME, 's', + "Use name as CA friendly name (can be repeated)"}, + {"in", OPT_IN, '<', "Input filename"}, + {"out", OPT_OUT, '>', "Output filename"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"password", OPT_PASSWORD, 's', "Set import/export password source"}, + {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"}, + {"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; -int MAIN(int argc, char **argv) +int pkcs12_main(int argc, char **argv) { + char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL; + char *name = NULL, *csp_name = NULL; + char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = ""; + int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0; + int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER; +# ifndef OPENSSL_NO_RC2 + int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; +# else + int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; +# endif + int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + int ret = 1, macver = 1, add_lmk = 0, private = 0; + int noprompt = 0; + char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL; + char *passin = NULL, *passout = NULL, *macalg = NULL; + char *cpass = NULL, *mpass = NULL, *badpass = NULL; + const char *CApath = NULL, *CAfile = NULL, *prog; + int noCApath = 0, noCAfile = 0; ENGINE *e = NULL; - char *infile = NULL, *outfile = NULL, *keyname = NULL; - char *certfile = NULL; BIO *in = NULL, *out = NULL; - char **args; - char *name = NULL; - char *csp_name = NULL; - int add_lmk = 0; PKCS12 *p12 = NULL; - char pass[50], macpass[50]; - int export_cert = 0; - int options = 0; - int chain = 0; - int badarg = 0; - int iter = PKCS12_DEFAULT_ITER; - int maciter = PKCS12_DEFAULT_ITER; - int twopass = 0; - int keytype = 0; - int cert_pbe; - int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; - int ret = 1; - int macver = 1; - int noprompt = 0; STACK_OF(OPENSSL_STRING) *canames = NULL; - char *cpass = NULL, *mpass = NULL; - char *passargin = NULL, *passargout = NULL, *passarg = NULL; - char *passin = NULL, *passout = NULL; - char *inrand = NULL; - char *macalg = NULL; - char *CApath = NULL, *CAfile = NULL; - char *engine = NULL; - - apps_startup(); - - enc = EVP_des_ede3_cbc(); - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - -# ifdef OPENSSL_FIPS - if (FIPS_mode()) - cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; - else -# endif - cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; - - args = argv + 1; - - while (*args) { - if (*args[0] == '-') { - if (!strcmp(*args, "-nokeys")) - options |= NOKEYS; - else if (!strcmp(*args, "-keyex")) - keytype = KEY_EX; - else if (!strcmp(*args, "-keysig")) - keytype = KEY_SIG; - else if (!strcmp(*args, "-nocerts")) - options |= NOCERTS; - else if (!strcmp(*args, "-clcerts")) - options |= CLCERTS; - else if (!strcmp(*args, "-cacerts")) - options |= CACERTS; - else if (!strcmp(*args, "-noout")) - options |= (NOKEYS | NOCERTS); - else if (!strcmp(*args, "-info")) - options |= INFO; - else if (!strcmp(*args, "-chain")) - chain = 1; - else if (!strcmp(*args, "-twopass")) - twopass = 1; - else if (!strcmp(*args, "-nomacver")) - macver = 0; - else if (!strcmp(*args, "-descert")) - cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; - else if (!strcmp(*args, "-export")) - export_cert = 1; - else if (!strcmp(*args, "-des")) - enc = EVP_des_cbc(); - else if (!strcmp(*args, "-des3")) - enc = EVP_des_ede3_cbc(); -# ifndef OPENSSL_NO_IDEA - else if (!strcmp(*args, "-idea")) - enc = EVP_idea_cbc(); -# endif -# ifndef OPENSSL_NO_SEED - else if (!strcmp(*args, "-seed")) - enc = EVP_seed_cbc(); -# endif -# ifndef OPENSSL_NO_AES - else if (!strcmp(*args, "-aes128")) - enc = EVP_aes_128_cbc(); - else if (!strcmp(*args, "-aes192")) - enc = EVP_aes_192_cbc(); - else if (!strcmp(*args, "-aes256")) - enc = EVP_aes_256_cbc(); -# endif -# ifndef OPENSSL_NO_CAMELLIA - else if (!strcmp(*args, "-camellia128")) - enc = EVP_camellia_128_cbc(); - else if (!strcmp(*args, "-camellia192")) - enc = EVP_camellia_192_cbc(); - else if (!strcmp(*args, "-camellia256")) - enc = EVP_camellia_256_cbc(); -# endif - else if (!strcmp(*args, "-noiter")) - iter = 1; - else if (!strcmp(*args, "-maciter")) - maciter = PKCS12_DEFAULT_ITER; - else if (!strcmp(*args, "-nomaciter")) - maciter = 1; - else if (!strcmp(*args, "-nomac")) - maciter = -1; - else if (!strcmp(*args, "-macalg")) - if (args[1]) { - args++; - macalg = *args; - } else - badarg = 1; - else if (!strcmp(*args, "-nodes")) - enc = NULL; - else if (!strcmp(*args, "-certpbe")) { - if (!set_pbe(bio_err, &cert_pbe, *++args)) - badarg = 1; - } else if (!strcmp(*args, "-keypbe")) { - if (!set_pbe(bio_err, &key_pbe, *++args)) - badarg = 1; - } else if (!strcmp(*args, "-rand")) { - if (args[1]) { - args++; - inrand = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-inkey")) { - if (args[1]) { - args++; - keyname = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-certfile")) { - if (args[1]) { - args++; - certfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-name")) { - if (args[1]) { - args++; - name = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-LMK")) - add_lmk = 1; - else if (!strcmp(*args, "-CSP")) { - if (args[1]) { - args++; - csp_name = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-caname")) { - if (args[1]) { - args++; - if (!canames) - canames = sk_OPENSSL_STRING_new_null(); - sk_OPENSSL_STRING_push(canames, *args); - } else - badarg = 1; - } else if (!strcmp(*args, "-in")) { - if (args[1]) { - args++; - infile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-passin")) { - if (args[1]) { - args++; - passargin = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-passout")) { - if (args[1]) { - args++; - passargout = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-password")) { - if (args[1]) { - args++; - passarg = *args; - noprompt = 1; - } else - badarg = 1; - } else if (!strcmp(*args, "-CApath")) { - if (args[1]) { - args++; - CApath = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-CAfile")) { - if (args[1]) { - args++; - CAfile = *args; - } else - badarg = 1; -# ifndef OPENSSL_NO_ENGINE - } else if (!strcmp(*args, "-engine")) { - if (args[1]) { - args++; - engine = *args; - } else - badarg = 1; -# endif - } else - badarg = 1; + const EVP_CIPHER *enc = EVP_des_ede3_cbc(); + OPTION_CHOICE o; - } else - badarg = 1; - args++; + prog = opt_init(argc, argv, pkcs12_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkcs12_options); + ret = 0; + goto end; + case OPT_NOKEYS: + options |= NOKEYS; + break; + case OPT_KEYEX: + keytype = KEY_EX; + break; + case OPT_KEYSIG: + keytype = KEY_SIG; + break; + case OPT_NOCERTS: + options |= NOCERTS; + break; + case OPT_CLCERTS: + options |= CLCERTS; + break; + case OPT_CACERTS: + options |= CACERTS; + break; + case OPT_NOOUT: + options |= (NOKEYS | NOCERTS); + break; + case OPT_INFO: + options |= INFO; + break; + case OPT_CHAIN: + chain = 1; + break; + case OPT_TWOPASS: + twopass = 1; + break; + case OPT_NOMACVER: + macver = 0; + break; + case OPT_DESCERT: + cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + break; + case OPT_EXPORT: + export_cert = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto opthelp; + break; + case OPT_NOITER: + iter = 1; + break; + case OPT_MACITER: + maciter = PKCS12_DEFAULT_ITER; + break; + case OPT_NOMACITER: + maciter = 1; + break; + case OPT_NOMAC: + maciter = -1; + break; + case OPT_MACALG: + macalg = opt_arg(); + break; + case OPT_NODES: + enc = NULL; + break; + case OPT_CERTPBE: + if (!set_pbe(&cert_pbe, opt_arg())) + goto opthelp; + break; + case OPT_KEYPBE: + if (!set_pbe(&key_pbe, opt_arg())) + goto opthelp; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_INKEY: + keyname = opt_arg(); + break; + case OPT_CERTFILE: + certfile = opt_arg(); + break; + case OPT_NAME: + name = opt_arg(); + break; + case OPT_LMK: + add_lmk = 1; + break; + case OPT_CSP: + csp_name = opt_arg(); + break; + case OPT_CANAME: + if (canames == NULL + && (canames = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(canames, opt_arg()); + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_PASSWORD: + passarg = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + } } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badarg) { - BIO_printf(bio_err, "Usage: pkcs12 [options]\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-export output PKCS12 file\n"); - BIO_printf(bio_err, "-chain add certificate chain\n"); - BIO_printf(bio_err, "-inkey file private key if not infile\n"); - BIO_printf(bio_err, "-certfile f add all certs in f\n"); - BIO_printf(bio_err, "-CApath arg - PEM format directory of CA's\n"); - BIO_printf(bio_err, "-CAfile arg - PEM format file of CA's\n"); - BIO_printf(bio_err, "-name \"name\" use name as friendly name\n"); - BIO_printf(bio_err, - "-caname \"nm\" use nm as CA friendly name (can be used more than once).\n"); - BIO_printf(bio_err, "-in infile input filename\n"); - BIO_printf(bio_err, "-out outfile output filename\n"); - BIO_printf(bio_err, - "-noout don't output anything, just verify.\n"); - BIO_printf(bio_err, "-nomacver don't verify MAC.\n"); - BIO_printf(bio_err, "-nocerts don't output certificates.\n"); - BIO_printf(bio_err, - "-clcerts only output client certificates.\n"); - BIO_printf(bio_err, "-cacerts only output CA certificates.\n"); - BIO_printf(bio_err, "-nokeys don't output private keys.\n"); - BIO_printf(bio_err, - "-info give info about PKCS#12 structure.\n"); - BIO_printf(bio_err, "-des encrypt private keys with DES\n"); - BIO_printf(bio_err, - "-des3 encrypt private keys with triple DES (default)\n"); -# ifndef OPENSSL_NO_IDEA - BIO_printf(bio_err, "-idea encrypt private keys with idea\n"); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, "-seed encrypt private keys with seed\n"); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc aes\n"); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc camellia\n"); -# endif - BIO_printf(bio_err, "-nodes don't encrypt private keys\n"); - BIO_printf(bio_err, "-noiter don't use encryption iteration\n"); - BIO_printf(bio_err, "-nomaciter don't use MAC iteration\n"); - BIO_printf(bio_err, "-maciter use MAC iteration\n"); - BIO_printf(bio_err, "-nomac don't generate MAC\n"); - BIO_printf(bio_err, - "-twopass separate MAC, encryption passwords\n"); - BIO_printf(bio_err, - "-descert encrypt PKCS#12 certificates with triple DES (default RC2-40)\n"); - BIO_printf(bio_err, - "-certpbe alg specify certificate PBE algorithm (default RC2-40)\n"); - BIO_printf(bio_err, - "-keypbe alg specify private key PBE algorithm (default 3DES)\n"); - BIO_printf(bio_err, - "-macalg alg digest algorithm used in MAC (default SHA1)\n"); - BIO_printf(bio_err, "-keyex set MS key exchange type\n"); - BIO_printf(bio_err, "-keysig set MS key signature type\n"); - BIO_printf(bio_err, - "-password p set import/export password source\n"); - BIO_printf(bio_err, "-passin p input file pass phrase source\n"); - BIO_printf(bio_err, "-passout p output file pass phrase source\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - BIO_printf(bio_err, "-CSP name Microsoft CSP name\n"); - BIO_printf(bio_err, - "-LMK Add local machine keyset attribute to private key\n"); - goto end; - } - e = setup_engine(bio_err, engine, 0); + private = 1; - if (passarg) { + if (passarg != NULL) { if (export_cert) - passargout = passarg; + passoutarg = passarg; else - passargin = passarg; + passinarg = passarg; } - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - if (!cpass) { + if (cpass == NULL) { if (export_cert) cpass = passout; else cpass = passin; } - if (cpass) { + if (cpass != NULL) { mpass = cpass; noprompt = 1; } else { @@ -433,61 +316,20 @@ int MAIN(int argc, char **argv) mpass = macpass; } - if (export_cert || inrand) { - app_RAND_load_file(NULL, bio_err, (inrand != NULL)); - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - } - ERR_load_crypto_strings(); - -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("read files"); -# endif - - if (!infile) - in = BIO_new_fp(stdin, BIO_NOCLOSE); - else - in = BIO_new_file(infile, "rb"); - if (!in) { - BIO_printf(bio_err, "Error opening input file %s\n", - infile ? infile : "<stdin>"); - perror(infile); - goto end; - } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("write files"); -# endif - - if (!outfile) { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else - out = BIO_new_file(outfile, "wb"); - if (!out) { - BIO_printf(bio_err, "Error opening output file %s\n", - outfile ? outfile : "<stdout>"); - perror(outfile); - goto end; - } if (twopass) { -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("read MAC password"); -# endif - if (EVP_read_pw_string - (macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) { - BIO_printf(bio_err, "Can't read Password\n"); + /* To avoid bit rot */ + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + if (EVP_read_pw_string( + macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + } else { +#endif + BIO_printf(bio_err, "Unsupported option -twopass\n"); goto end; } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); -# endif } if (export_cert) { @@ -506,29 +348,20 @@ int MAIN(int argc, char **argv) if (options & NOCERTS) chain = 0; -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("process -export_cert"); - CRYPTO_push_info("reading private key"); -# endif if (!(options & NOKEYS)) { - key = load_key(bio_err, keyname ? keyname : infile, + key = load_key(keyname ? keyname : infile, FORMAT_PEM, 1, passin, e, "private key"); - if (!key) + if (key == NULL) goto export_end; } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("reading certs from input"); -# endif /* Load in all certs in input file */ if (!(options & NOCERTS)) { - certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, - "certificates"); - if (!certs) + if (!load_certs(infile, &certs, FORMAT_PEM, NULL, + "certificates")) goto export_end; - if (key) { + if (key != NULL) { /* Look for matching private key */ for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); @@ -542,7 +375,7 @@ int MAIN(int argc, char **argv) break; } } - if (!ucert) { + if (ucert == NULL) { BIO_printf(bio_err, "No certificate matches private key\n"); goto export_end; @@ -550,43 +383,22 @@ int MAIN(int argc, char **argv) } } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("reading certs from input 2"); -# endif /* Add any more certificates asked for */ - if (certfile) { - STACK_OF(X509) *morecerts = NULL; - if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, - NULL, e, - "certificates from certfile"))) + if (certfile != NULL) { + if (!load_certs(certfile, &certs, FORMAT_PEM, NULL, + "certificates from certfile")) goto export_end; - while (sk_X509_num(morecerts) > 0) - sk_X509_push(certs, sk_X509_shift(morecerts)); - sk_X509_free(morecerts); } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("reading certs from certfile"); -# endif - -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("building chain"); -# endif /* If chaining get chain from user cert */ if (chain) { int vret; STACK_OF(X509) *chain2; - X509_STORE *store = X509_STORE_new(); - if (!store) { - BIO_printf(bio_err, "Memory allocation error\n"); + X509_STORE *store; + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) + == NULL) goto export_end; - } - if (!X509_STORE_load_locations(store, CAfile, CApath)) - X509_STORE_set_default_paths(store); vret = get_cert_chain(ucert, store, &chain2); X509_STORE_free(store); @@ -615,32 +427,32 @@ int MAIN(int argc, char **argv) X509_alias_set1(sk_X509_value(certs, i), catmp, -1); } - if (csp_name && key) + if (csp_name != NULL && key != NULL) EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, MBSTRING_ASC, (unsigned char *)csp_name, -1); - if (add_lmk && key) + if (add_lmk && key != NULL) EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("reading password"); -# endif - - if (!noprompt && - EVP_read_pw_string(pass, sizeof(pass), "Enter Export Password:", - 1)) { - BIO_printf(bio_err, "Can't read Password\n"); - goto export_end; + if (!noprompt) { + /* To avoid bit rot */ + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + if (EVP_read_pw_string(pass, sizeof(pass), + "Enter Export Password:", 1)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto export_end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto export_end; + } } - if (!twopass) - BUF_strlcpy(macpass, pass, sizeof(macpass)); -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("creating PKCS#12 structure"); -# endif + if (!twopass) + OPENSSL_strlcpy(macpass, pass, sizeof(macpass)); p12 = PKCS12_create(cpass, name, key, ucert, certs, key_pbe, cert_pbe, iter, -1, keytype); @@ -651,122 +463,135 @@ int MAIN(int argc, char **argv) } if (macalg) { - macmd = EVP_get_digestbyname(macalg); - if (!macmd) { - BIO_printf(bio_err, "Unknown digest algorithm %s\n", macalg); - } + if (!opt_md(macalg, &macmd)) + goto opthelp; } if (maciter != -1) PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_push_info("writing pkcs12"); -# endif + assert(private); + + out = bio_open_owner(outfile, FORMAT_PKCS12, private); + if (out == NULL) + goto end; i2d_PKCS12_bio(out, p12); ret = 0; export_end: -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); - CRYPTO_pop_info(); - CRYPTO_push_info("process -export_cert: freeing"); -# endif - if (key) - EVP_PKEY_free(key); - if (certs) - sk_X509_pop_free(certs, X509_free); - if (ucert) - X509_free(ucert); + EVP_PKEY_free(key); + sk_X509_pop_free(certs, X509_free); + X509_free(ucert); -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); -# endif goto end; } - if (!(p12 = d2i_PKCS12_bio(in, NULL))) { + in = bio_open_default(infile, 'r', FORMAT_PKCS12); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, FORMAT_PEM, private); + if (out == NULL) + goto end; + + if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) { ERR_print_errors(bio_err); goto end; } -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("read import password"); -# endif - if (!noprompt - && EVP_read_pw_string(pass, sizeof(pass), "Enter Import Password:", - 0)) { - BIO_printf(bio_err, "Can't read Password\n"); - goto end; + + if (!noprompt) { + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + if (EVP_read_pw_string(pass, sizeof(pass), "Enter Import Password:", + 0)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto end; + } } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); -# endif if (!twopass) - BUF_strlcpy(macpass, pass, sizeof(macpass)); + OPENSSL_strlcpy(macpass, pass, sizeof(macpass)); - if ((options & INFO) && p12->mac) - BIO_printf(bio_err, "MAC Iteration %ld\n", - p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1); + if ((options & INFO) && PKCS12_mac_present(p12)) { + const ASN1_INTEGER *tmaciter; + const X509_ALGOR *macalgid; + const ASN1_OBJECT *macobj; + const ASN1_OCTET_STRING *tmac; + const ASN1_OCTET_STRING *tsalt; + + PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, p12); + /* current hash algorithms do not use parameters so extract just name, + in future alg_print() may be needed */ + X509_ALGOR_get0(&macobj, NULL, NULL, macalgid); + BIO_puts(bio_err, "MAC: "); + i2a_ASN1_OBJECT(bio_err, macobj); + BIO_printf(bio_err, ", Iteration %ld\n", + tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L); + BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n", + tmac != NULL ? ASN1_STRING_length(tmac) : 0L, + tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L); + } if (macver) { -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("verify MAC"); -# endif /* If we enter empty password try no password first */ if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { /* If mac and crypto pass the same set it to NULL too */ if (!twopass) cpass = NULL; } else if (!PKCS12_verify_mac(p12, mpass, -1)) { - BIO_printf(bio_err, "Mac verify error: invalid password?\n"); - ERR_print_errors(bio_err); - goto end; + /* + * May be UTF8 from previous version of OpenSSL: + * convert to a UTF8 form which will translate + * to the same Unicode password. + */ + unsigned char *utmp; + int utmplen; + utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen); + if (utmp == NULL) + goto end; + badpass = OPENSSL_uni2utf8(utmp, utmplen); + OPENSSL_free(utmp); + if (!PKCS12_verify_mac(p12, badpass, -1)) { + BIO_printf(bio_err, "Mac verify error: invalid password?\n"); + ERR_print_errors(bio_err); + goto end; + } else { + BIO_printf(bio_err, "Warning: using broken algorithm\n"); + if (!twopass) + cpass = badpass; + } } - BIO_printf(bio_err, "MAC verified OK\n"); -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); -# endif } -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("output keys and certificates"); -# endif - if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout)) { + + assert(private); + if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) { BIO_printf(bio_err, "Error outputting keys and certificates\n"); ERR_print_errors(bio_err); goto end; } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); -# endif ret = 0; end: - if (p12) - PKCS12_free(p12); - if (export_cert || inrand) - app_RAND_write_file(NULL, bio_err); -# ifdef CRYPTO_MDEBUG - CRYPTO_remove_all_info(); -# endif + PKCS12_free(p12); release_engine(e); BIO_free(in); BIO_free_all(out); - if (canames) - sk_OPENSSL_STRING_free(canames); - if (passin) - OPENSSL_free(passin); - if (passout) - OPENSSL_free(passout); - apps_shutdown(); - OPENSSL_EXIT(ret); + sk_OPENSSL_STRING_free(canames); + OPENSSL_free(badpass); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; } -int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, - int passlen, int options, char *pempass) +int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, + int passlen, int options, char *pempass, + const EVP_CIPHER *enc) { STACK_OF(PKCS7) *asafes = NULL; STACK_OF(PKCS12_SAFEBAG) *bags; @@ -774,7 +599,7 @@ int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int ret = 0; PKCS7 *p7; - if (!(asafes = PKCS12_unpack_authsafes(p12))) + if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) return 0; for (i = 0; i < sk_PKCS7_num(asafes); i++) { p7 = sk_PKCS7_value(asafes, i); @@ -786,15 +611,16 @@ int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, } else if (bagnid == NID_pkcs7_encrypted) { if (options & INFO) { BIO_printf(bio_err, "PKCS7 Encrypted data: "); - alg_print(bio_err, p7->d.encrypted->enc_data->algorithm); + alg_print(p7->d.encrypted->enc_data->algorithm); } bags = PKCS12_unpack_p7encdata(p7, pass, passlen); - } else + } else { continue; + } if (!bags) goto err; if (!dump_certs_pkeys_bags(out, bags, pass, passlen, - options, pempass)) { + options, pempass, enc)) { sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); goto err; } @@ -804,63 +630,72 @@ int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, ret = 1; err: - - if (asafes) - sk_PKCS7_pop_free(asafes, PKCS7_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); return ret; } -int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, - char *pass, int passlen, int options, char *pempass) +int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc) { int i; for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { if (!dump_certs_pkeys_bag(out, sk_PKCS12_SAFEBAG_value(bags, i), - pass, passlen, options, pempass)) + pass, passlen, options, pempass, enc)) return 0; } return 1; } -int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, - int passlen, int options, char *pempass) +int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc) { EVP_PKEY *pkey; PKCS8_PRIV_KEY_INFO *p8; + const PKCS8_PRIV_KEY_INFO *p8c; X509 *x509; + const STACK_OF(X509_ATTRIBUTE) *attrs; int ret = 0; - switch (M_PKCS12_bag_type(bag)) { + attrs = PKCS12_SAFEBAG_get0_attrs(bag); + + switch (PKCS12_SAFEBAG_get_nid(bag)) { case NID_keyBag: if (options & INFO) BIO_printf(bio_err, "Key bag\n"); if (options & NOKEYS) return 1; - print_attribs(out, bag->attrib, "Bag Attributes"); - p8 = bag->value.keybag; - if (!(pkey = EVP_PKCS82PKEY(p8))) + print_attribs(out, attrs, "Bag Attributes"); + p8c = PKCS12_SAFEBAG_get0_p8inf(bag); + if ((pkey = EVP_PKCS82PKEY(p8c)) == NULL) return 0; - print_attribs(out, p8->attributes, "Key Attributes"); + print_attribs(out, PKCS8_pkey_get0_attrs(p8c), "Key Attributes"); ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); EVP_PKEY_free(pkey); break; case NID_pkcs8ShroudedKeyBag: if (options & INFO) { + const X509_SIG *tp8; + const X509_ALGOR *tp8alg; + BIO_printf(bio_err, "Shrouded Keybag: "); - alg_print(bio_err, bag->value.shkeybag->algor); + tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag); + X509_SIG_get0(tp8, &tp8alg, NULL); + alg_print(tp8alg); } if (options & NOKEYS) return 1; - print_attribs(out, bag->attrib, "Bag Attributes"); - if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) + print_attribs(out, attrs, "Bag Attributes"); + if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) return 0; - if (!(pkey = EVP_PKCS82PKEY(p8))) { + if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) { PKCS8_PRIV_KEY_INFO_free(p8); return 0; } - print_attribs(out, p8->attributes, "Key Attributes"); + print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); PKCS8_PRIV_KEY_INFO_free(p8); ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); EVP_PKEY_free(pkey); @@ -871,15 +706,15 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, BIO_printf(bio_err, "Certificate bag\n"); if (options & NOCERTS) return 1; - if (PKCS12_get_attr(bag, NID_localKeyID)) { + if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) { if (options & CACERTS) return 1; } else if (options & CLCERTS) return 1; - print_attribs(out, bag->attrib, "Bag Attributes"); - if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) + print_attribs(out, attrs, "Bag Attributes"); + if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) return 1; - if (!(x509 = PKCS12_certbag2x509(bag))) + if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) return 0; dump_cert_text(out, x509); ret = PEM_write_bio_X509(out, x509); @@ -889,16 +724,15 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, case NID_safeContentsBag: if (options & INFO) BIO_printf(bio_err, "Safe Contents bag\n"); - print_attribs(out, bag->attrib, "Bag Attributes"); - return dump_certs_pkeys_bags(out, bag->value.safes, pass, - passlen, options, pempass); + print_attribs(out, attrs, "Bag Attributes"); + return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag), + pass, passlen, options, pempass, enc); default: BIO_printf(bio_err, "Warning unsupported bag type: "); - i2a_ASN1_OBJECT(bio_err, bag->type); + i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag)); BIO_printf(bio_err, "\n"); return 1; - break; } return ret; } @@ -908,37 +742,44 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, static int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain) { - X509_STORE_CTX store_ctx; + X509_STORE_CTX *store_ctx = NULL; STACK_OF(X509) *chn = NULL; int i = 0; - if (!X509_STORE_CTX_init(&store_ctx, store, cert, NULL)) { - *chain = NULL; - return X509_V_ERR_UNSPECIFIED; + store_ctx = X509_STORE_CTX_new(); + if (store_ctx == NULL) { + i = X509_V_ERR_UNSPECIFIED; + goto end; + } + if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) { + i = X509_V_ERR_UNSPECIFIED; + goto end; } - if (X509_verify_cert(&store_ctx) > 0) - chn = X509_STORE_CTX_get1_chain(&store_ctx); - else if ((i = X509_STORE_CTX_get_error(&store_ctx)) == 0) + + if (X509_verify_cert(store_ctx) > 0) + chn = X509_STORE_CTX_get1_chain(store_ctx); + else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0) i = X509_V_ERR_UNSPECIFIED; - X509_STORE_CTX_cleanup(&store_ctx); +end: + X509_STORE_CTX_free(store_ctx); *chain = chn; return i; } -int alg_print(BIO *x, X509_ALGOR *alg) +static int alg_print(const X509_ALGOR *alg) { int pbenid, aparamtype; - ASN1_OBJECT *aoid; - void *aparam; + const ASN1_OBJECT *aoid; + const void *aparam; PBEPARAM *pbe = NULL; X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg); pbenid = OBJ_obj2nid(aoid); - BIO_printf(x, "%s", OBJ_nid2ln(pbenid)); + BIO_printf(bio_err, "%s", OBJ_nid2ln(pbenid)); /* * If PBE algorithm is PBES2 decode algorithm parameters @@ -950,14 +791,14 @@ int alg_print(BIO *x, X509_ALGOR *alg) if (aparamtype == V_ASN1_SEQUENCE) pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM)); if (pbe2 == NULL) { - BIO_puts(x, "<unsupported parameters>"); + BIO_puts(bio_err, ", <unsupported parameters>"); goto done; } X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc); pbenid = OBJ_obj2nid(aoid); X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption); encnid = OBJ_obj2nid(aoid); - BIO_printf(x, ", %s, %s", OBJ_nid2ln(pbenid), + BIO_printf(bio_err, ", %s, %s", OBJ_nid2ln(pbenid), OBJ_nid2sn(encnid)); /* If KDF is PBKDF2 decode parameters */ if (pbenid == NID_id_pbkdf2) { @@ -966,7 +807,7 @@ int alg_print(BIO *x, X509_ALGOR *alg) if (aparamtype == V_ASN1_SEQUENCE) kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM)); if (kdf == NULL) { - BIO_puts(x, "<unsupported parameters>"); + BIO_puts(bio_err, ", <unsupported parameters>"); goto done; } @@ -976,23 +817,41 @@ int alg_print(BIO *x, X509_ALGOR *alg) X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf); prfnid = OBJ_obj2nid(aoid); } - BIO_printf(x, ", Iteration %ld, PRF %s", + BIO_printf(bio_err, ", Iteration %ld, PRF %s", ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid)); PBKDF2PARAM_free(kdf); +#ifndef OPENSSL_NO_SCRYPT + } else if (pbenid == NID_id_scrypt) { + SCRYPT_PARAMS *kdf = NULL; + + if (aparamtype == V_ASN1_SEQUENCE) + kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS)); + if (kdf == NULL) { + BIO_puts(bio_err, ", <unsupported parameters>"); + goto done; + } + BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, " + "Block size(r): %ld, Paralelizm(p): %ld", + ASN1_STRING_length(kdf->salt), + ASN1_INTEGER_get(kdf->costParameter), + ASN1_INTEGER_get(kdf->blockSize), + ASN1_INTEGER_get(kdf->parallelizationParameter)); + SCRYPT_PARAMS_free(kdf); +#endif } PBE2PARAM_free(pbe2); } else { if (aparamtype == V_ASN1_SEQUENCE) pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM)); if (pbe == NULL) { - BIO_puts(x, "<unsupported parameters>"); + BIO_puts(bio_err, ", <unsupported parameters>"); goto done; } - BIO_printf(x, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter)); + BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter)); PBEPARAM_free(pbe); } done: - BIO_puts(x, "\n"); + BIO_puts(bio_err, "\n"); return 1; } @@ -1003,22 +862,10 @@ int cert_load(BIO *in, STACK_OF(X509) *sk) int ret; X509 *cert; ret = 0; -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("cert_load(): reading one cert"); -# endif while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) { -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); -# endif ret = 1; sk_X509_push(sk, cert); -# ifdef CRYPTO_MDEBUG - CRYPTO_push_info("cert_load(): reading one cert"); -# endif } -# ifdef CRYPTO_MDEBUG - CRYPTO_pop_info(); -# endif if (ret) ERR_clear_error(); return ret; @@ -1026,7 +873,7 @@ int cert_load(BIO *in, STACK_OF(X509) *sk) /* Generalised attribute print: handle PKCS#8 and bag attributes */ -int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, +int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name) { X509_ATTRIBUTE *attr; @@ -1043,17 +890,20 @@ int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, } BIO_printf(out, "%s\n", name); for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { + ASN1_OBJECT *attr_obj; attr = sk_X509_ATTRIBUTE_value(attrlst, i); - attr_nid = OBJ_obj2nid(attr->object); + attr_obj = X509_ATTRIBUTE_get0_object(attr); + attr_nid = OBJ_obj2nid(attr_obj); BIO_printf(out, " "); if (attr_nid == NID_undef) { - i2a_ASN1_OBJECT(out, attr->object); + i2a_ASN1_OBJECT(out, attr_obj); BIO_printf(out, ": "); - } else + } else { BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); + } - if (sk_ASN1_TYPE_num(attr->value.set)) { - av = sk_ASN1_TYPE_value(attr->value.set, 0); + if (X509_ATTRIBUTE_count(attr)) { + av = X509_ATTRIBUTE_get0_type(attr, 0); switch (av->type) { case V_ASN1_BMPSTRING: value = OPENSSL_uni2asc(av->value.bmpstring->data, @@ -1078,8 +928,9 @@ int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, BIO_printf(out, "<Unsupported tag %d>\n", av->type); break; } - } else + } else { BIO_printf(out, "<No Values>\n"); + } } return 1; } @@ -1091,11 +942,11 @@ void hex_prin(BIO *out, unsigned char *buf, int len) BIO_printf(out, "%02X ", buf[i]); } -static int set_pbe(BIO *err, int *ppbe, const char *str) +static int set_pbe(int *ppbe, const char *str) { if (!str) return 0; - if (!strcmp(str, "NONE")) { + if (strcmp(str, "NONE") == 0) { *ppbe = -1; return 1; } @@ -1107,6 +958,4 @@ static int set_pbe(BIO *err, int *ppbe, const char *str) return 1; } -#else -static void *dummy = &dummy; #endif diff --git a/apps/pkcs7.c b/apps/pkcs7.c index c5d51d2b4831..c3e9f5c69260 100644 --- a/apps/pkcs7.c +++ b/apps/pkcs7.c @@ -1,59 +1,10 @@ -/* apps/pkcs7.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> @@ -61,6 +12,7 @@ #include <string.h> #include <time.h> #include "apps.h" +#include "progs.h" #include <openssl/err.h> #include <openssl/objects.h> #include <openssl/evp.h> @@ -68,159 +20,103 @@ #include <openssl/pkcs7.h> #include <openssl/pem.h> -#undef PROG -#define PROG pkcs7_main - -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -print_certs - */ +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT, + OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS pkcs7_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"noout", OPT_NOOUT, '-', "Don't output encoded data"}, + {"text", OPT_TEXT, '-', "Print full details of certificates"}, + {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"}, + {"print_certs", OPT_PRINT_CERTS, '-', + "Print_certs print any certs or crl in the input"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int pkcs7_main(int argc, char **argv) { + ENGINE *e = NULL; PKCS7 *p7 = NULL; - int i, badops = 0; BIO *in = NULL, *out = NULL; - int informat, outformat; - char *infile, *outfile, *prog; - int print_certs = 0, text = 0, noout = 0, p7_print = 0; - int ret = 1; - char *engine = NULL; - ENGINE *e = NULL; + int informat = FORMAT_PEM, outformat = FORMAT_PEM; + char *infile = NULL, *outfile = NULL, *prog; + int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1; + OPTION_CHOICE o; - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-noout") == 0) + prog = opt_init(argc, argv, pkcs7_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkcs7_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-text") == 0) + break; + case OPT_TEXT: text = 1; - else if (strcmp(*argv, "-print") == 0) + break; + case OPT_PRINT: p7_print = 1; - else if (strcmp(*argv, "-print_certs") == 0) + break; + case OPT_PRINT_CERTS: print_certs = 1; -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -#endif - else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); break; } - argc--; - argv++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - DER or PEM\n"); - BIO_printf(bio_err, " -outform arg output format - DER or PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, - " -print_certs print any certs or crl in the input\n"); - BIO_printf(bio_err, - " -text print full details of certificates\n"); - BIO_printf(bio_err, " -noout don't output encoded data\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -#endif - ret = 1; + in = bio_open_default(infile, 'r', informat); + if (in == NULL) goto end; - } - - ERR_load_crypto_strings(); - - e = setup_engine(bio_err, engine, 0); - - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) { - ERR_print_errors(bio_err); - goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - BIO_printf(bio_err, "unable to load input file\n"); - ERR_print_errors(bio_err); - goto end; - } - } if (informat == FORMAT_ASN1) p7 = d2i_PKCS7_bio(in, NULL); - else if (informat == FORMAT_PEM) + else p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); - else { - BIO_printf(bio_err, "bad input format specified for pkcs7 object\n"); - goto end; - } if (p7 == NULL) { BIO_printf(bio_err, "unable to load PKCS7 object\n"); ERR_print_errors(bio_err); goto end; } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; if (p7_print) PKCS7_print_ctx(out, p7, 0, NULL); @@ -268,7 +164,7 @@ int MAIN(int argc, char **argv) for (i = 0; i < sk_X509_CRL_num(crls); i++) { crl = sk_X509_CRL_value(crls, i); - X509_CRL_print(out, crl); + X509_CRL_print_ex(out, crl, get_nameopt()); if (!noout) PEM_write_bio_X509_CRL(out, crl); @@ -283,12 +179,8 @@ int MAIN(int argc, char **argv) if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_PKCS7_bio(out, p7); - else if (outformat == FORMAT_PEM) + else i = PEM_write_bio_PKCS7(out, p7); - else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; - } if (!i) { BIO_printf(bio_err, "unable to write pkcs7 object\n"); @@ -298,13 +190,9 @@ int MAIN(int argc, char **argv) } ret = 0; end: - if (p7 != NULL) - PKCS7_free(p7); + PKCS7_free(p7); release_engine(e); - if (in != NULL) - BIO_free(in); - if (out != NULL) - BIO_free_all(out); - apps_shutdown(); - OPENSSL_EXIT(ret); + BIO_free(in); + BIO_free_all(out); + return ret; } diff --git a/apps/pkcs8.c b/apps/pkcs8.c index d7f0720ca128..205536560ac1 100644 --- a/apps/pkcs8.c +++ b/apps/pkcs8.c @@ -1,294 +1,268 @@ -/* pkcs8.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 1999-2004. - */ -/* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ + #include <stdio.h> +#include <stdlib.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/pkcs12.h> -#define PROG pkcs8_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, + OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT, +#ifndef OPENSSL_NO_SCRYPT + OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P, +#endif + OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT, + OPT_TRADITIONAL, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS pkcs8_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"}, + {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"}, + {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"}, + OPT_R_OPTIONS, + {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"}, + {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"}, + {"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"}, + {"iter", OPT_ITER, 'p', "Specify the iteration count"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif +#ifndef OPENSSL_NO_SCRYPT + {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"}, + {"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"}, + {"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"}, + {"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int pkcs8_main(int argc, char **argv) { - ENGINE *e = NULL; - char **args, *infile = NULL, *outfile = NULL; - char *passargin = NULL, *passargout = NULL; BIO *in = NULL, *out = NULL; - int topk8 = 0; - int pbe_nid = -1; - const EVP_CIPHER *cipher = NULL; - int iter = PKCS12_DEFAULT_ITER; - int informat, outformat; - int p8_broken = PKCS8_OK; - int nocrypt = 0; - X509_SIG *p8 = NULL; - PKCS8_PRIV_KEY_INFO *p8inf = NULL; + ENGINE *e = NULL; EVP_PKEY *pkey = NULL; - char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL; - int badarg = 0; - int ret = 1; - char *engine = NULL; - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - - informat = FORMAT_PEM; - outformat = FORMAT_PEM; + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + X509_SIG *p8 = NULL; + const EVP_CIPHER *cipher = NULL; + char *infile = NULL, *outfile = NULL; + char *passinarg = NULL, *passoutarg = NULL, *prog; +#ifndef OPENSSL_NO_UI_CONSOLE + char pass[APP_PASS_LEN]; +#endif + char *passin = NULL, *passout = NULL, *p8pass = NULL; + OPTION_CHOICE o; + int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1; + int private = 0, traditional = 0; +#ifndef OPENSSL_NO_SCRYPT + long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0; +#endif - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - args = argv + 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-v2")) { - if (args[1]) { - args++; - cipher = EVP_get_cipherbyname(*args); - if (!cipher) { - BIO_printf(bio_err, "Unknown cipher %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-v1")) { - if (args[1]) { - args++; - pbe_nid = OBJ_txt2nid(*args); - if (pbe_nid == NID_undef) { - BIO_printf(bio_err, "Unknown PBE algorithm %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-v2prf")) { - if (args[1]) { - args++; - pbe_nid = OBJ_txt2nid(*args); - if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) { - BIO_printf(bio_err, "Unknown PRF algorithm %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-inform")) { - if (args[1]) { - args++; - informat = str2fmt(*args); - } else - badarg = 1; - } else if (!strcmp(*args, "-outform")) { - if (args[1]) { - args++; - outformat = str2fmt(*args); - } else - badarg = 1; - } else if (!strcmp(*args, "-topk8")) + prog = opt_init(argc, argv, pkcs8_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkcs8_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_TOPK8: topk8 = 1; - else if (!strcmp(*args, "-noiter")) + break; + case OPT_NOITER: iter = 1; - else if (!strcmp(*args, "-nocrypt")) + break; + case OPT_NOCRYPT: nocrypt = 1; - else if (!strcmp(*args, "-nooct")) - p8_broken = PKCS8_NO_OCTET; - else if (!strcmp(*args, "-nsdb")) - p8_broken = PKCS8_NS_DB; - else if (!strcmp(*args, "-embed")) - p8_broken = PKCS8_EMBEDDED_PARAM; - else if (!strcmp(*args, "-passin")) { - if (!args[1]) - goto bad; - passargin = *(++args); - } else if (!strcmp(*args, "-passout")) { - if (!args[1]) - goto bad; - passargout = *(++args); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*args, "-engine") == 0) { - if (!args[1]) - goto bad; - engine = *(++args); - } + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_TRADITIONAL: + traditional = 1; + break; + case OPT_V2: + if (!opt_cipher(opt_arg(), &cipher)) + goto opthelp; + break; + case OPT_V1: + pbe_nid = OBJ_txt2nid(opt_arg()); + if (pbe_nid == NID_undef) { + BIO_printf(bio_err, + "%s: Unknown PBE algorithm %s\n", prog, opt_arg()); + goto opthelp; + } + break; + case OPT_V2PRF: + pbe_nid = OBJ_txt2nid(opt_arg()); + if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) { + BIO_printf(bio_err, + "%s: Unknown PRF algorithm %s\n", prog, opt_arg()); + goto opthelp; + } + if (cipher == NULL) + cipher = EVP_aes_256_cbc(); + break; + case OPT_ITER: + if (!opt_int(opt_arg(), &iter)) + goto opthelp; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; +#ifndef OPENSSL_NO_SCRYPT + case OPT_SCRYPT: + scrypt_N = 16384; + scrypt_r = 8; + scrypt_p = 1; + if (cipher == NULL) + cipher = EVP_aes_256_cbc(); + break; + case OPT_SCRYPT_N: + if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0) + goto opthelp; + break; + case OPT_SCRYPT_R: + if (!opt_long(opt_arg(), &scrypt_r) || scrypt_r <= 0) + goto opthelp; + break; + case OPT_SCRYPT_P: + if (!opt_long(opt_arg(), &scrypt_p) || scrypt_p <= 0) + goto opthelp; + break; #endif - else if (!strcmp(*args, "-in")) { - if (args[1]) { - args++; - infile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } else - badarg = 1; - args++; + } } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badarg) { - bad: - BIO_printf(bio_err, "Usage pkcs8 [options]\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, "-inform X input format (DER or PEM)\n"); - BIO_printf(bio_err, - "-passin arg input file pass phrase source\n"); - BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, - "-passout arg output file pass phrase source\n"); - BIO_printf(bio_err, "-topk8 output PKCS8 file\n"); - BIO_printf(bio_err, - "-nooct use (nonstandard) no octet format\n"); - BIO_printf(bio_err, - "-embed use (nonstandard) embedded DSA parameters format\n"); - BIO_printf(bio_err, - "-nsdb use (nonstandard) DSA Netscape DB format\n"); - BIO_printf(bio_err, "-noiter use 1 as iteration count\n"); - BIO_printf(bio_err, - "-nocrypt use or expect unencrypted private key\n"); - BIO_printf(bio_err, - "-v2 alg use PKCS#5 v2.0 and cipher \"alg\"\n"); - BIO_printf(bio_err, - "-v1 obj use PKCS#5 v1.5 and cipher \"alg\"\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -#endif - goto end; - } - e = setup_engine(bio_err, engine, 0); + private = 1; - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - if ((pbe_nid == -1) && !cipher) - pbe_nid = NID_pbeWithMD5AndDES_CBC; + if ((pbe_nid == -1) && cipher == NULL) + cipher = EVP_aes_256_cbc(); - if (infile) { - if (!(in = BIO_new_file(infile, "rb"))) { - BIO_printf(bio_err, "Can't open input file %s\n", infile); - goto end; - } - } else - in = BIO_new_fp(stdin, BIO_NOCLOSE); + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; - if (outfile) { - if (!(out = BIO_new_file(outfile, "wb"))) { - BIO_printf(bio_err, "Can't open output file %s\n", outfile); - goto end; - } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } if (topk8) { - pkey = load_key(bio_err, infile, informat, 1, passin, e, "key"); - if (!pkey) + pkey = load_key(infile, informat, 1, passin, e, "key"); + if (pkey == NULL) goto end; - if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) { + if ((p8inf = EVP_PKEY2PKCS8(pkey)) == NULL) { BIO_printf(bio_err, "Error converting key\n"); ERR_print_errors(bio_err); goto end; } if (nocrypt) { - if (outformat == FORMAT_PEM) + assert(private); + if (outformat == FORMAT_PEM) { PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); - else if (outformat == FORMAT_ASN1) + } else if (outformat == FORMAT_ASN1) { i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); - else { + } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } } else { - if (passout) + X509_ALGOR *pbe; + if (cipher) { +#ifndef OPENSSL_NO_SCRYPT + if (scrypt_N && scrypt_r && scrypt_p) + pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL, + scrypt_N, scrypt_r, scrypt_p); + else +#endif + pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL, + pbe_nid); + } else { + pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0); + } + if (pbe == NULL) { + BIO_printf(bio_err, "Error setting PBE algorithm\n"); + ERR_print_errors(bio_err); + goto end; + } + if (passout != NULL) { p8pass = passout; - else { + } else if (1) { + /* To avoid bit rot */ +#ifndef OPENSSL_NO_UI_CONSOLE p8pass = pass; if (EVP_read_pw_string - (pass, sizeof(pass), "Enter Encryption Password:", 1)) + (pass, sizeof(pass), "Enter Encryption Password:", 1)) { + X509_ALGOR_free(pbe); goto end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto end; } - app_RAND_load_file(NULL, bio_err, 0); - if (!(p8 = PKCS8_encrypt(pbe_nid, cipher, - p8pass, strlen(p8pass), - NULL, 0, iter, p8inf))) { + p8 = PKCS8_set0_pbe(p8pass, strlen(p8pass), p8inf, pbe); + if (p8 == NULL) { + X509_ALGOR_free(pbe); BIO_printf(bio_err, "Error encrypting key\n"); ERR_print_errors(bio_err); goto end; } - app_RAND_write_file(NULL, bio_err); + assert(private); if (outformat == FORMAT_PEM) PEM_write_bio_PKCS8(out, p8); else if (outformat == FORMAT_ASN1) @@ -304,80 +278,68 @@ int MAIN(int argc, char **argv) } if (nocrypt) { - if (informat == FORMAT_PEM) + if (informat == FORMAT_PEM) { p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); - else if (informat == FORMAT_ASN1) + } else if (informat == FORMAT_ASN1) { p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); - else { + } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } } else { - if (informat == FORMAT_PEM) + if (informat == FORMAT_PEM) { p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); - else if (informat == FORMAT_ASN1) + } else if (informat == FORMAT_ASN1) { p8 = d2i_PKCS8_bio(in, NULL); - else { + } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } - if (!p8) { + if (p8 == NULL) { BIO_printf(bio_err, "Error reading key\n"); ERR_print_errors(bio_err); goto end; } - if (passin) + if (passin != NULL) { p8pass = passin; - else { + } else if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE p8pass = pass; - EVP_read_pw_string(pass, sizeof(pass), "Enter Password:", 0); + if (EVP_read_pw_string(pass, sizeof(pass), "Enter Password:", 0)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto end; } p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); } - if (!p8inf) { + if (p8inf == NULL) { BIO_printf(bio_err, "Error decrypting key\n"); ERR_print_errors(bio_err); goto end; } - if (!(pkey = EVP_PKCS82PKEY(p8inf))) { + if ((pkey = EVP_PKCS82PKEY(p8inf)) == NULL) { BIO_printf(bio_err, "Error converting key\n"); ERR_print_errors(bio_err); goto end; } - if (p8inf->broken) { - BIO_printf(bio_err, "Warning: broken key encoding: "); - switch (p8inf->broken) { - case PKCS8_NO_OCTET: - BIO_printf(bio_err, "No Octet String in PrivateKey\n"); - break; - - case PKCS8_EMBEDDED_PARAM: - BIO_printf(bio_err, "DSA parameters included in PrivateKey\n"); - break; - - case PKCS8_NS_DB: - BIO_printf(bio_err, "DSA public key include in PrivateKey\n"); - break; - - case PKCS8_NEG_PRIVKEY: - BIO_printf(bio_err, "DSA private key value is negative\n"); - break; - - default: - BIO_printf(bio_err, "Unknown broken type\n"); - break; - } - } - - if (outformat == FORMAT_PEM) - PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); - else if (outformat == FORMAT_ASN1) + assert(private); + if (outformat == FORMAT_PEM) { + if (traditional) + PEM_write_bio_PrivateKey_traditional(out, pkey, NULL, NULL, 0, + NULL, passout); + else + PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); + } else if (outformat == FORMAT_ASN1) { i2d_PrivateKey_bio(out, pkey); - else { + } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } @@ -390,10 +352,8 @@ int MAIN(int argc, char **argv) release_engine(e); BIO_free_all(out); BIO_free(in); - if (passin) - OPENSSL_free(passin); - if (passout) - OPENSSL_free(passout); + OPENSSL_free(passin); + OPENSSL_free(passout); return ret; } diff --git a/apps/pkey.c b/apps/pkey.c index 63d878a293aa..0dd5590bdc0b 100644 --- a/apps/pkey.c +++ b/apps/pkey.c @@ -1,248 +1,243 @@ -/* apps/pkey.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2006 - */ -/* ==================================================================== - * Copyright (c) 2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ + #include <stdio.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/evp.h> -#define PROG pkey_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, + OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB, + OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS pkey_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', "Input format (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"in", OPT_IN, 's', "Input key"}, + {"out", OPT_OUT, '>', "Output file"}, + {"pubin", OPT_PUBIN, '-', + "Read public key from input (default is private key)"}, + {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, + {"text_pub", OPT_TEXT_PUB, '-', "Only output public key components"}, + {"text", OPT_TEXT, '-', "Output in plaintext as well"}, + {"noout", OPT_NOOUT, '-', "Don't output the key"}, + {"", OPT_MD, '-', "Any supported cipher"}, + {"traditional", OPT_TRADITIONAL, '-', + "Use traditional format for private keys"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"check", OPT_CHECK, '-', "Check key consistency"}, + {"pubcheck", OPT_PUB_CHECK, '-', "Check public key consistency"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int pkey_main(int argc, char **argv) { - ENGINE *e = NULL; - char **args, *infile = NULL, *outfile = NULL; - char *passargin = NULL, *passargout = NULL; BIO *in = NULL, *out = NULL; - const EVP_CIPHER *cipher = NULL; - int informat, outformat; - int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0; + ENGINE *e = NULL; EVP_PKEY *pkey = NULL; - char *passin = NULL, *passout = NULL; - int badarg = 0; - char *engine = NULL; - int ret = 1; - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - - informat = FORMAT_PEM; - outformat = FORMAT_PEM; + const EVP_CIPHER *cipher = NULL; + char *infile = NULL, *outfile = NULL, *passin = NULL, *passout = NULL; + char *passinarg = NULL, *passoutarg = NULL, *prog; + OPTION_CHOICE o; + int informat = FORMAT_PEM, outformat = FORMAT_PEM; + int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0, ret = 1; + int private = 0, traditional = 0, check = 0, pub_check = 0; - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - args = argv + 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-inform")) { - if (args[1]) { - args++; - informat = str2fmt(*args); - } else - badarg = 1; - } else if (!strcmp(*args, "-outform")) { - if (args[1]) { - args++; - outformat = str2fmt(*args); - } else - badarg = 1; - } else if (!strcmp(*args, "-passin")) { - if (!args[1]) - goto bad; - passargin = *(++args); - } else if (!strcmp(*args, "-passout")) { - if (!args[1]) - goto bad; - passargout = *(++args); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*args, "-engine") == 0) { - if (!args[1]) - goto bad; - engine = *(++args); - } -#endif - else if (!strcmp(*args, "-in")) { - if (args[1]) { - args++; - infile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } else if (strcmp(*args, "-pubin") == 0) { - pubin = 1; - pubout = 1; - pubtext = 1; - } else if (strcmp(*args, "-pubout") == 0) + prog = opt_init(argc, argv, pkey_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkey_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PUBIN: + pubin = pubout = pubtext = 1; + break; + case OPT_PUBOUT: pubout = 1; - else if (strcmp(*args, "-text_pub") == 0) { - pubtext = 1; - text = 1; - } else if (strcmp(*args, "-text") == 0) + break; + case OPT_TEXT_PUB: + pubtext = text = 1; + break; + case OPT_TEXT: text = 1; - else if (strcmp(*args, "-noout") == 0) + break; + case OPT_NOOUT: noout = 1; - else { - cipher = EVP_get_cipherbyname(*args + 1); - if (!cipher) { - BIO_printf(bio_err, "Unknown cipher %s\n", *args + 1); - badarg = 1; - } + break; + case OPT_TRADITIONAL: + traditional = 1; + break; + case OPT_CHECK: + check = 1; + break; + case OPT_PUB_CHECK: + pub_check = 1; + break; + case OPT_MD: + if (!opt_cipher(opt_unknown(), &cipher)) + goto opthelp; } - args++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badarg) { - bad: - BIO_printf(bio_err, "Usage pkey [options]\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, "-inform X input format (DER or PEM)\n"); - BIO_printf(bio_err, - "-passin arg input file pass phrase source\n"); - BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, - "-passout arg output file pass phrase source\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); -#endif - return 1; - } - e = setup_engine(bio_err, engine, 0); + private = !noout && !pubout ? 1 : 0; + if (text && !pubtext) + private = 1; - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - if (outfile) { - if (!(out = BIO_new_file(outfile, "wb"))) { - BIO_printf(bio_err, "Can't open output file %s\n", outfile); - goto end; - } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; if (pubin) - pkey = load_pubkey(bio_err, infile, informat, 1, - passin, e, "Public Key"); + pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); else - pkey = load_key(bio_err, infile, informat, 1, passin, e, "key"); - if (!pkey) + pkey = load_key(infile, informat, 1, passin, e, "key"); + if (pkey == NULL) goto end; + if (check || pub_check) { + int r; + EVP_PKEY_CTX *ctx; + + ctx = EVP_PKEY_CTX_new(pkey, e); + if (ctx == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + if (check) + r = EVP_PKEY_check(ctx); + else + r = EVP_PKEY_public_check(ctx); + + if (r == 1) { + BIO_printf(out, "Key is valid\n"); + } else { + /* + * Note: at least for RSA keys if this function returns + * -1, there will be no error reasons. + */ + unsigned long err; + + BIO_printf(out, "Key is invalid\n"); + + while ((err = ERR_peek_error()) != 0) { + BIO_printf(out, "Detailed error: %s\n", + ERR_reason_error_string(err)); + ERR_get_error(); /* remove err from error stack */ + } + } + EVP_PKEY_CTX_free(ctx); + } + if (!noout) { if (outformat == FORMAT_PEM) { - if (pubout) - PEM_write_bio_PUBKEY(out, pkey); - else - PEM_write_bio_PrivateKey(out, pkey, cipher, - NULL, 0, NULL, passout); + if (pubout) { + if (!PEM_write_bio_PUBKEY(out, pkey)) + goto end; + } else { + assert(private); + if (traditional) { + if (!PEM_write_bio_PrivateKey_traditional(out, pkey, cipher, + NULL, 0, NULL, + passout)) + goto end; + } else { + if (!PEM_write_bio_PrivateKey(out, pkey, cipher, + NULL, 0, NULL, passout)) + goto end; + } + } } else if (outformat == FORMAT_ASN1) { - if (pubout) - i2d_PUBKEY_bio(out, pkey); - else - i2d_PrivateKey_bio(out, pkey); + if (pubout) { + if (!i2d_PUBKEY_bio(out, pkey)) + goto end; + } else { + assert(private); + if (!i2d_PrivateKey_bio(out, pkey)) + goto end; + } } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } - } if (text) { - if (pubtext) - EVP_PKEY_print_public(out, pkey, 0, NULL); - else - EVP_PKEY_print_private(out, pkey, 0, NULL); + if (pubtext) { + if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) + goto end; + } else { + assert(private); + if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0) + goto end; + } } ret = 0; end: + if (ret != 0) + ERR_print_errors(bio_err); EVP_PKEY_free(pkey); release_engine(e); BIO_free_all(out); BIO_free(in); - if (passin) - OPENSSL_free(passin); - if (passout) - OPENSSL_free(passout); + OPENSSL_free(passin); + OPENSSL_free(passout); return ret; } diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c index 1437f03ae9a1..41c3f532b345 100644 --- a/apps/pkeyparam.c +++ b/apps/pkeyparam.c @@ -1,168 +1,127 @@ -/* apps/pkeyparam.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2006 - */ -/* ==================================================================== - * Copyright (c) 2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ + #include <stdio.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/evp.h> -#define PROG pkeyparam_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT, + OPT_ENGINE, OPT_CHECK +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS pkeyparam_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"text", OPT_TEXT, '-', "Print parameters as text"}, + {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"check", OPT_CHECK, '-', "Check key param consistency"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int pkeyparam_main(int argc, char **argv) { - char **args, *infile = NULL, *outfile = NULL; + ENGINE *e = NULL; BIO *in = NULL, *out = NULL; - int text = 0, noout = 0; EVP_PKEY *pkey = NULL; - int badarg = 0; - char *engine = NULL; - ENGINE *e = NULL; - int ret = 1; - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - args = argv + 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-in")) { - if (args[1]) { - args++; - infile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*args, "-engine") == 0) { - if (!args[1]) - goto bad; - engine = *(++args); - } -#endif + int text = 0, noout = 0, ret = 1, check = 0; + OPTION_CHOICE o; + char *infile = NULL, *outfile = NULL, *prog; - else if (strcmp(*args, "-text") == 0) + prog = opt_init(argc, argv, pkeyparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkeyparam_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_TEXT: text = 1; - else if (strcmp(*args, "-noout") == 0) + break; + case OPT_NOOUT: noout = 1; - args++; + break; + case OPT_CHECK: + check = 1; + break; + } } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badarg) { -#ifndef OPENSSL_NO_ENGINE - bad: -#endif - BIO_printf(bio_err, "Usage pkeyparam [options]\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, "-text print parameters as text\n"); - BIO_printf(bio_err, - "-noout don't output encoded parameters\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); -#endif - return 1; + in = bio_open_default(infile, 'r', FORMAT_PEM); + if (in == NULL) + goto end; + out = bio_open_default(outfile, 'w', FORMAT_PEM); + if (out == NULL) + goto end; + pkey = PEM_read_bio_Parameters(in, NULL); + if (pkey == NULL) { + BIO_printf(bio_err, "Error reading parameters\n"); + ERR_print_errors(bio_err); + goto end; } - e = setup_engine(bio_err, engine, 0); - if (infile) { - if (!(in = BIO_new_file(infile, "r"))) { - BIO_printf(bio_err, "Can't open input file %s\n", infile); - goto end; - } - } else - in = BIO_new_fp(stdin, BIO_NOCLOSE); + if (check) { + int r; + EVP_PKEY_CTX *ctx; - if (outfile) { - if (!(out = BIO_new_file(outfile, "w"))) { - BIO_printf(bio_err, "Can't open output file %s\n", outfile); + ctx = EVP_PKEY_CTX_new(pkey, e); + if (ctx == NULL) { + ERR_print_errors(bio_err); goto end; } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } - pkey = PEM_read_bio_Parameters(in, NULL); - if (!pkey) { - BIO_printf(bio_err, "Error reading parameters\n"); - ERR_print_errors(bio_err); - goto end; + r = EVP_PKEY_param_check(ctx); + + if (r == 1) { + BIO_printf(out, "Parameters are valid\n"); + } else { + /* + * Note: at least for RSA keys if this function returns + * -1, there will be no error reasons. + */ + unsigned long err; + + BIO_printf(out, "Parameters are invalid\n"); + + while ((err = ERR_peek_error()) != 0) { + BIO_printf(out, "Detailed error: %s\n", + ERR_reason_error_string(err)); + ERR_get_error(); /* remove err from error stack */ + } + } + EVP_PKEY_CTX_free(ctx); } if (!noout) diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c index 19f2e5d9cf9f..2c4e524b693e 100644 --- a/apps/pkeyutl.c +++ b/apps/pkeyutl.c @@ -1,231 +1,227 @@ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2006. - */ -/* ==================================================================== - * Copyright (c) 2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include "apps.h" +#include "progs.h" #include <string.h> #include <openssl/err.h> #include <openssl/pem.h> #include <openssl/evp.h> +#define KEY_NONE 0 #define KEY_PRIVKEY 1 #define KEY_PUBKEY 2 #define KEY_CERT 3 -static void usage(void); - -#undef PROG - -#define PROG pkeyutl_main - -static EVP_PKEY_CTX *init_ctx(int *pkeysize, +static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, - char *passargin, int pkey_op, ENGINE *e, - int impl); + char *passinarg, int pkey_op, ENGINE *e, + const int impl); -static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, - const char *file, ENGINE* e); +static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, + ENGINE *e); static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, unsigned char *out, size_t *poutlen, - unsigned char *in, size_t inlen); + const unsigned char *in, size_t inlen); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT, + OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN, + OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, + OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN, + OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int argc, char **); +const OPTIONS pkeyutl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"pubin", OPT_PUBIN, '-', "Input is a public key"}, + {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"}, + {"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"}, + {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, + {"sign", OPT_SIGN, '-', "Sign input data with private key"}, + {"verify", OPT_VERIFY, '-', "Verify with public key"}, + {"verifyrecover", OPT_VERIFYRECOVER, '-', + "Verify with public key, recover original data"}, + {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"}, + {"derive", OPT_DERIVE, '-', "Derive shared secret"}, + {"kdf", OPT_KDF, 's', "Use KDF algorithm"}, + {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"}, + {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"}, + {"inkey", OPT_INKEY, 's', "Input private key file"}, + {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"peerform", OPT_PEERFORM, 'E', "Peer key format - default PEM"}, + {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, + {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"engine_impl", OPT_ENGINE_IMPL, '-', + "Also use engine given by -engine for crypto operations"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int pkeyutl_main(int argc, char **argv) { BIO *in = NULL, *out = NULL; - char *infile = NULL, *outfile = NULL, *sigfile = NULL; ENGINE *e = NULL; - int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; - int keyform = FORMAT_PEM, peerform = FORMAT_PEM; - char badarg = 0, rev = 0; - char hexdump = 0, asn1parse = 0; EVP_PKEY_CTX *ctx = NULL; - char *passargin = NULL; - int keysize = -1; - int engine_impl = 0; + char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; + char hexdump = 0, asn1parse = 0, rev = 0, *prog; unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; - size_t buf_outlen = 0; - int buf_inlen = 0, siglen = -1; + OPTION_CHOICE o; + int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM; + int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; + int engine_impl = 0; + int ret = 1, rv = -1; + size_t buf_outlen; const char *inkey = NULL; const char *peerkey = NULL; + const char *kdfalg = NULL; + int kdflen = 0; STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; - int ret = 1, rv = -1; - - argc--; - argv++; - - if (!bio_err) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - - while (argc >= 1) { - if (!strcmp(*argv, "-in")) { - if (--argc < 1) - badarg = 1; - else - infile = *(++argv); - } else if (!strcmp(*argv, "-out")) { - if (--argc < 1) - badarg = 1; - else - outfile = *(++argv); - } else if (!strcmp(*argv, "-sigfile")) { - if (--argc < 1) - badarg = 1; - else - sigfile = *(++argv); - } else if (!strcmp(*argv, "-inkey")) { - if (--argc < 1) - badarg = 1; - else - inkey = *++argv; - } else if (!strcmp(*argv, "-peerkey")) { - if (--argc < 1) - badarg = 1; - else - peerkey = *++argv; - } else if (!strcmp(*argv, "-passin")) { - if (--argc < 1) - badarg = 1; - else - passargin = *(++argv); - } else if (strcmp(*argv, "-peerform") == 0) { - if (--argc < 1) - badarg = 1; - else - peerform = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - badarg = 1; - else - keyform = str2fmt(*(++argv)); - } -#ifndef OPENSSL_NO_ENGINE - else if (!strcmp(*argv, "-engine")) { - if (--argc < 1) - badarg = 1; - else - e = setup_engine(bio_err, *(++argv), 0); - } else if (!strcmp(*argv, "-engine_impl")) { - engine_impl = 1; - } -#endif - else if (!strcmp(*argv, "-pubin")) + prog = opt_init(argc, argv, pkeyutl_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkeyutl_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_SIGFILE: + sigfile = opt_arg(); + break; + case OPT_ENGINE_IMPL: + engine_impl = 1; + break; + case OPT_INKEY: + inkey = opt_arg(); + break; + case OPT_PEERKEY: + peerkey = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PEERFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform)) + goto opthelp; + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform)) + goto opthelp; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PUBIN: key_type = KEY_PUBKEY; - else if (!strcmp(*argv, "-certin")) + break; + case OPT_CERTIN: key_type = KEY_CERT; - else if (!strcmp(*argv, "-asn1parse")) + break; + case OPT_ASN1PARSE: asn1parse = 1; - else if (!strcmp(*argv, "-hexdump")) + break; + case OPT_HEXDUMP: hexdump = 1; - else if (!strcmp(*argv, "-sign")) + break; + case OPT_SIGN: pkey_op = EVP_PKEY_OP_SIGN; - else if (!strcmp(*argv, "-verify")) + break; + case OPT_VERIFY: pkey_op = EVP_PKEY_OP_VERIFY; - else if (!strcmp(*argv, "-verifyrecover")) + break; + case OPT_VERIFYRECOVER: pkey_op = EVP_PKEY_OP_VERIFYRECOVER; - else if (!strcmp(*argv, "-encrypt")) + break; + case OPT_ENCRYPT: pkey_op = EVP_PKEY_OP_ENCRYPT; - else if (!strcmp(*argv, "-decrypt")) + break; + case OPT_DECRYPT: pkey_op = EVP_PKEY_OP_DECRYPT; - else if (!strcmp(*argv, "-derive")) + break; + case OPT_DERIVE: + pkey_op = EVP_PKEY_OP_DERIVE; + break; + case OPT_KDF: pkey_op = EVP_PKEY_OP_DERIVE; - else if (!strcmp(*argv, "-rev")) + key_type = KEY_NONE; + kdfalg = opt_arg(); + break; + case OPT_KDFLEN: + kdflen = atoi(opt_arg()); + break; + case OPT_REV: rev = 1; - else if (strcmp(*argv, "-pkeyopt") == 0) { - if (--argc < 1) - badarg = 1; - else if ((pkeyopts == NULL && - (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || - sk_OPENSSL_STRING_push(pkeyopts, *++argv) == 0) { + break; + case OPT_PKEYOPT: + if ((pkeyopts == NULL && + (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || + sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) { BIO_puts(bio_err, "out of memory\n"); goto end; } - } else - badarg = 1; - if (badarg) { - usage(); - goto end; + break; } - argc--; - argv++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (inkey == NULL || - (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE)) { - usage(); - goto end; + if (kdfalg != NULL) { + if (kdflen == 0) { + BIO_printf(bio_err, + "%s: no KDF length given (-kdflen parameter).\n", prog); + goto opthelp; + } + } else if (inkey == NULL) { + BIO_printf(bio_err, + "%s: no private key given (-inkey parameter).\n", prog); + goto opthelp; + } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) { + BIO_printf(bio_err, + "%s: no peer key given (-peerkey parameter).\n", prog); + goto opthelp; } - ctx = init_ctx(&keysize, inkey, keyform, key_type, - passargin, pkey_op, e, engine_impl); - if (!ctx) { - BIO_puts(bio_err, "Error initializing context\n"); + ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type, + passinarg, pkey_op, e, engine_impl); + if (ctx == NULL) { + BIO_printf(bio_err, "%s: Error initializing context\n", prog); ERR_print_errors(bio_err); goto end; } - if (peerkey != NULL && !setup_peer(bio_err, ctx, peerform, peerkey, e)) { - BIO_puts(bio_err, "Error setting up peer key\n"); + if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) { + BIO_printf(bio_err, "%s: Error setting up peer key\n", prog); ERR_print_errors(bio_err); goto end; } @@ -237,56 +233,39 @@ int MAIN(int argc, char **argv) const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i); if (pkey_ctrl_string(ctx, opt) <= 0) { - BIO_puts(bio_err, "parameter setting error\n"); + BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n", + prog, opt); ERR_print_errors(bio_err); goto end; } } } - if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) { - BIO_puts(bio_err, "Signature file specified for non verify\n"); + if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) { + BIO_printf(bio_err, + "%s: Signature file specified for non verify\n", prog); goto end; } - if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) { - BIO_puts(bio_err, "No signature file specified for verify\n"); + if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) { + BIO_printf(bio_err, + "%s: No signature file specified for verify\n", prog); goto end; } -/* FIXME: seed PRNG only if needed */ - app_RAND_load_file(NULL, bio_err, 0); - if (pkey_op != EVP_PKEY_OP_DERIVE) { - if (infile) { - if (!(in = BIO_new_file(infile, "rb"))) { - BIO_puts(bio_err, "Error Opening Input File\n"); - ERR_print_errors(bio_err); - goto end; - } - } else - in = BIO_new_fp(stdin, BIO_NOCLOSE); - } - - if (outfile) { - if (!(out = BIO_new_file(outfile, "wb"))) { - BIO_printf(bio_err, "Error Creating Output File\n"); - ERR_print_errors(bio_err); + in = bio_open_default(infile, 'r', FORMAT_BINARY); + if (in == NULL) goto end; - } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif } + out = bio_open_default(outfile, 'w', FORMAT_BINARY); + if (out == NULL) + goto end; - if (sigfile) { + if (sigfile != NULL) { BIO *sigbio = BIO_new_file(sigfile, "rb"); - if (!sigbio) { + + if (sigbio == NULL) { BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); goto end; } @@ -298,12 +277,12 @@ int MAIN(int argc, char **argv) } } - if (in) { + if (in != NULL) { /* Read the input data */ buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); if (buf_inlen < 0) { BIO_printf(bio_err, "Error reading input Data\n"); - exit(1); + goto end; } if (rev) { size_t i; @@ -317,96 +296,76 @@ int MAIN(int argc, char **argv) } } + /* Sanity check the input */ + if (buf_inlen > EVP_MAX_MD_SIZE + && (pkey_op == EVP_PKEY_OP_SIGN + || pkey_op == EVP_PKEY_OP_VERIFY + || pkey_op == EVP_PKEY_OP_VERIFYRECOVER)) { + BIO_printf(bio_err, + "Error: The input data looks too long to be a hash\n"); + goto end; + } + if (pkey_op == EVP_PKEY_OP_VERIFY) { rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, buf_in, (size_t)buf_inlen); - if (rv == 0) - BIO_puts(out, "Signature Verification Failure\n"); - else if (rv == 1) { + if (rv == 1) { BIO_puts(out, "Signature Verified Successfully\n"); ret = 0; + } else { + BIO_puts(out, "Signature Verification Failure\n"); } - if (rv >= 0) - goto end; + goto end; + } + if (kdflen != 0) { + buf_outlen = kdflen; + rv = 1; } else { rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, buf_in, (size_t)buf_inlen); - if (rv > 0 && buf_outlen != 0) { - buf_out = OPENSSL_malloc(buf_outlen); - if (!buf_out) - rv = -1; - else - rv = do_keyop(ctx, pkey_op, - buf_out, (size_t *)&buf_outlen, - buf_in, (size_t)buf_inlen); - } } - + if (rv > 0 && buf_outlen != 0) { + buf_out = app_malloc(buf_outlen, "buffer output"); + rv = do_keyop(ctx, pkey_op, + buf_out, (size_t *)&buf_outlen, + buf_in, (size_t)buf_inlen); + } if (rv <= 0) { - BIO_printf(bio_err, "Public Key operation error\n"); + if (pkey_op != EVP_PKEY_OP_DERIVE) { + BIO_puts(bio_err, "Public Key operation error\n"); + } else { + BIO_puts(bio_err, "Key derivation failed\n"); + } ERR_print_errors(bio_err); goto end; } ret = 0; + if (asn1parse) { if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) ERR_print_errors(bio_err); - } else if (hexdump) + } else if (hexdump) { BIO_dump(out, (char *)buf_out, buf_outlen); - else + } else { BIO_write(out, buf_out, buf_outlen); + } end: - if (ctx) - EVP_PKEY_CTX_free(ctx); + EVP_PKEY_CTX_free(ctx); release_engine(e); BIO_free(in); BIO_free_all(out); - if (buf_in != NULL) - OPENSSL_free(buf_in); - if (buf_out != NULL) - OPENSSL_free(buf_out); - if (sig != NULL) - OPENSSL_free(sig); - if (pkeyopts != NULL) - sk_OPENSSL_STRING_free(pkeyopts); + OPENSSL_free(buf_in); + OPENSSL_free(buf_out); + OPENSSL_free(sig); + sk_OPENSSL_STRING_free(pkeyopts); return ret; } -static void usage() -{ - BIO_printf(bio_err, "Usage: pkeyutl [options]\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, - "-sigfile file signature file (verify operation only)\n"); - BIO_printf(bio_err, "-inkey file input key\n"); - BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); - BIO_printf(bio_err, "-pubin input is a public key\n"); - BIO_printf(bio_err, - "-certin input is a certificate carrying a public key\n"); - BIO_printf(bio_err, "-pkeyopt X:Y public key options\n"); - BIO_printf(bio_err, "-sign sign with private key\n"); - BIO_printf(bio_err, "-verify verify with public key\n"); - BIO_printf(bio_err, - "-verifyrecover verify with public key, recover original data\n"); - BIO_printf(bio_err, "-encrypt encrypt with public key\n"); - BIO_printf(bio_err, "-decrypt decrypt with private key\n"); - BIO_printf(bio_err, "-derive derive shared secret\n"); - BIO_printf(bio_err, "-hexdump hex dump output\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, maybe a hardware device, for loading keys.\n"); - BIO_printf(bio_err, "-engine_impl also use engine given by -engine for crypto operations\n"); -#endif - BIO_printf(bio_err, "-passin arg pass phrase source\n"); - -} - -static EVP_PKEY_CTX *init_ctx(int *pkeysize, +static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, - char *passargin, int pkey_op, ENGINE *e, - int engine_impl) + char *passinarg, int pkey_op, ENGINE *e, + const int engine_impl) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -416,50 +375,62 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize, X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) - && (key_type != KEY_PRIVKEY)) { + && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } - if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: - pkey = load_key(bio_err, keyfile, keyform, 0, - passin, e, "Private Key"); + pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: - pkey = load_pubkey(bio_err, keyfile, keyform, 0, - NULL, e, "Public Key"); + pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: - x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate"); + x = load_cert(keyfile, keyform, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; - } + case KEY_NONE: + break; - *pkeysize = EVP_PKEY_size(pkey); + } - if (!pkey) - goto end; - #ifndef OPENSSL_NO_ENGINE if (engine_impl) - impl = e; + impl = e; #endif - - ctx = EVP_PKEY_CTX_new(pkey, impl); - - EVP_PKEY_free(pkey); - if (!ctx) + if (kdfalg != NULL) { + int kdfnid = OBJ_sn2nid(kdfalg); + + if (kdfnid == NID_undef) { + kdfnid = OBJ_ln2nid(kdfalg); + if (kdfnid == NID_undef) { + BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n", + kdfalg); + goto end; + } + } + ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); + } else { + if (pkey == NULL) + goto end; + *pkeysize = EVP_PKEY_size(pkey); + ctx = EVP_PKEY_CTX_new(pkey, impl); + EVP_PKEY_free(pkey); + } + + if (ctx == NULL) goto end; switch (pkey_op) { @@ -494,28 +465,24 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize, } end: - - if (passin) - OPENSSL_free(passin); - + OPENSSL_free(passin); return ctx; } -static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, - const char *file, ENGINE* e) +static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, + ENGINE *e) { EVP_PKEY *peer = NULL; - ENGINE* engine = NULL; + ENGINE *engine = NULL; int ret; if (peerform == FORMAT_ENGINE) engine = e; - peer = load_pubkey(bio_err, file, peerform, 0, NULL, engine, "Peer Key"); - - if (!peer) { + peer = load_pubkey(file, peerform, 0, NULL, engine, "Peer Key"); + if (peer == NULL) { BIO_printf(bio_err, "Error reading peer key %s\n", file); - ERR_print_errors(err); + ERR_print_errors(bio_err); return 0; } @@ -523,13 +490,13 @@ static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, EVP_PKEY_free(peer); if (ret <= 0) - ERR_print_errors(err); + ERR_print_errors(bio_err); return ret; } static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, unsigned char *out, size_t *poutlen, - unsigned char *in, size_t inlen) + const unsigned char *in, size_t inlen) { int rv = 0; switch (pkey_op) { diff --git a/apps/prime.c b/apps/prime.c index d8f764a3d7f1..694479764696 100644 --- a/apps/prime.c +++ b/apps/prime.c @@ -1,162 +1,133 @@ -/* ==================================================================== - * Copyright (c) 2004 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/bn.h> -#undef PROG -#define PROG prime_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS prime_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"}, + {OPT_HELP_STR, 1, '-', + " number Number to check for primality\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"hex", OPT_HEX, '-', "Hex output"}, + {"generate", OPT_GENERATE, '-', "Generate a prime"}, + {"bits", OPT_BITS, 'p', "Size of number in bits"}, + {"safe", OPT_SAFE, '-', + "When used with -generate, generate a safe prime"}, + {"checks", OPT_CHECKS, 'p', "Number of checks"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int prime_main(int argc, char **argv) { - int hex = 0; - int checks = 20; - int generate = 0; - int bits = 0; - int safe = 0; BIGNUM *bn = NULL; - BIO *bio_out; + int hex = 0, checks = 20, generate = 0, bits = 0, safe = 0, ret = 1; + char *prog; + OPTION_CHOICE o; - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - --argc; - ++argv; - while (argc >= 1 && **argv == '-') { - if (!strcmp(*argv, "-hex")) + prog = opt_init(argc, argv, prime_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(prime_options); + ret = 0; + goto end; + case OPT_HEX: hex = 1; - else if (!strcmp(*argv, "-generate")) + break; + case OPT_GENERATE: generate = 1; - else if (!strcmp(*argv, "-bits")) - if (--argc < 1) - goto bad; - else - bits = atoi(*++argv); - else if (!strcmp(*argv, "-safe")) + break; + case OPT_BITS: + bits = atoi(opt_arg()); + break; + case OPT_SAFE: safe = 1; - else if (!strcmp(*argv, "-checks")) - if (--argc < 1) - goto bad; - else - checks = atoi(*++argv); - else { - BIO_printf(bio_err, "Unknown option '%s'\n", *argv); - goto bad; + break; + case OPT_CHECKS: + checks = atoi(opt_arg()); + break; } - --argc; - ++argv; - } - - if (argv[0] == NULL && !generate) { - BIO_printf(bio_err, "No prime specified\n"); - goto bad; } + argc = opt_num_rest(); + argv = opt_rest(); - if ((bio_out = BIO_new(BIO_s_file())) != NULL) { - BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - bio_out = BIO_push(tmpbio, bio_out); + if (generate) { + if (argc != 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; } -#endif + } else if (argc == 0) { + BIO_printf(bio_err, "%s: No prime specified\n", prog); + goto opthelp; } if (generate) { char *s; if (!bits) { - BIO_printf(bio_err, "Specifiy the number of bits.\n"); - return 1; + BIO_printf(bio_err, "Specify the number of bits.\n"); + goto end; } bn = BN_new(); - BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL); + if (bn == NULL) { + BIO_printf(bio_err, "Out of memory.\n"); + goto end; + } + if (!BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL)) { + BIO_printf(bio_err, "Failed to generate prime.\n"); + goto end; + } s = hex ? BN_bn2hex(bn) : BN_bn2dec(bn); + if (s == NULL) { + BIO_printf(bio_err, "Out of memory.\n"); + goto end; + } BIO_printf(bio_out, "%s\n", s); OPENSSL_free(s); } else { - int r; + for ( ; *argv; argv++) { + int r; - if (hex) - r = BN_hex2bn(&bn, argv[0]); - else - r = BN_dec2bn(&bn, argv[0]); + if (hex) + r = BN_hex2bn(&bn, argv[0]); + else + r = BN_dec2bn(&bn, argv[0]); - if(!r) { - BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]); - goto end; - } + if (!r) { + BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]); + goto end; + } - BN_print(bio_out, bn); - BIO_printf(bio_out, " is %sprime\n", - BN_is_prime_ex(bn, checks, NULL, NULL) ? "" : "not "); + BN_print(bio_out, bn); + BIO_printf(bio_out, " (%s) %s prime\n", + argv[0], + BN_is_prime_ex(bn, checks, NULL, NULL) + ? "is" : "is not"); + } } + ret = 0; end: BN_free(bn); - BIO_free_all(bio_out); - - return 0; - - bad: - BIO_printf(bio_err, "options are\n"); - BIO_printf(bio_err, "%-14s hex\n", "-hex"); - BIO_printf(bio_err, "%-14s number of checks\n", "-checks <n>"); - BIO_printf(bio_err, "%-14s generate prime\n", "-generate"); - BIO_printf(bio_err, "%-14s number of bits\n", "-bits <n>"); - BIO_printf(bio_err, "%-14s safe prime\n", "-safe"); - return 1; + return ret; } diff --git a/apps/privkey.pem b/apps/privkey.pem index 0af46474a7ee..02f34981ec71 100644 --- a/apps/privkey.pem +++ b/apps/privkey.pem @@ -1,18 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,BA26229A1653B7FF - -6nhWG8PKhTPO/s3ZvjUa6226NlKdvPDZFsNXOOoSUs9ejxpb/aj5huhs6qRYzsz9 -Year47uaAZYhGD0vAagnNiBnYmjWEpN9G/wQxG7pgZThK1ZxDi63qn8aQ8UjuGHo -F6RpnnBQIAnWTWqr/Qsybtc5EoNkrj/Cpx0OfbSr6gZsFBCxwX1R1hT3/mhJ45f3 -XMofY32Vdfx9/vtw1O7HmlHXQnXaqnbd9/nn1EpvFJG9+UjPoW7gV4jCOLuR4deE -jS8hm+cpkwXmFtk3VGjT9tQXPpMv3JpYfBqgGQoMAJ5Toq0DWcHi6Wg08PsD8lgy -vmTioPsRg+JGkJkJ8GnusgLpQdlQJbjzd7wGE6ElUFLfOxLo8bLlRHoriHNdWYhh -JjY0LyeTkovcmWxVjImc6ZyBz5Ly4t0BYf1gq3OkjsV91Q1taBxnhiavfizqMCAf -PPB3sLQnlXG77TOXkNxpqbZfEYrVZW2Nsqqdn8s07Uj4IMONZyq2odYKWFPMJBiM -POYwXjMAOcmFMTHYsVlhcUJuV6LOuipw/FEbTtPH/MYMxLe4zx65dYo1rb4iLKLS -gMtB0o/Wl4Xno3ZXh1ucicYnV2J7NpVcjVq+3SFiCRu2SrSkZHZ23EPS13Ec6fcz -8X/YGA2vTJ8MAOozAzQUwHQYvLk7bIoQVekqDq4p0AZQbhdspHpArCk0Ifqqzg/v -Uyky/zZiQYanzDenTSRVI/8wac3olxpU8QvbySxYqmbkgq6bTpXJfYFQfnAttEsC -dA4S5UFgyOPZluxCAM4yaJF3Ft6neutNwftuJQMbgCUi9vYg2tGdSw== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMo7DFNMqywUA1O/ +qvWqCOm6rGrUAcR+dKsSXw6y2qiKO7APDDyotc0b4Mxwqjga98npex2RBIwUoCGJ +iEmMXo/a8RbXVUZ+ZwcAX7PC+XeXVC5qoajaBBkd2MvYmib/2PqnNrgvhHsUL5dO +xhC7cRqxLM/g45k3Yyw+nGa+WkTdAgMBAAECgYBMBT5w4dVG0I8foGFnz+9hzWab +Ee9IKjE5TcKmB93ilXQyjrWO5+zPmbc7ou6aAKk9IaPCTY1kCyzW7pho7Xdt+RFq +TgVXGZZfqtixO7f2/5oqZAkd00eOn9ZrhBpVMu4yXbbDvhDyFe4/oy0HGDjRUhxa +Lf6ZlBuTherxm4eFkQJBAPBQwRs9UtqaMAQlagA9pV5UsQjV1WT4IxDURMPfXgCd +ETNkB6pP0SmxQm5xhv9N2HY1UtoWpug9s0OU5IJB15sCQQDXbfbjiujNbuOxCFNw +68JZaCFVdNovyOWORkpenQLNEjVkmTCS9OayK09ADEYtsdpUGKeF+2EYBNkFr5px +CajnAkBMYI4PNz1HBuwt1SpMa0tMoMQnV7bbwVV7usskKbC5pzHZUHhzM6z5gEHp +0iEisT4Ty7zKXZqsgzefSgoaMAzzAkEAoCIaUhtwXzwdPfvNYnOs3J6doJMimECB ++lbfcyLM8TimvadtRt+KGEg/OYGmLNM2UiqdY+duzdbUpvhYGcwvYwJAQvaoi9z2 +CkiwSs/PFrLaNlfLJmXRsUBzmiWYoh6+IQJJorEXz7ewI72ee9RBO4s746cgUFwH +Ri+qO+HhZFUBqQ== +-----END PRIVATE KEY----- diff --git a/apps/progs.h b/apps/progs.h deleted file mode 100644 index d5c0039bd69d..000000000000 --- a/apps/progs.h +++ /dev/null @@ -1,366 +0,0 @@ -/* apps/progs.h */ -/* automatically generated by progs.pl for openssl.c */ - -extern int verify_main(int argc, char *argv[]); -extern int asn1parse_main(int argc, char *argv[]); -extern int req_main(int argc, char *argv[]); -extern int dgst_main(int argc, char *argv[]); -extern int dh_main(int argc, char *argv[]); -extern int dhparam_main(int argc, char *argv[]); -extern int enc_main(int argc, char *argv[]); -extern int passwd_main(int argc, char *argv[]); -extern int gendh_main(int argc, char *argv[]); -extern int errstr_main(int argc, char *argv[]); -extern int ca_main(int argc, char *argv[]); -extern int crl_main(int argc, char *argv[]); -extern int rsa_main(int argc, char *argv[]); -extern int rsautl_main(int argc, char *argv[]); -extern int dsa_main(int argc, char *argv[]); -extern int dsaparam_main(int argc, char *argv[]); -extern int ec_main(int argc, char *argv[]); -extern int ecparam_main(int argc, char *argv[]); -extern int x509_main(int argc, char *argv[]); -extern int genrsa_main(int argc, char *argv[]); -extern int gendsa_main(int argc, char *argv[]); -extern int genpkey_main(int argc, char *argv[]); -extern int s_server_main(int argc, char *argv[]); -extern int s_client_main(int argc, char *argv[]); -extern int speed_main(int argc, char *argv[]); -extern int s_time_main(int argc, char *argv[]); -extern int version_main(int argc, char *argv[]); -extern int pkcs7_main(int argc, char *argv[]); -extern int cms_main(int argc, char *argv[]); -extern int crl2pkcs7_main(int argc, char *argv[]); -extern int sess_id_main(int argc, char *argv[]); -extern int ciphers_main(int argc, char *argv[]); -extern int nseq_main(int argc, char *argv[]); -extern int pkcs12_main(int argc, char *argv[]); -extern int pkcs8_main(int argc, char *argv[]); -extern int pkey_main(int argc, char *argv[]); -extern int pkeyparam_main(int argc, char *argv[]); -extern int pkeyutl_main(int argc, char *argv[]); -extern int spkac_main(int argc, char *argv[]); -extern int smime_main(int argc, char *argv[]); -extern int rand_main(int argc, char *argv[]); -extern int engine_main(int argc, char *argv[]); -extern int ocsp_main(int argc, char *argv[]); -extern int prime_main(int argc, char *argv[]); -extern int ts_main(int argc, char *argv[]); -extern int srp_main(int argc, char *argv[]); - -#define FUNC_TYPE_GENERAL 1 -#define FUNC_TYPE_MD 2 -#define FUNC_TYPE_CIPHER 3 -#define FUNC_TYPE_PKEY 4 -#define FUNC_TYPE_MD_ALG 5 -#define FUNC_TYPE_CIPHER_ALG 6 - -typedef struct { - int type; - const char *name; - int (*func)(int argc, char *argv[]); -} FUNCTION; -DECLARE_LHASH_OF(FUNCTION); - -FUNCTION functions[] = { - {FUNC_TYPE_GENERAL, "verify", verify_main}, - {FUNC_TYPE_GENERAL, "asn1parse", asn1parse_main}, - {FUNC_TYPE_GENERAL, "req", req_main}, - {FUNC_TYPE_GENERAL, "dgst", dgst_main}, -#ifndef OPENSSL_NO_DH - {FUNC_TYPE_GENERAL, "dh", dh_main}, -#endif -#ifndef OPENSSL_NO_DH - {FUNC_TYPE_GENERAL, "dhparam", dhparam_main}, -#endif - {FUNC_TYPE_GENERAL, "enc", enc_main}, - {FUNC_TYPE_GENERAL, "passwd", passwd_main}, -#ifndef OPENSSL_NO_DH - {FUNC_TYPE_GENERAL, "gendh", gendh_main}, -#endif - {FUNC_TYPE_GENERAL, "errstr", errstr_main}, - {FUNC_TYPE_GENERAL, "ca", ca_main}, - {FUNC_TYPE_GENERAL, "crl", crl_main}, -#ifndef OPENSSL_NO_RSA - {FUNC_TYPE_GENERAL, "rsa", rsa_main}, -#endif -#ifndef OPENSSL_NO_RSA - {FUNC_TYPE_GENERAL, "rsautl", rsautl_main}, -#endif -#ifndef OPENSSL_NO_DSA - {FUNC_TYPE_GENERAL, "dsa", dsa_main}, -#endif -#ifndef OPENSSL_NO_DSA - {FUNC_TYPE_GENERAL, "dsaparam", dsaparam_main}, -#endif -#ifndef OPENSSL_NO_EC - {FUNC_TYPE_GENERAL, "ec", ec_main}, -#endif -#ifndef OPENSSL_NO_EC - {FUNC_TYPE_GENERAL, "ecparam", ecparam_main}, -#endif - {FUNC_TYPE_GENERAL, "x509", x509_main}, -#ifndef OPENSSL_NO_RSA - {FUNC_TYPE_GENERAL, "genrsa", genrsa_main}, -#endif -#ifndef OPENSSL_NO_DSA - {FUNC_TYPE_GENERAL, "gendsa", gendsa_main}, -#endif - {FUNC_TYPE_GENERAL, "genpkey", genpkey_main}, -#if !defined(OPENSSL_NO_SOCK) - {FUNC_TYPE_GENERAL, "s_server", s_server_main}, -#endif -#if !defined(OPENSSL_NO_SOCK) - {FUNC_TYPE_GENERAL, "s_client", s_client_main}, -#endif -#ifndef OPENSSL_NO_SPEED - {FUNC_TYPE_GENERAL, "speed", speed_main}, -#endif -#if !defined(OPENSSL_NO_SOCK) - {FUNC_TYPE_GENERAL, "s_time", s_time_main}, -#endif - {FUNC_TYPE_GENERAL, "version", version_main}, - {FUNC_TYPE_GENERAL, "pkcs7", pkcs7_main}, -#ifndef OPENSSL_NO_CMS - {FUNC_TYPE_GENERAL, "cms", cms_main}, -#endif - {FUNC_TYPE_GENERAL, "crl2pkcs7", crl2pkcs7_main}, - {FUNC_TYPE_GENERAL, "sess_id", sess_id_main}, -#if !defined(OPENSSL_NO_SOCK) - {FUNC_TYPE_GENERAL, "ciphers", ciphers_main}, -#endif - {FUNC_TYPE_GENERAL, "nseq", nseq_main}, -#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) - {FUNC_TYPE_GENERAL, "pkcs12", pkcs12_main}, -#endif - {FUNC_TYPE_GENERAL, "pkcs8", pkcs8_main}, - {FUNC_TYPE_GENERAL, "pkey", pkey_main}, - {FUNC_TYPE_GENERAL, "pkeyparam", pkeyparam_main}, - {FUNC_TYPE_GENERAL, "pkeyutl", pkeyutl_main}, - {FUNC_TYPE_GENERAL, "spkac", spkac_main}, - {FUNC_TYPE_GENERAL, "smime", smime_main}, - {FUNC_TYPE_GENERAL, "rand", rand_main}, -#ifndef OPENSSL_NO_ENGINE - {FUNC_TYPE_GENERAL, "engine", engine_main}, -#endif -#ifndef OPENSSL_NO_OCSP - {FUNC_TYPE_GENERAL, "ocsp", ocsp_main}, -#endif - {FUNC_TYPE_GENERAL, "prime", prime_main}, - {FUNC_TYPE_GENERAL, "ts", ts_main}, -#ifndef OPENSSL_NO_SRP - {FUNC_TYPE_GENERAL, "srp", srp_main}, -#endif -#ifndef OPENSSL_NO_MD2 - {FUNC_TYPE_MD, "md2", dgst_main}, -#endif -#ifndef OPENSSL_NO_MD4 - {FUNC_TYPE_MD, "md4", dgst_main}, -#endif -#ifndef OPENSSL_NO_MD5 - {FUNC_TYPE_MD, "md5", dgst_main}, -#endif -#ifndef OPENSSL_NO_SHA - {FUNC_TYPE_MD, "sha", dgst_main}, -#endif -#ifndef OPENSSL_NO_SHA1 - {FUNC_TYPE_MD, "sha1", dgst_main}, -#endif -#ifndef OPENSSL_NO_MDC2 - {FUNC_TYPE_MD, "mdc2", dgst_main}, -#endif -#ifndef OPENSSL_NO_RMD160 - {FUNC_TYPE_MD, "rmd160", dgst_main}, -#endif -#ifndef OPENSSL_NO_AES - {FUNC_TYPE_CIPHER, "aes-128-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_AES - {FUNC_TYPE_CIPHER, "aes-128-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_AES - {FUNC_TYPE_CIPHER, "aes-192-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_AES - {FUNC_TYPE_CIPHER, "aes-192-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_AES - {FUNC_TYPE_CIPHER, "aes-256-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_AES - {FUNC_TYPE_CIPHER, "aes-256-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_CAMELLIA - {FUNC_TYPE_CIPHER, "camellia-128-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_CAMELLIA - {FUNC_TYPE_CIPHER, "camellia-128-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_CAMELLIA - {FUNC_TYPE_CIPHER, "camellia-192-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_CAMELLIA - {FUNC_TYPE_CIPHER, "camellia-192-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_CAMELLIA - {FUNC_TYPE_CIPHER, "camellia-256-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_CAMELLIA - {FUNC_TYPE_CIPHER, "camellia-256-ecb", enc_main}, -#endif - {FUNC_TYPE_CIPHER, "base64", enc_main}, -#ifdef ZLIB - {FUNC_TYPE_CIPHER, "zlib", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des3", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "desx", enc_main}, -#endif -#ifndef OPENSSL_NO_IDEA - {FUNC_TYPE_CIPHER, "idea", enc_main}, -#endif -#ifndef OPENSSL_NO_SEED - {FUNC_TYPE_CIPHER, "seed", enc_main}, -#endif -#ifndef OPENSSL_NO_RC4 - {FUNC_TYPE_CIPHER, "rc4", enc_main}, -#endif -#ifndef OPENSSL_NO_RC4 - {FUNC_TYPE_CIPHER, "rc4-40", enc_main}, -#endif -#ifndef OPENSSL_NO_RC2 - {FUNC_TYPE_CIPHER, "rc2", enc_main}, -#endif -#ifndef OPENSSL_NO_BF - {FUNC_TYPE_CIPHER, "bf", enc_main}, -#endif -#ifndef OPENSSL_NO_CAST - {FUNC_TYPE_CIPHER, "cast", enc_main}, -#endif -#ifndef OPENSSL_NO_RC5 - {FUNC_TYPE_CIPHER, "rc5", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede3", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede3-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede3-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_DES - {FUNC_TYPE_CIPHER, "des-ede3-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_IDEA - {FUNC_TYPE_CIPHER, "idea-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_IDEA - {FUNC_TYPE_CIPHER, "idea-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_IDEA - {FUNC_TYPE_CIPHER, "idea-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_IDEA - {FUNC_TYPE_CIPHER, "idea-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_SEED - {FUNC_TYPE_CIPHER, "seed-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_SEED - {FUNC_TYPE_CIPHER, "seed-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_SEED - {FUNC_TYPE_CIPHER, "seed-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_SEED - {FUNC_TYPE_CIPHER, "seed-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_RC2 - {FUNC_TYPE_CIPHER, "rc2-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_RC2 - {FUNC_TYPE_CIPHER, "rc2-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_RC2 - {FUNC_TYPE_CIPHER, "rc2-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_RC2 - {FUNC_TYPE_CIPHER, "rc2-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_RC2 - {FUNC_TYPE_CIPHER, "rc2-64-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_RC2 - {FUNC_TYPE_CIPHER, "rc2-40-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_BF - {FUNC_TYPE_CIPHER, "bf-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_BF - {FUNC_TYPE_CIPHER, "bf-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_BF - {FUNC_TYPE_CIPHER, "bf-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_BF - {FUNC_TYPE_CIPHER, "bf-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_CAST - {FUNC_TYPE_CIPHER, "cast5-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_CAST - {FUNC_TYPE_CIPHER, "cast5-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_CAST - {FUNC_TYPE_CIPHER, "cast5-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_CAST - {FUNC_TYPE_CIPHER, "cast5-ofb", enc_main}, -#endif -#ifndef OPENSSL_NO_CAST - {FUNC_TYPE_CIPHER, "cast-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_RC5 - {FUNC_TYPE_CIPHER, "rc5-cbc", enc_main}, -#endif -#ifndef OPENSSL_NO_RC5 - {FUNC_TYPE_CIPHER, "rc5-ecb", enc_main}, -#endif -#ifndef OPENSSL_NO_RC5 - {FUNC_TYPE_CIPHER, "rc5-cfb", enc_main}, -#endif -#ifndef OPENSSL_NO_RC5 - {FUNC_TYPE_CIPHER, "rc5-ofb", enc_main}, -#endif - {0, NULL, NULL} -}; diff --git a/apps/progs.pl b/apps/progs.pl index 73498e3d6efa..57671405dda0 100644 --- a/apps/progs.pl +++ b/apps/progs.pl @@ -1,104 +1,181 @@ -#!/usr/local/bin/perl +#! /usr/bin/env perl +# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html -print "/* apps/progs.h */\n"; -print "/* automatically generated by progs.pl for openssl.c */\n\n"; +# Generate progs.h file by looking for command mains in list of C files +# passed on the command line. -grep(s/^asn1pars$/asn1parse/,@ARGV); +use strict; +use warnings; +use lib '.'; +use configdata qw/@disablables %unified_info/; -foreach (@ARGV) - { printf "extern int %s_main(int argc, char *argv[]);\n",$_; } +my %commands = (); +my $cmdre = qr/^\s*int\s+([a-z_][a-z0-9_]*)_main\(\s*int\s+argc\s*,/; +my $apps_openssl = shift @ARGV; +my $YEAR = [localtime()]->[5] + 1900; -print <<'EOF'; +# because the program apps/openssl has object files as sources, and +# they then have the corresponding C files as source, we need to chain +# the lookups in %unified_info +my @openssl_source = + map { @{$unified_info{sources}->{$_}} } + grep { /\.o$/ } + @{$unified_info{sources}->{$apps_openssl}}; -#define FUNC_TYPE_GENERAL 1 -#define FUNC_TYPE_MD 2 -#define FUNC_TYPE_CIPHER 3 -#define FUNC_TYPE_PKEY 4 -#define FUNC_TYPE_MD_ALG 5 -#define FUNC_TYPE_CIPHER_ALG 6 +foreach my $filename (@openssl_source) { + open F, $filename or die "Couldn't open $filename: $!\n"; + foreach ( grep /$cmdre/, <F> ) { + my @foo = /$cmdre/; + $commands{$1} = 1; + } + close F; +} -typedef struct { - int type; +@ARGV = sort keys %commands; + +print <<"EOF"; +/* + * WARNING: do not edit! + * Generated by apps/progs.pl + * + * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +typedef enum FUNC_TYPE { + FT_none, FT_general, FT_md, FT_cipher, FT_pkey, + FT_md_alg, FT_cipher_alg +} FUNC_TYPE; + +typedef struct function_st { + FUNC_TYPE type; const char *name; int (*func)(int argc, char *argv[]); + const OPTIONS *help; } FUNCTION; -DECLARE_LHASH_OF(FUNCTION); -FUNCTION functions[] = { +DEFINE_LHASH_OF(FUNCTION); + EOF -foreach (@ARGV) - { - push(@files,$_); - $str=" {FUNC_TYPE_GENERAL, \"$_\", ${_}_main},\n"; - if (($_ =~ /^s_/) || ($_ =~ /^ciphers$/)) - { print "#if !defined(OPENSSL_NO_SOCK)\n${str}#endif\n"; } - elsif ( ($_ =~ /^speed$/)) - { print "#ifndef OPENSSL_NO_SPEED\n${str}#endif\n"; } - elsif ( ($_ =~ /^engine$/)) - { print "#ifndef OPENSSL_NO_ENGINE\n${str}#endif\n"; } - elsif ( ($_ =~ /^rsa$/) || ($_ =~ /^genrsa$/) || ($_ =~ /^rsautl$/)) - { print "#ifndef OPENSSL_NO_RSA\n${str}#endif\n"; } - elsif ( ($_ =~ /^dsa$/) || ($_ =~ /^gendsa$/) || ($_ =~ /^dsaparam$/)) - { print "#ifndef OPENSSL_NO_DSA\n${str}#endif\n"; } - elsif ( ($_ =~ /^ec$/) || ($_ =~ /^ecparam$/)) - { print "#ifndef OPENSSL_NO_EC\n${str}#endif\n";} - elsif ( ($_ =~ /^dh$/) || ($_ =~ /^gendh$/) || ($_ =~ /^dhparam$/)) - { print "#ifndef OPENSSL_NO_DH\n${str}#endif\n"; } - elsif ( ($_ =~ /^pkcs12$/)) - { print "#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1)\n${str}#endif\n"; } - elsif ( ($_ =~ /^cms$/)) - { print "#ifndef OPENSSL_NO_CMS\n${str}#endif\n"; } - elsif ( ($_ =~ /^ocsp$/)) - { print "#ifndef OPENSSL_NO_OCSP\n${str}#endif\n"; } - elsif ( ($_ =~ /^srp$/)) - { print "#ifndef OPENSSL_NO_SRP\n${str}#endif\n"; } - else - { print $str; } - } +foreach (@ARGV) { + printf "extern int %s_main(int argc, char *argv[]);\n", $_; +} +print "\n"; + +foreach (@ARGV) { + printf "extern const OPTIONS %s_options[];\n", $_; +} +print "\n"; + +my %cmd_disabler = ( + ciphers => "sock", + genrsa => "rsa", + rsautl => "rsa", + gendsa => "dsa", + dsaparam => "dsa", + gendh => "dh", + dhparam => "dh", + ecparam => "ec", + pkcs12 => "des", +); -foreach ("md2","md4","md5","sha","sha1","mdc2","rmd160") - { - push(@files,$_); - printf "#ifndef OPENSSL_NO_".uc($_)."\n {FUNC_TYPE_MD, \"".$_."\", dgst_main},\n#endif\n"; - } +print "#ifdef INCLUDE_FUNCTION_TABLE\n"; +print "static FUNCTION functions[] = {\n"; +foreach my $cmd ( @ARGV ) { + my $str = " {FT_general, \"$cmd\", ${cmd}_main, ${cmd}_options},\n"; + if ($cmd =~ /^s_/) { + print "#ifndef OPENSSL_NO_SOCK\n${str}#endif\n"; + } elsif (grep { $cmd eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; + } elsif (my $disabler = $cmd_disabler{$cmd}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } +} -foreach ( - "aes-128-cbc", "aes-128-ecb", - "aes-192-cbc", "aes-192-ecb", - "aes-256-cbc", "aes-256-ecb", - "camellia-128-cbc", "camellia-128-ecb", - "camellia-192-cbc", "camellia-192-ecb", - "camellia-256-cbc", "camellia-256-ecb", - "base64", "zlib", - "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40", - "rc2", "bf", "cast", "rc5", - "des-ecb", "des-ede", "des-ede3", - "des-cbc", "des-ede-cbc","des-ede3-cbc", - "des-cfb", "des-ede-cfb","des-ede3-cfb", - "des-ofb", "des-ede-ofb","des-ede3-ofb", - "idea-cbc","idea-ecb", "idea-cfb", "idea-ofb", - "seed-cbc","seed-ecb", "seed-cfb", "seed-ofb", - "rc2-cbc", "rc2-ecb", "rc2-cfb","rc2-ofb", "rc2-64-cbc", "rc2-40-cbc", - "bf-cbc", "bf-ecb", "bf-cfb", "bf-ofb", - "cast5-cbc","cast5-ecb", "cast5-cfb","cast5-ofb", - "cast-cbc", "rc5-cbc", "rc5-ecb", "rc5-cfb", "rc5-ofb") - { - push(@files,$_); +my %md_disabler = ( + blake2b512 => "blake2", + blake2s256 => "blake2", +); +foreach my $cmd ( + "md2", "md4", "md5", + "gost", + "sha1", "sha224", "sha256", "sha384", + "sha512", "sha512-224", "sha512-256", + "sha3-224", "sha3-256", "sha3-384", "sha3-512", + "shake128", "shake256", + "mdc2", "rmd160", "blake2b512", "blake2s256", + "sm3" +) { + my $str = " {FT_md, \"$cmd\", dgst_main},\n"; + if (grep { $cmd eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; + } elsif (my $disabler = $md_disabler{$cmd}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } +} - $t=sprintf(" {FUNC_TYPE_CIPHER, \"%s\", enc_main},\n",$_); - if ($_ =~ /des/) { $t="#ifndef OPENSSL_NO_DES\n${t}#endif\n"; } - elsif ($_ =~ /aes/) { $t="#ifndef OPENSSL_NO_AES\n${t}#endif\n"; } - elsif ($_ =~ /camellia/) { $t="#ifndef OPENSSL_NO_CAMELLIA\n${t}#endif\n"; } - elsif ($_ =~ /idea/) { $t="#ifndef OPENSSL_NO_IDEA\n${t}#endif\n"; } - elsif ($_ =~ /seed/) { $t="#ifndef OPENSSL_NO_SEED\n${t}#endif\n"; } - elsif ($_ =~ /rc4/) { $t="#ifndef OPENSSL_NO_RC4\n${t}#endif\n"; } - elsif ($_ =~ /rc2/) { $t="#ifndef OPENSSL_NO_RC2\n${t}#endif\n"; } - elsif ($_ =~ /bf/) { $t="#ifndef OPENSSL_NO_BF\n${t}#endif\n"; } - elsif ($_ =~ /cast/) { $t="#ifndef OPENSSL_NO_CAST\n${t}#endif\n"; } - elsif ($_ =~ /rc5/) { $t="#ifndef OPENSSL_NO_RC5\n${t}#endif\n"; } - elsif ($_ =~ /zlib/) { $t="#ifdef ZLIB\n${t}#endif\n"; } - print $t; - } +my %cipher_disabler = ( + des3 => "des", + desx => "des", + cast5 => "cast", +); +foreach my $cmd ( + "aes-128-cbc", "aes-128-ecb", + "aes-192-cbc", "aes-192-ecb", + "aes-256-cbc", "aes-256-ecb", + "aria-128-cbc", "aria-128-cfb", + "aria-128-ctr", "aria-128-ecb", "aria-128-ofb", + "aria-128-cfb1", "aria-128-cfb8", + "aria-192-cbc", "aria-192-cfb", + "aria-192-ctr", "aria-192-ecb", "aria-192-ofb", + "aria-192-cfb1", "aria-192-cfb8", + "aria-256-cbc", "aria-256-cfb", + "aria-256-ctr", "aria-256-ecb", "aria-256-ofb", + "aria-256-cfb1", "aria-256-cfb8", + "camellia-128-cbc", "camellia-128-ecb", + "camellia-192-cbc", "camellia-192-ecb", + "camellia-256-cbc", "camellia-256-ecb", + "base64", "zlib", + "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40", + "rc2", "bf", "cast", "rc5", + "des-ecb", "des-ede", "des-ede3", + "des-cbc", "des-ede-cbc","des-ede3-cbc", + "des-cfb", "des-ede-cfb","des-ede3-cfb", + "des-ofb", "des-ede-ofb","des-ede3-ofb", + "idea-cbc","idea-ecb", "idea-cfb", "idea-ofb", + "seed-cbc","seed-ecb", "seed-cfb", "seed-ofb", + "rc2-cbc", "rc2-ecb", "rc2-cfb","rc2-ofb", "rc2-64-cbc", "rc2-40-cbc", + "bf-cbc", "bf-ecb", "bf-cfb", "bf-ofb", + "cast5-cbc","cast5-ecb", "cast5-cfb","cast5-ofb", + "cast-cbc", "rc5-cbc", "rc5-ecb", "rc5-cfb", "rc5-ofb", + "sm4-cbc", "sm4-ecb", "sm4-cfb", "sm4-ofb", "sm4-ctr" +) { + my $str = " {FT_cipher, \"$cmd\", enc_main, enc_options},\n"; + (my $algo = $cmd) =~ s/-.*//g; + if ($cmd eq "zlib") { + print "#ifdef ZLIB\n${str}#endif\n"; + } elsif (grep { $algo eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($algo) . "\n${str}#endif\n"; + } elsif (my $disabler = $cipher_disabler{$algo}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } +} print " {0, NULL, NULL}\n};\n"; +print "#endif\n"; diff --git a/apps/rand.c b/apps/rand.c index eddb8af8d70a..4c6181507bd5 100644 --- a/apps/rand.c +++ b/apps/rand.c @@ -1,59 +1,14 @@ -/* apps/rand.c */ -/* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include "apps.h" +#include "progs.h" #include <ctype.h> #include <stdio.h> @@ -63,132 +18,82 @@ #include <openssl/err.h> #include <openssl/rand.h> -#undef PROG -#define PROG rand_main - -/*- - * -out file - write to file - * -rand file:file - PRNG seed files - * -base64 - base64 encode output - * -hex - hex encode output - * num - write 'num' bytes - */ +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, + OPT_R_ENUM +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS rand_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [flags] num\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output file"}, + OPT_R_OPTIONS, + {"base64", OPT_BASE64, '-', "Base64 encode output"}, + {"hex", OPT_HEX, '-', "Hex encode output"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int rand_main(int argc, char **argv) { - int i, r, ret = 1; - int badopt; - char *outfile = NULL; - char *inrand = NULL; - int base64 = 0; - int hex = 0; - BIO *out = NULL; - int num = -1; ENGINE *e = NULL; - char *engine = NULL; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto err; + BIO *out = NULL; + char *outfile = NULL, *prog; + OPTION_CHOICE o; + int format = FORMAT_BINARY, i, num = -1, r, ret = 1; - badopt = 0; - i = 0; - while (!badopt && argv[++i] != NULL) { - if (strcmp(argv[i], "-out") == 0) { - if ((argv[i + 1] != NULL) && (outfile == NULL)) - outfile = argv[++i]; - else - badopt = 1; - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(argv[i], "-engine") == 0) { - if ((argv[i + 1] != NULL) && (engine == NULL)) - engine = argv[++i]; - else - badopt = 1; + prog = opt_init(argc, argv, rand_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rand_options); + ret = 0; + goto end; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_BASE64: + format = FORMAT_BASE64; + break; + case OPT_HEX: + format = FORMAT_TEXT; + break; } -#endif - else if (strcmp(argv[i], "-rand") == 0) { - if ((argv[i + 1] != NULL) && (inrand == NULL)) - inrand = argv[++i]; - else - badopt = 1; - } else if (strcmp(argv[i], "-base64") == 0) { - if (!base64) - base64 = 1; - else - badopt = 1; - } else if (strcmp(argv[i], "-hex") == 0) { - if (!hex) - hex = 1; - else - badopt = 1; - } else if (isdigit((unsigned char)argv[i][0])) { - if (num < 0) { - r = sscanf(argv[i], "%d", &num); - if (r == 0 || num < 0) - badopt = 1; - } else - badopt = 1; - } else - badopt = 1; } - - if (hex && base64) - badopt = 1; - - if (num < 0) - badopt = 1; - - if (badopt) { - BIO_printf(bio_err, "Usage: rand [options] num\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-out file - write to file\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e - use engine e, possibly a hardware device.\n"); -#endif - BIO_printf(bio_err, "-rand file%cfile%c... - seed PRNG from files\n", - LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, "-base64 - base64 encode output\n"); - BIO_printf(bio_err, "-hex - hex encode output\n"); - goto err; + argc = opt_num_rest(); + argv = opt_rest(); + if (argc == 1) { + if (!opt_int(argv[0], &num) || num <= 0) + goto end; + } else if (argc > 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; } - e = setup_engine(bio_err, engine, 0); - - app_RAND_load_file(NULL, bio_err, (inrand != NULL)); - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - out = BIO_new(BIO_s_file()); + out = bio_open_default(outfile, 'w', format); if (out == NULL) - goto err; - if (outfile != NULL) - r = BIO_write_filename(out, outfile); - else { - r = BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } - if (r <= 0) - goto err; + goto end; - if (base64) { + if (format == FORMAT_BASE64) { BIO *b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) - goto err; + goto end; out = BIO_push(b64, out); } @@ -201,27 +106,28 @@ int MAIN(int argc, char **argv) chunk = sizeof(buf); r = RAND_bytes(buf, chunk); if (r <= 0) - goto err; - if (!hex) - BIO_write(out, buf, chunk); - else { + goto end; + if (format != FORMAT_TEXT) { + if (BIO_write(out, buf, chunk) != chunk) + goto end; + } else { for (i = 0; i < chunk; i++) - BIO_printf(out, "%02x", buf[i]); + if (BIO_printf(out, "%02x", buf[i]) != 2) + goto end; } num -= chunk; } - if (hex) + if (format == FORMAT_TEXT) BIO_puts(out, "\n"); - (void)BIO_flush(out); + if (BIO_flush(out) <= 0) + goto end; - app_RAND_write_file(NULL, bio_err); ret = 0; - err: - ERR_print_errors(bio_err); + end: + if (ret != 0) + ERR_print_errors(bio_err); release_engine(e); - if (out) - BIO_free_all(out); - apps_shutdown(); - OPENSSL_EXIT(ret); + BIO_free_all(out); + return ret; } diff --git a/apps/rehash.c b/apps/rehash.c new file mode 100644 index 000000000000..de7217cb1003 --- /dev/null +++ b/apps/rehash.c @@ -0,0 +1,512 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2013-2014 Timo Teräs <timo.teras@gmail.com> + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include "progs.h" + +#if defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) || \ + (defined(__VMS) && defined(__DECC) && __CRTL_VER >= 80300000) +# include <unistd.h> +# include <stdio.h> +# include <limits.h> +# include <errno.h> +# include <string.h> +# include <ctype.h> +# include <sys/stat.h> + +/* + * Make sure that the processing of symbol names is treated the same as when + * libcrypto is built. This is done automatically for public headers (see + * include/openssl/__DECC_INCLUDE_PROLOGUE.H and __DECC_INCLUDE_EPILOGUE.H), + * but not for internal headers. + */ +# ifdef __VMS +# pragma names save +# pragma names as_is,shortened +# endif + +# include "internal/o_dir.h" + +# ifdef __VMS +# pragma names restore +# endif + +# include <openssl/evp.h> +# include <openssl/pem.h> +# include <openssl/x509.h> + + +# ifndef PATH_MAX +# define PATH_MAX 4096 +# endif +# ifndef NAME_MAX +# define NAME_MAX 255 +# endif +# define MAX_COLLISIONS 256 + +typedef struct hentry_st { + struct hentry_st *next; + char *filename; + unsigned short old_id; + unsigned char need_symlink; + unsigned char digest[EVP_MAX_MD_SIZE]; +} HENTRY; + +typedef struct bucket_st { + struct bucket_st *next; + HENTRY *first_entry, *last_entry; + unsigned int hash; + unsigned short type; + unsigned short num_needed; +} BUCKET; + +enum Type { + /* Keep in sync with |suffixes|, below. */ + TYPE_CERT=0, TYPE_CRL=1 +}; + +enum Hash { + HASH_OLD, HASH_NEW, HASH_BOTH +}; + + +static int evpmdsize; +static const EVP_MD *evpmd; +static int remove_links = 1; +static int verbose = 0; +static BUCKET *hash_table[257]; + +static const char *suffixes[] = { "", "r" }; +static const char *extensions[] = { "pem", "crt", "cer", "crl" }; + + +static void bit_set(unsigned char *set, unsigned int bit) +{ + set[bit >> 3] |= 1 << (bit & 0x7); +} + +static int bit_isset(unsigned char *set, unsigned int bit) +{ + return set[bit >> 3] & (1 << (bit & 0x7)); +} + + +/* + * Process an entry; return number of errors. + */ +static int add_entry(enum Type type, unsigned int hash, const char *filename, + const unsigned char *digest, int need_symlink, + unsigned short old_id) +{ + static BUCKET nilbucket; + static HENTRY nilhentry; + BUCKET *bp; + HENTRY *ep, *found = NULL; + unsigned int ndx = (type + hash) % OSSL_NELEM(hash_table); + + for (bp = hash_table[ndx]; bp; bp = bp->next) + if (bp->type == type && bp->hash == hash) + break; + if (bp == NULL) { + bp = app_malloc(sizeof(*bp), "hash bucket"); + *bp = nilbucket; + bp->next = hash_table[ndx]; + bp->type = type; + bp->hash = hash; + hash_table[ndx] = bp; + } + + for (ep = bp->first_entry; ep; ep = ep->next) { + if (digest && memcmp(digest, ep->digest, evpmdsize) == 0) { + BIO_printf(bio_err, + "%s: warning: skipping duplicate %s in %s\n", + opt_getprog(), + type == TYPE_CERT ? "certificate" : "CRL", filename); + return 0; + } + if (strcmp(filename, ep->filename) == 0) { + found = ep; + if (digest == NULL) + break; + } + } + ep = found; + if (ep == NULL) { + if (bp->num_needed >= MAX_COLLISIONS) { + BIO_printf(bio_err, + "%s: error: hash table overflow for %s\n", + opt_getprog(), filename); + return 1; + } + ep = app_malloc(sizeof(*ep), "collision bucket"); + *ep = nilhentry; + ep->old_id = ~0; + ep->filename = OPENSSL_strdup(filename); + if (bp->last_entry) + bp->last_entry->next = ep; + if (bp->first_entry == NULL) + bp->first_entry = ep; + bp->last_entry = ep; + } + + if (old_id < ep->old_id) + ep->old_id = old_id; + if (need_symlink && !ep->need_symlink) { + ep->need_symlink = 1; + bp->num_needed++; + memcpy(ep->digest, digest, evpmdsize); + } + return 0; +} + +/* + * Check if a symlink goes to the right spot; return 0 if okay. + * This can be -1 if bad filename, or an error count. + */ +static int handle_symlink(const char *filename, const char *fullpath) +{ + unsigned int hash = 0; + int i, type, id; + unsigned char ch; + char linktarget[PATH_MAX], *endptr; + ossl_ssize_t n; + + for (i = 0; i < 8; i++) { + ch = filename[i]; + if (!isxdigit(ch)) + return -1; + hash <<= 4; + hash += OPENSSL_hexchar2int(ch); + } + if (filename[i++] != '.') + return -1; + for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) { + const char *suffix = suffixes[type]; + if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0) + break; + } + i += strlen(suffixes[type]); + + id = strtoul(&filename[i], &endptr, 10); + if (*endptr != '\0') + return -1; + + n = readlink(fullpath, linktarget, sizeof(linktarget)); + if (n < 0 || n >= (int)sizeof(linktarget)) + return -1; + linktarget[n] = 0; + + return add_entry(type, hash, linktarget, NULL, 0, id); +} + +/* + * process a file, return number of errors. + */ +static int do_file(const char *filename, const char *fullpath, enum Hash h) +{ + STACK_OF (X509_INFO) *inf = NULL; + X509_INFO *x; + X509_NAME *name = NULL; + BIO *b; + const char *ext; + unsigned char digest[EVP_MAX_MD_SIZE]; + int type, errs = 0; + size_t i; + + /* Does it end with a recognized extension? */ + if ((ext = strrchr(filename, '.')) == NULL) + goto end; + for (i = 0; i < OSSL_NELEM(extensions); i++) { + if (strcasecmp(extensions[i], ext + 1) == 0) + break; + } + if (i >= OSSL_NELEM(extensions)) + goto end; + + /* Does it have X.509 data in it? */ + if ((b = BIO_new_file(fullpath, "r")) == NULL) { + BIO_printf(bio_err, "%s: error: skipping %s, cannot open file\n", + opt_getprog(), filename); + errs++; + goto end; + } + inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); + BIO_free(b); + if (inf == NULL) + goto end; + + if (sk_X509_INFO_num(inf) != 1) { + BIO_printf(bio_err, + "%s: warning: skipping %s," + "it does not contain exactly one certificate or CRL\n", + opt_getprog(), filename); + /* This is not an error. */ + goto end; + } + x = sk_X509_INFO_value(inf, 0); + if (x->x509 != NULL) { + type = TYPE_CERT; + name = X509_get_subject_name(x->x509); + X509_digest(x->x509, evpmd, digest, NULL); + } else if (x->crl != NULL) { + type = TYPE_CRL; + name = X509_CRL_get_issuer(x->crl); + X509_CRL_digest(x->crl, evpmd, digest, NULL); + } else { + ++errs; + goto end; + } + if (name != NULL) { + if ((h == HASH_NEW) || (h == HASH_BOTH)) + errs += add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0); + if ((h == HASH_OLD) || (h == HASH_BOTH)) + errs += add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0); + } + +end: + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return errs; +} + +static void str_free(char *s) +{ + OPENSSL_free(s); +} + +static int ends_with_dirsep(const char *path) +{ + if (*path != '\0') + path += strlen(path) - 1; +# if defined __VMS + if (*path == ']' || *path == '>' || *path == ':') + return 1; +# elif defined _WIN32 + if (*path == '\\') + return 1; +# endif + return *path == '/'; +} + +/* + * Process a directory; return number of errors found. + */ +static int do_dir(const char *dirname, enum Hash h) +{ + BUCKET *bp, *nextbp; + HENTRY *ep, *nextep; + OPENSSL_DIR_CTX *d = NULL; + struct stat st; + unsigned char idmask[MAX_COLLISIONS / 8]; + int n, numfiles, nextid, buflen, errs = 0; + size_t i; + const char *pathsep; + const char *filename; + char *buf, *copy = NULL; + STACK_OF(OPENSSL_STRING) *files = NULL; + + if (app_access(dirname, W_OK) < 0) { + BIO_printf(bio_err, "Skipping %s, can't write\n", dirname); + return 1; + } + buflen = strlen(dirname); + pathsep = (buflen && !ends_with_dirsep(dirname)) ? "/": ""; + buflen += NAME_MAX + 1 + 1; + buf = app_malloc(buflen, "filename buffer"); + + if (verbose) + BIO_printf(bio_out, "Doing %s\n", dirname); + + if ((files = sk_OPENSSL_STRING_new_null()) == NULL) { + BIO_printf(bio_err, "Skipping %s, out of memory\n", dirname); + errs = 1; + goto err; + } + while ((filename = OPENSSL_DIR_read(&d, dirname)) != NULL) { + if ((copy = OPENSSL_strdup(filename)) == NULL + || sk_OPENSSL_STRING_push(files, copy) == 0) { + OPENSSL_free(copy); + BIO_puts(bio_err, "out of memory\n"); + errs = 1; + goto err; + } + } + OPENSSL_DIR_end(&d); + sk_OPENSSL_STRING_sort(files); + + numfiles = sk_OPENSSL_STRING_num(files); + for (n = 0; n < numfiles; ++n) { + filename = sk_OPENSSL_STRING_value(files, n); + if (BIO_snprintf(buf, buflen, "%s%s%s", + dirname, pathsep, filename) >= buflen) + continue; + if (lstat(buf, &st) < 0) + continue; + if (S_ISLNK(st.st_mode) && handle_symlink(filename, buf) == 0) + continue; + errs += do_file(filename, buf, h); + } + + for (i = 0; i < OSSL_NELEM(hash_table); i++) { + for (bp = hash_table[i]; bp; bp = nextbp) { + nextbp = bp->next; + nextid = 0; + memset(idmask, 0, (bp->num_needed + 7) / 8); + for (ep = bp->first_entry; ep; ep = ep->next) + if (ep->old_id < bp->num_needed) + bit_set(idmask, ep->old_id); + + for (ep = bp->first_entry; ep; ep = nextep) { + nextep = ep->next; + if (ep->old_id < bp->num_needed) { + /* Link exists, and is used as-is */ + BIO_snprintf(buf, buflen, "%08x.%s%d", bp->hash, + suffixes[bp->type], ep->old_id); + if (verbose) + BIO_printf(bio_out, "link %s -> %s\n", + ep->filename, buf); + } else if (ep->need_symlink) { + /* New link needed (it may replace something) */ + while (bit_isset(idmask, nextid)) + nextid++; + + BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d", + dirname, pathsep, &n, bp->hash, + suffixes[bp->type], nextid); + if (verbose) + BIO_printf(bio_out, "link %s -> %s\n", + ep->filename, &buf[n]); + if (unlink(buf) < 0 && errno != ENOENT) { + BIO_printf(bio_err, + "%s: Can't unlink %s, %s\n", + opt_getprog(), buf, strerror(errno)); + errs++; + } + if (symlink(ep->filename, buf) < 0) { + BIO_printf(bio_err, + "%s: Can't symlink %s, %s\n", + opt_getprog(), ep->filename, + strerror(errno)); + errs++; + } + bit_set(idmask, nextid); + } else if (remove_links) { + /* Link to be deleted */ + BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d", + dirname, pathsep, &n, bp->hash, + suffixes[bp->type], ep->old_id); + if (verbose) + BIO_printf(bio_out, "unlink %s\n", + &buf[n]); + if (unlink(buf) < 0 && errno != ENOENT) { + BIO_printf(bio_err, + "%s: Can't unlink %s, %s\n", + opt_getprog(), buf, strerror(errno)); + errs++; + } + } + OPENSSL_free(ep->filename); + OPENSSL_free(ep); + } + OPENSSL_free(bp); + } + hash_table[i] = NULL; + } + + err: + sk_OPENSSL_STRING_pop_free(files, str_free); + OPENSSL_free(buf); + return errs; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE +} OPTION_CHOICE; + +const OPTIONS rehash_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert-directory...]\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"h", OPT_HELP, '-', "Display this summary"}, + {"compat", OPT_COMPAT, '-', "Create both new- and old-style hash links"}, + {"old", OPT_OLD, '-', "Use old-style hash to generate links"}, + {"n", OPT_N, '-', "Do not remove existing links"}, + {"v", OPT_VERBOSE, '-', "Verbose output"}, + {NULL} +}; + + +int rehash_main(int argc, char **argv) +{ + const char *env, *prog; + char *e, *m; + int errs = 0; + OPTION_CHOICE o; + enum Hash h = HASH_NEW; + + prog = opt_init(argc, argv, rehash_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rehash_options); + goto end; + case OPT_COMPAT: + h = HASH_BOTH; + break; + case OPT_OLD: + h = HASH_OLD; + break; + case OPT_N: + remove_links = 0; + break; + case OPT_VERBOSE: + verbose = 1; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + evpmd = EVP_sha1(); + evpmdsize = EVP_MD_size(evpmd); + + if (*argv != NULL) { + while (*argv != NULL) + errs += do_dir(*argv++, h); + } else if ((env = getenv(X509_get_default_cert_dir_env())) != NULL) { + char lsc[2] = { LIST_SEPARATOR_CHAR, '\0' }; + m = OPENSSL_strdup(env); + for (e = strtok(m, lsc); e != NULL; e = strtok(NULL, lsc)) + errs += do_dir(e, h); + OPENSSL_free(m); + } else { + errs += do_dir(X509_get_default_cert_dir(), h); + } + + end: + return errs; +} + +#else +const OPTIONS rehash_options[] = { + {NULL} +}; + +int rehash_main(int argc, char **argv) +{ + BIO_printf(bio_err, "Not available; use c_rehash script\n"); + return 1; +} + +#endif /* defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) */ diff --git a/apps/req.c b/apps/req.c index 7fcab18cd1c9..6fd28a2aba24 100644 --- a/apps/req.c +++ b/apps/req.c @@ -1,77 +1,19 @@ -/* apps/req.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - /* - * Until the key-gen callbacks are modified to use newer prototypes, we allow - * deprecated functions for openssl-internal code + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#ifdef OPENSSL_NO_DEPRECATED -# undef OPENSSL_NO_DEPRECATED -#endif #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> -#ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -#endif +#include <ctype.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/evp.h> #include <openssl/conf.h> @@ -82,6 +24,7 @@ #include <openssl/objects.h> #include <openssl/pem.h> #include <openssl/bn.h> +#include <openssl/lhash.h> #ifndef OPENSSL_NO_RSA # include <openssl/rsa.h> #endif @@ -104,37 +47,13 @@ #define DEFAULT_KEY_LENGTH 2048 #define MIN_KEY_LENGTH 512 -#undef PROG -#define PROG req_main - -/*- - * -inform arg - input format - default PEM (DER or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -verify - check request signature - * -noout - don't print stuff out. - * -text - print out human readable text. - * -nodes - no des encryption - * -config file - Load configuration file. - * -key file - make a request using key in file (or use it for verification). - * -keyform arg - key file format. - * -rand file(s) - load the file(s) into the PRNG. - * -newkey - make a key and a request. - * -modulus - print RSA modulus. - * -pubkey - output Public Key. - * -x509 - output a self signed X509 structure instead. - * -asn1-kludge - output new certificate request in a format that some CA's - * require. This format is wrong - */ - static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn, int attribs, unsigned long chtype); -static int build_subject(X509_REQ *req, char *subj, unsigned long chtype, +static int build_subject(X509_REQ *req, const char *subj, unsigned long chtype, int multirdn); static int prompt_info(X509_REQ *req, - STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect, - STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, + STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, + STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, int attribs, unsigned long chtype); static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk, STACK_OF(CONF_VALUE) *attr, int attribs, @@ -146,355 +65,387 @@ static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value, int nid, int n_min, int n_max, unsigned long chtype, int mval); static int genpkey_cb(EVP_PKEY_CTX *ctx); +static int build_data(char *text, const char *def, + char *value, int n_min, int n_max, + char *buf, const int buf_size, + const char *desc1, const char *desc2 + ); static int req_check_len(int len, int n_min, int n_max); static int check_end(const char *str, const char *end); -static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr, +static int join(char buf[], size_t buf_size, const char *name, + const char *tail, const char *desc); +static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, int *pkey_type, long *pkeylen, char **palgnam, ENGINE *keygen_engine); -#ifndef MONOLITH -static char *default_config_file = NULL; -#endif static CONF *req_conf = NULL; +static CONF *addext_conf = NULL; static int batch = 0; -int MAIN(int, char **); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY, + OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT, + OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, + OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, + OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, + OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, + OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, + OPT_REQEXTS, OPT_PRECERT, OPT_MD, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS req_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"key", OPT_KEY, 's', "Private key to use"}, + {"keyform", OPT_KEYFORM, 'f', "Key file format"}, + {"pubkey", OPT_PUBKEY, '-', "Output public key"}, + {"new", OPT_NEW, '-', "New request"}, + {"config", OPT_CONFIG, '<', "Request template file"}, + {"keyout", OPT_KEYOUT, '>', "File to send the key to"}, + {"passin", OPT_PASSIN, 's', "Private key password source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + OPT_R_OPTIONS, + {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"}, + {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"batch", OPT_BATCH, '-', + "Do not ask anything during request generation"}, + {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"}, + {"modulus", OPT_MODULUS, '-', "RSA modulus"}, + {"verify", OPT_VERIFY, '-', "Verify signature on REQ"}, + {"nodes", OPT_NODES, '-', "Don't encrypt the output key"}, + {"noout", OPT_NOOUT, '-', "Do not output REQ"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"reqopt", OPT_REQOPT, 's', "Various request text options"}, + {"text", OPT_TEXT, '-', "Text form of request"}, + {"x509", OPT_X509, '-', + "Output a x509 structure instead of a cert request"}, + {OPT_MORE_STR, 1, 1, "(Required by some CA's)"}, + {"subj", OPT_SUBJ, 's', "Set or modify request subject"}, + {"subject", OPT_SUBJECT, '-', "Output the request's subject"}, + {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', + "Enable support for multivalued RDNs"}, + {"days", OPT_DAYS, 'p', "Number of days cert is valid for"}, + {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, + {"addext", OPT_ADDEXT, 's', + "Additional cert extension key=value pair (may be given more than once)"}, + {"extensions", OPT_EXTENSIONS, 's', + "Cert extension section (override value in config file)"}, + {"reqexts", OPT_REQEXTS, 's', + "Request extension section (override value in config file)"}, + {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"keygen_engine", OPT_KEYGEN_ENGINE, 's', + "Specify engine to be used for key generation operations"}, +#endif + {NULL} +}; + + +/* + * An LHASH of strings, where each string is an extension name. + */ +static unsigned long ext_name_hash(const OPENSSL_STRING *a) +{ + return OPENSSL_LH_strhash((const char *)a); +} + +static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) +{ + return strcmp((const char *)a, (const char *)b); +} + +static void exts_cleanup(OPENSSL_STRING *x) +{ + OPENSSL_free((char *)x); +} -int MAIN(int argc, char **argv) +/* + * Is the |kv| key already duplicated? This is remarkably tricky to get + * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax + * error. + */ +static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) { + char *p; + size_t off; + + /* Check syntax. */ + /* Skip leading whitespace, make a copy. */ + while (*kv && isspace(*kv)) + if (*++kv == '\0') + return 1; + if ((p = strchr(kv, '=')) == NULL) + return 1; + off = p - kv; + if ((kv = OPENSSL_strdup(kv)) == NULL) + return -1; + + /* Skip trailing space before the equal sign. */ + for (p = kv + off; p > kv; --p) + if (!isspace(p[-1])) + break; + if (p == kv) { + OPENSSL_free(kv); + return 1; + } + *p = '\0'; + + /* Finally have a clean "key"; see if it's there [by attempt to add it]. */ + if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv)) + != NULL || lh_OPENSSL_STRING_error(addexts)) { + OPENSSL_free(p != NULL ? p : kv); + return -1; + } + + return 0; +} + +int req_main(int argc, char **argv) +{ + ASN1_INTEGER *serial = NULL; + BIO *in = NULL, *out = NULL; ENGINE *e = NULL, *gen_eng = NULL; - unsigned long nmflag = 0, reqflag = 0; - int ex = 1, x509 = 0, days = 30; - X509 *x509ss = NULL; - X509_REQ *req = NULL; + EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *genctx = NULL; - const char *keyalg = NULL; - char *keyalgstr = NULL; STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; - EVP_PKEY *pkey = NULL; - int i = 0, badops = 0, newreq = 0, verbose = 0, pkey_type = -1; - long newkey = -1; - BIO *in = NULL, *out = NULL; - int informat, outformat, verify = 0, noout = 0, text = 0, keyform = - FORMAT_PEM; - int nodes = 0, kludge = 0, newhdr = 0, subject = 0, pubkey = 0; - char *infile, *outfile, *prog, *keyfile = NULL, *template = - NULL, *keyout = NULL; - char *engine = NULL; - char *extensions = NULL; - char *req_exts = NULL; + LHASH_OF(OPENSSL_STRING) *addexts = NULL; + X509 *x509ss = NULL; + X509_REQ *req = NULL; const EVP_CIPHER *cipher = NULL; - ASN1_INTEGER *serial = NULL; - int modulus = 0; - char *inrand = NULL; - char *passargin = NULL, *passargout = NULL; - char *passin = NULL, *passout = NULL; - char *p; - char *subj = NULL; - int multirdn = 0; const EVP_MD *md_alg = NULL, *digest = NULL; - unsigned long chtype = MBSTRING_ASC; -#ifndef MONOLITH - char *to_free; - long errline; -#endif + BIO *addext_bio = NULL; + char *extensions = NULL, *infile = NULL; + char *outfile = NULL, *keyfile = NULL; + char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL; + char *passin = NULL, *passout = NULL; + char *nofree_passin = NULL, *nofree_passout = NULL; + char *req_exts = NULL, *subj = NULL; + char *template = default_config_file, *keyout = NULL; + const char *keyalg = NULL; + OPTION_CHOICE o; + int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0; + int pkey_type = -1, private = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM; + int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0; + int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; + long newkey = -1; + unsigned long chtype = MBSTRING_ASC, reqflag = 0; - req_conf = NULL; #ifndef OPENSSL_NO_DES cipher = EVP_des_ede3_cbc(); #endif - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } + prog = opt_init(argc, argv, req_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(req_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_KEYGEN_ENGINE: #ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } else if (strcmp(*argv, "-keygen_engine") == 0) { - if (--argc < 1) - goto bad; - gen_eng = ENGINE_by_id(*(++argv)); + gen_eng = ENGINE_by_id(opt_arg()); if (gen_eng == NULL) { BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv); - goto end; + goto opthelp; } - } #endif - else if (strcmp(*argv, "-key") == 0) { - if (--argc < 1) - goto bad; - keyfile = *(++argv); - } else if (strcmp(*argv, "-pubkey") == 0) { + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_PUBKEY: pubkey = 1; - } else if (strcmp(*argv, "-new") == 0) { + break; + case OPT_NEW: newreq = 1; - } else if (strcmp(*argv, "-config") == 0) { - if (--argc < 1) - goto bad; - template = *(++argv); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - goto bad; - keyform = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-keyout") == 0) { - if (--argc < 1) - goto bad; - keyout = *(++argv); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-passout") == 0) { - if (--argc < 1) - goto bad; - passargout = *(++argv); - } else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - } else if (strcmp(*argv, "-newkey") == 0) { - if (--argc < 1) - goto bad; - keyalg = *(++argv); + break; + case OPT_CONFIG: + template = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_KEYOUT: + keyout = opt_arg(); + break; + case OPT_PASSIN: + passargin = opt_arg(); + break; + case OPT_PASSOUT: + passargout = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_NEWKEY: + keyalg = opt_arg(); newreq = 1; - } else if (strcmp(*argv, "-pkeyopt") == 0) { - if (--argc < 1) - goto bad; + break; + case OPT_PKEYOPT: if (!pkeyopts) pkeyopts = sk_OPENSSL_STRING_new_null(); - if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-sigopt") == 0) { - if (--argc < 1) - goto bad; + if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg())) + goto opthelp; + break; + case OPT_SIGOPT: if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); - if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-batch") == 0) + if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto opthelp; + break; + case OPT_BATCH: batch = 1; - else if (strcmp(*argv, "-newhdr") == 0) + break; + case OPT_NEWHDR: newhdr = 1; - else if (strcmp(*argv, "-modulus") == 0) + break; + case OPT_MODULUS: modulus = 1; - else if (strcmp(*argv, "-verify") == 0) + break; + case OPT_VERIFY: verify = 1; - else if (strcmp(*argv, "-nodes") == 0) + break; + case OPT_NODES: nodes = 1; - else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-verbose") == 0) + break; + case OPT_VERBOSE: verbose = 1; - else if (strcmp(*argv, "-utf8") == 0) + break; + case OPT_UTF8: chtype = MBSTRING_UTF8; - else if (strcmp(*argv, "-nameopt") == 0) { - if (--argc < 1) - goto bad; - if (!set_name_ex(&nmflag, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-reqopt") == 0) { - if (--argc < 1) - goto bad; - if (!set_cert_ex(&reqflag, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-subject") == 0) - subject = 1; - else if (strcmp(*argv, "-text") == 0) + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto opthelp; + break; + case OPT_REQOPT: + if (!set_cert_ex(&reqflag, opt_arg())) + goto opthelp; + break; + case OPT_TEXT: text = 1; - else if (strcmp(*argv, "-x509") == 0) { + break; + case OPT_X509: x509 = 1; - } else if (strcmp(*argv, "-asn1-kludge") == 0) - kludge = 1; - else if (strcmp(*argv, "-no-asn1-kludge") == 0) - kludge = 0; - else if (strcmp(*argv, "-subj") == 0) { - if (--argc < 1) - goto bad; - subj = *(++argv); - } else if (strcmp(*argv, "-multivalue-rdn") == 0) + break; + case OPT_DAYS: + days = atoi(opt_arg()); + break; + case OPT_SET_SERIAL: + if (serial != NULL) { + BIO_printf(bio_err, "Serial number supplied twice\n"); + goto opthelp; + } + serial = s2i_ASN1_INTEGER(NULL, opt_arg()); + if (serial == NULL) + goto opthelp; + break; + case OPT_SUBJECT: + subject = 1; + break; + case OPT_SUBJ: + subj = opt_arg(); + break; + case OPT_MULTIVALUE_RDN: multirdn = 1; - else if (strcmp(*argv, "-days") == 0) { - if (--argc < 1) - goto bad; - days = atoi(*(++argv)); - if (days == 0) - days = 30; - } else if (strcmp(*argv, "-set_serial") == 0) { - if (--argc < 1) - goto bad; - serial = s2i_ASN1_INTEGER(NULL, *(++argv)); - if (!serial) - goto bad; - } else if (strcmp(*argv, "-extensions") == 0) { - if (--argc < 1) - goto bad; - extensions = *(++argv); - } else if (strcmp(*argv, "-reqexts") == 0) { - if (--argc < 1) - goto bad; - req_exts = *(++argv); - } else if ((md_alg = EVP_get_digestbyname(&((*argv)[1]))) != NULL) { - /* ok */ + break; + case OPT_ADDEXT: + p = opt_arg(); + if (addexts == NULL) { + addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp); + addext_bio = BIO_new(BIO_s_mem()); + if (addexts == NULL || addext_bio == NULL) + goto end; + } + i = duplicated(addexts, p); + if (i == 1) + goto opthelp; + if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0) + goto end; + break; + case OPT_EXTENSIONS: + extensions = opt_arg(); + break; + case OPT_REQEXTS: + req_exts = opt_arg(); + break; + case OPT_PRECERT: + newreq = precert = 1; + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &md_alg)) + goto opthelp; digest = md_alg; - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; break; } - argc--; - argv++; - } - - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -inform arg input format - DER or PEM\n"); - BIO_printf(bio_err, " -outform arg output format - DER or PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, " -text text form of request\n"); - BIO_printf(bio_err, " -pubkey output public key\n"); - BIO_printf(bio_err, " -noout do not output REQ\n"); - BIO_printf(bio_err, " -verify verify signature on REQ\n"); - BIO_printf(bio_err, " -modulus RSA modulus\n"); - BIO_printf(bio_err, " -nodes don't encrypt the output key\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device\n"); -#endif - BIO_printf(bio_err, " -subject output the request's subject\n"); - BIO_printf(bio_err, " -passin private key password source\n"); - BIO_printf(bio_err, - " -key file use the private key contained in file\n"); - BIO_printf(bio_err, " -keyform arg key file format\n"); - BIO_printf(bio_err, " -keyout arg file to send the key to\n"); - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - BIO_printf(bio_err, - " -newkey rsa:bits generate a new RSA key of 'bits' in size\n"); - BIO_printf(bio_err, - " -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n"); -#ifndef OPENSSL_NO_ECDSA - BIO_printf(bio_err, - " -newkey ec:file generate a new EC key, parameters taken from CA in 'file'\n"); -#endif - BIO_printf(bio_err, - " -[digest] Digest to sign with (md5, sha1, md2, mdc2, md4)\n"); - BIO_printf(bio_err, " -config file request template file.\n"); - BIO_printf(bio_err, - " -subj arg set or modify request subject\n"); - BIO_printf(bio_err, - " -multivalue-rdn enable support for multivalued RDNs\n"); - BIO_printf(bio_err, " -new new request.\n"); - BIO_printf(bio_err, - " -batch do not ask anything during request generation\n"); - BIO_printf(bio_err, - " -x509 output a x509 structure instead of a cert. req.\n"); - BIO_printf(bio_err, - " -days number of days a certificate generated by -x509 is valid for.\n"); - BIO_printf(bio_err, - " -set_serial serial number to use for a certificate generated by -x509.\n"); - BIO_printf(bio_err, - " -newhdr output \"NEW\" in the header lines\n"); - BIO_printf(bio_err, - " -asn1-kludge Output the 'request' in a format that is wrong but some CA's\n"); - BIO_printf(bio_err, - " have been reported as requiring\n"); - BIO_printf(bio_err, - " -extensions .. specify certificate extension section (override value in config file)\n"); - BIO_printf(bio_err, - " -reqexts .. specify request extension section (override value in config file)\n"); - BIO_printf(bio_err, - " -utf8 input characters are UTF8 (default ASCII)\n"); - BIO_printf(bio_err, - " -nameopt arg - various certificate name options\n"); - BIO_printf(bio_err, - " -reqopt arg - various request text options\n\n"); - goto end; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + if (days && !x509) + BIO_printf(bio_err, "Ignoring -days; not generating a certificate\n"); if (x509 && infile == NULL) newreq = 1; - ERR_load_crypto_strings(); - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + /* TODO: simplify this as pkey is still always NULL here */ + private = newreq && (pkey == NULL) ? 1 : 0; + + if (!app_passwd(passargin, passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } -#ifndef MONOLITH /* else this has happened in openssl.c - * (global `config') */ - /* Lets load up our environment a little */ - p = getenv("OPENSSL_CONF"); - if (p == NULL) - p = getenv("SSLEAY_CONF"); - if (p == NULL) - p = to_free = make_config_name(); - default_config_file = p; - config = NCONF_new(NULL); - i = NCONF_load(config, p, &errline); -#endif - - if (template != NULL) { - long errline = -1; + if (verbose) + BIO_printf(bio_err, "Using configuration from %s\n", template); + req_conf = app_load_config(template); + if (addext_bio) { if (verbose) - BIO_printf(bio_err, "Using configuration from %s\n", template); - req_conf = NCONF_new(NULL); - i = NCONF_load(req_conf, template, &errline); - if (i == 0) { - BIO_printf(bio_err, "error on line %ld of %s\n", errline, - template); - goto end; - } - } else { - req_conf = config; - - if (req_conf == NULL) { - BIO_printf(bio_err, "Unable to load config info from %s\n", - default_config_file); - if (newreq) - goto end; - } else if (verbose) - BIO_printf(bio_err, "Using configuration from %s\n", - default_config_file); + BIO_printf(bio_err, + "Using additional configuration from command line\n"); + addext_conf = app_load_config_bio(addext_bio, NULL); } + if (template != default_config_file && !app_load_modules(req_conf)) + goto end; if (req_conf != NULL) { - if (!load_config(bio_err, req_conf)) - goto end; p = NCONF_get_string(req_conf, NULL, "oid_file"); if (p == NULL) ERR_clear_error(); @@ -513,25 +464,26 @@ int MAIN(int argc, char **argv) } } } - if (!add_oid_section(bio_err, req_conf)) + if (!add_oid_section(req_conf)) goto end; if (md_alg == NULL) { p = NCONF_get_string(req_conf, SECTION, "default_md"); - if (p == NULL) + if (p == NULL) { ERR_clear_error(); - if (p != NULL) { - if ((md_alg = EVP_get_digestbyname(p)) != NULL) - digest = md_alg; + } else { + if (!opt_md(p, &md_alg)) + goto opthelp; + digest = md_alg; } } - if (!extensions) { + if (extensions == NULL) { extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); - if (!extensions) + if (extensions == NULL) ERR_clear_error(); } - if (extensions) { + if (extensions != NULL) { /* Check syntax of file */ X509V3_CTX ctx; X509V3_set_ctx_test(&ctx); @@ -542,42 +494,54 @@ int MAIN(int argc, char **argv) goto end; } } + if (addext_conf != NULL) { + /* Check syntax of command line extensions */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, addext_conf); + if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) { + BIO_printf(bio_err, "Error Loading command line extensions\n"); + goto end; + } + } - if (!passin) { - passin = NCONF_get_string(req_conf, SECTION, "input_password"); - if (!passin) + if (passin == NULL) { + passin = nofree_passin = + NCONF_get_string(req_conf, SECTION, "input_password"); + if (passin == NULL) ERR_clear_error(); } - if (!passout) { - passout = NCONF_get_string(req_conf, SECTION, "output_password"); - if (!passout) + if (passout == NULL) { + passout = nofree_passout = + NCONF_get_string(req_conf, SECTION, "output_password"); + if (passout == NULL) ERR_clear_error(); } p = NCONF_get_string(req_conf, SECTION, STRING_MASK); - if (!p) + if (p == NULL) ERR_clear_error(); - if (p && !ASN1_STRING_set_default_mask_asc(p)) { + if (p != NULL && !ASN1_STRING_set_default_mask_asc(p)) { BIO_printf(bio_err, "Invalid global string mask setting %s\n", p); goto end; } if (chtype != MBSTRING_UTF8) { p = NCONF_get_string(req_conf, SECTION, UTF8_IN); - if (!p) + if (p == NULL) ERR_clear_error(); - else if (!strcmp(p, "yes")) + else if (strcmp(p, "yes") == 0) chtype = MBSTRING_UTF8; } - if (!req_exts) { + if (req_exts == NULL) { req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); - if (!req_exts) + if (req_exts == NULL) ERR_clear_error(); } - if (req_exts) { + if (req_exts != NULL) { /* Check syntax of file */ X509V3_CTX ctx; X509V3_set_ctx_test(&ctx); @@ -590,45 +554,27 @@ int MAIN(int argc, char **argv) } } - in = BIO_new(BIO_s_file()); - out = BIO_new(BIO_s_file()); - if ((in == NULL) || (out == NULL)) - goto end; - - e = setup_engine(bio_err, engine, 0); - if (keyfile != NULL) { - pkey = load_key(bio_err, keyfile, keyform, 0, passin, e, - "Private Key"); - if (!pkey) { - /* - * load_key() has already printed an appropriate message - */ + pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); + if (pkey == NULL) { + /* load_key() has already printed an appropriate message */ goto end; } else { - char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE"); - if (randfile == NULL) - ERR_clear_error(); - app_RAND_load_file(randfile, bio_err, 0); + app_RAND_load_conf(req_conf, SECTION); } } if (newreq && (pkey == NULL)) { - char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE"); - if (randfile == NULL) - ERR_clear_error(); - app_RAND_load_file(randfile, bio_err, 0); - if (inrand) - app_RAND_load_files(inrand); + app_RAND_load_conf(req_conf, SECTION); if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) { newkey = DEFAULT_KEY_LENGTH; } - if (keyalg) { - genctx = set_keygen_ctx(bio_err, keyalg, &pkey_type, &newkey, + if (keyalg != NULL) { + genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey, &keyalgstr, gen_eng); - if (!genctx) + if (genctx == NULL) goto end; } @@ -640,14 +586,28 @@ int MAIN(int argc, char **argv) goto end; } - if (!genctx) { - genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &newkey, + if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for RSA keys.\n" + " Your key size is %ld! Larger key size may behave not as expected.\n", + OPENSSL_RSA_MAX_MODULUS_BITS, newkey); + +#ifndef OPENSSL_NO_DSA + if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for DSA keys.\n" + " Your key size is %ld! Larger key size may behave not as expected.\n", + OPENSSL_DSA_MAX_MODULUS_BITS, newkey); +#endif + + if (genctx == NULL) { + genctx = set_keygen_ctx(NULL, &pkey_type, &newkey, &keyalgstr, gen_eng); if (!genctx) goto end; } - if (pkeyopts) { + if (pkeyopts != NULL) { char *genopt; for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) { genopt = sk_OPENSSL_STRING_value(pkeyopts, i); @@ -659,8 +619,11 @@ int MAIN(int argc, char **argv) } } - BIO_printf(bio_err, "Generating a %ld bit %s private key\n", - newkey, keyalgstr); + if (pkey_type == EVP_PKEY_EC) { + BIO_printf(bio_err, "Generating an EC private key\n"); + } else { + BIO_printf(bio_err, "Generating a %s private key\n", keyalgstr); + } EVP_PKEY_CTX_set_cb(genctx, genpkey_cb); EVP_PKEY_CTX_set_app_data(genctx, bio_err); @@ -673,30 +636,19 @@ int MAIN(int argc, char **argv) EVP_PKEY_CTX_free(genctx); genctx = NULL; - app_RAND_write_file(randfile, bio_err); - if (keyout == NULL) { keyout = NCONF_get_string(req_conf, SECTION, KEYFILE); if (keyout == NULL) ERR_clear_error(); } - if (keyout == NULL) { + if (keyout == NULL) BIO_printf(bio_err, "writing new private key to stdout\n"); - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } else { + else BIO_printf(bio_err, "writing new private key to '%s'\n", keyout); - if (BIO_write_filename(out, keyout) <= 0) { - perror(keyout); - goto end; - } - } + out = bio_open_owner(keyout, outformat, private); + if (out == NULL) + goto end; p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key"); if (p == NULL) { @@ -712,6 +664,7 @@ int MAIN(int argc, char **argv) i = 0; loop: + assert(private); if (!PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, passout)) { if ((ERR_GET_REASON(ERR_peek_error()) == @@ -722,33 +675,20 @@ int MAIN(int argc, char **argv) } goto end; } + BIO_free(out); + out = NULL; BIO_printf(bio_err, "-----\n"); } if (!newreq) { - /* - * Since we are using a pre-existing certificate request, the kludge - * 'format' info should not be changed. - */ - kludge = -1; - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; if (informat == FORMAT_ASN1) req = d2i_X509_REQ_bio(in, NULL); - else if (informat == FORMAT_PEM) + else req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); - else { - BIO_printf(bio_err, - "bad input format specified for X509 request\n"); - goto end; - } if (req == NULL) { BIO_printf(bio_err, "unable to load X509 request\n"); goto end; @@ -769,11 +709,6 @@ int MAIN(int argc, char **argv) i = make_REQ(req, pkey, subj, multirdn, !x509, chtype); subj = NULL; /* done processing '-subj' option */ - if ((kludge > 0) - && !sk_X509_ATTRIBUTE_num(req->req_info->attributes)) { - sk_X509_ATTRIBUTE_free(req->req_info->attributes); - req->req_info->attributes = NULL; - } if (!i) { BIO_printf(bio_err, "problems making Certificate Request\n"); goto end; @@ -786,9 +721,10 @@ int MAIN(int argc, char **argv) goto end; /* Set version to V3 */ - if (extensions && !X509_set_version(x509ss, 2)) + if ((extensions != NULL || addext_conf != NULL) + && !X509_set_version(x509ss, 2)) goto end; - if (serial) { + if (serial != NULL) { if (!X509_set_serialNumber(x509ss, serial)) goto end; } else { @@ -798,17 +734,18 @@ int MAIN(int argc, char **argv) if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) goto end; - if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0)) - goto end; - if (!X509_time_adj_ex(X509_get_notAfter(x509ss), days, 0, NULL)) + if (days == 0) { + /* set default days if it's not specified */ + days = 30; + } + if (!set_cert_times(x509ss, NULL, NULL, days)) goto end; if (!X509_set_subject_name (x509ss, X509_REQ_get_subject_name(req))) goto end; - tmppkey = X509_REQ_get_pubkey(req); + tmppkey = X509_REQ_get0_pubkey(req); if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey)) goto end; - EVP_PKEY_free(tmppkey); /* Set up V3 context struct */ @@ -816,15 +753,30 @@ int MAIN(int argc, char **argv) X509V3_set_nconf(&ext_ctx, req_conf); /* Add extensions */ - if (extensions && !X509V3_EXT_add_nconf(req_conf, - &ext_ctx, extensions, - x509ss)) { + if (extensions != NULL && !X509V3_EXT_add_nconf(req_conf, + &ext_ctx, extensions, + x509ss)) { BIO_printf(bio_err, "Error Loading extension section %s\n", extensions); goto end; } + if (addext_conf != NULL + && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default", + x509ss)) { + BIO_printf(bio_err, "Error Loading command line extensions\n"); + goto end; + } - i = do_X509_sign(bio_err, x509ss, pkey, digest, sigopts); + /* If a pre-cert was requested, we need to add a poison extension */ + if (precert) { + if (X509_add1_ext_i2d(x509ss, NID_ct_precert_poison, NULL, 1, 0) + != 1) { + BIO_printf(bio_err, "Error adding poison extension\n"); + goto end; + } + } + + i = do_X509_sign(x509ss, pkey, digest, sigopts); if (!i) { ERR_print_errors(bio_err); goto end; @@ -838,14 +790,20 @@ int MAIN(int argc, char **argv) X509V3_set_nconf(&ext_ctx, req_conf); /* Add extensions */ - if (req_exts && !X509V3_EXT_REQ_add_nconf(req_conf, - &ext_ctx, req_exts, - req)) { + if (req_exts != NULL + && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, + req_exts, req)) { BIO_printf(bio_err, "Error Loading extension section %s\n", req_exts); goto end; } - i = do_X509_REQ_sign(bio_err, req, pkey, digest, sigopts); + if (addext_conf != NULL + && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default", + req)) { + BIO_printf(bio_err, "Error Loading command line extensions\n"); + goto end; + } + i = do_X509_REQ_sign(req, pkey, digest, sigopts); if (!i) { ERR_print_errors(bio_err); goto end; @@ -854,7 +812,7 @@ int MAIN(int argc, char **argv) } if (subj && x509) { - BIO_printf(bio_err, "Cannot modifiy certificate subject\n"); + BIO_printf(bio_err, "Cannot modify certificate subject\n"); goto end; } @@ -862,134 +820,111 @@ int MAIN(int argc, char **argv) if (verbose) { BIO_printf(bio_err, "Modifying Request's Subject\n"); print_name(bio_err, "old subject=", - X509_REQ_get_subject_name(req), nmflag); + X509_REQ_get_subject_name(req), get_nameopt()); } if (build_subject(req, subj, chtype, multirdn) == 0) { BIO_printf(bio_err, "ERROR: cannot modify subject\n"); - ex = 1; + ret = 1; goto end; } - req->req_info->enc.modified = 1; - if (verbose) { print_name(bio_err, "new subject=", - X509_REQ_get_subject_name(req), nmflag); + X509_REQ_get_subject_name(req), get_nameopt()); } } if (verify && !x509) { - int tmp = 0; + EVP_PKEY *tpubkey = pkey; - if (pkey == NULL) { - pkey = X509_REQ_get_pubkey(req); - tmp = 1; - if (pkey == NULL) + if (tpubkey == NULL) { + tpubkey = X509_REQ_get0_pubkey(req); + if (tpubkey == NULL) goto end; } - i = X509_REQ_verify(req, pkey); - if (tmp) { - EVP_PKEY_free(pkey); - pkey = NULL; - } + i = X509_REQ_verify(req, tpubkey); if (i < 0) { goto end; } else if (i == 0) { BIO_printf(bio_err, "verify failure\n"); ERR_print_errors(bio_err); - } else /* if (i > 0) */ + } else { /* if (i > 0) */ BIO_printf(bio_err, "verify OK\n"); + } } if (noout && !text && !modulus && !subject && !pubkey) { - ex = 0; + ret = 0; goto end; } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } else { - if ((keyout != NULL) && (strcmp(outfile, keyout) == 0)) - i = (int)BIO_append_filename(out, outfile); - else - i = (int)BIO_write_filename(out, outfile); - if (!i) { - perror(outfile); - goto end; - } - } + out = bio_open_default(outfile, + keyout != NULL && outfile != NULL && + strcmp(keyout, outfile) == 0 ? 'a' : 'w', + outformat); + if (out == NULL) + goto end; if (pubkey) { - EVP_PKEY *tpubkey; - tpubkey = X509_REQ_get_pubkey(req); + EVP_PKEY *tpubkey = X509_REQ_get0_pubkey(req); + if (tpubkey == NULL) { BIO_printf(bio_err, "Error getting public key\n"); ERR_print_errors(bio_err); goto end; } PEM_write_bio_PUBKEY(out, tpubkey); - EVP_PKEY_free(tpubkey); } if (text) { if (x509) - X509_print_ex(out, x509ss, nmflag, reqflag); + X509_print_ex(out, x509ss, get_nameopt(), reqflag); else - X509_REQ_print_ex(out, req, nmflag, reqflag); + X509_REQ_print_ex(out, req, get_nameopt(), reqflag); } if (subject) { if (x509) print_name(out, "subject=", X509_get_subject_name(x509ss), - nmflag); + get_nameopt()); else print_name(out, "subject=", X509_REQ_get_subject_name(req), - nmflag); + get_nameopt()); } if (modulus) { EVP_PKEY *tpubkey; if (x509) - tpubkey = X509_get_pubkey(x509ss); + tpubkey = X509_get0_pubkey(x509ss); else - tpubkey = X509_REQ_get_pubkey(req); + tpubkey = X509_REQ_get0_pubkey(req); if (tpubkey == NULL) { fprintf(stdout, "Modulus=unavailable\n"); goto end; } fprintf(stdout, "Modulus="); #ifndef OPENSSL_NO_RSA - if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) - BN_print(out, tpubkey->pkey.rsa->n); - else + if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) { + const BIGNUM *n; + RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL); + BN_print(out, n); + } else #endif fprintf(stdout, "Wrong Algorithm type"); - EVP_PKEY_free(tpubkey); fprintf(stdout, "\n"); } if (!noout && !x509) { if (outformat == FORMAT_ASN1) i = i2d_X509_REQ_bio(out, req); - else if (outformat == FORMAT_PEM) { - if (newhdr) - i = PEM_write_bio_X509_REQ_NEW(out, req); - else - i = PEM_write_bio_X509_REQ(out, req); - } else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; - } + else if (newhdr) + i = PEM_write_bio_X509_REQ_NEW(out, req); + else + i = PEM_write_bio_X509_REQ(out, req); if (!i) { BIO_printf(bio_err, "unable to write X509 request\n"); goto end; @@ -998,54 +933,42 @@ int MAIN(int argc, char **argv) if (!noout && x509 && (x509ss != NULL)) { if (outformat == FORMAT_ASN1) i = i2d_X509_bio(out, x509ss); - else if (outformat == FORMAT_PEM) + else i = PEM_write_bio_X509(out, x509ss); - else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; - } if (!i) { BIO_printf(bio_err, "unable to write X509 certificate\n"); goto end; } } - ex = 0; + ret = 0; end: -#ifndef MONOLITH - if (to_free) - OPENSSL_free(to_free); -#endif - if (ex) { + if (ret) { ERR_print_errors(bio_err); } - if ((req_conf != NULL) && (req_conf != config)) - NCONF_free(req_conf); + NCONF_free(req_conf); + NCONF_free(addext_conf); + BIO_free(addext_bio); BIO_free(in); BIO_free_all(out); EVP_PKEY_free(pkey); - if (genctx) - EVP_PKEY_CTX_free(genctx); - if (pkeyopts) - sk_OPENSSL_STRING_free(pkeyopts); - if (sigopts) - sk_OPENSSL_STRING_free(sigopts); + EVP_PKEY_CTX_free(genctx); + sk_OPENSSL_STRING_free(pkeyopts); + sk_OPENSSL_STRING_free(sigopts); + lh_OPENSSL_STRING_doall(addexts, exts_cleanup); + lh_OPENSSL_STRING_free(addexts); #ifndef OPENSSL_NO_ENGINE - if (gen_eng) - ENGINE_free(gen_eng); + ENGINE_free(gen_eng); #endif - if (keyalgstr) - OPENSSL_free(keyalgstr); + OPENSSL_free(keyalgstr); X509_REQ_free(req); X509_free(x509ss); ASN1_INTEGER_free(serial); release_engine(e); - if (passargin && passin) + if (passin != nofree_passin) OPENSSL_free(passin); - if (passargout && passout) + if (passout != nofree_passout) OPENSSL_free(passout); - OBJ_cleanup(); - apps_shutdown(); - OPENSSL_EXIT(ex); + return ret; } static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, @@ -1059,7 +982,7 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, tmp = NCONF_get_string(req_conf, SECTION, PROMPT); if (tmp == NULL) ERR_clear_error(); - if ((tmp != NULL) && !strcmp(tmp, "no")) + if ((tmp != NULL) && strcmp(tmp, "no") == 0) no_prompt = 1; dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME); @@ -1090,15 +1013,13 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, if (!X509_REQ_set_version(req, 0L)) goto err; /* version 1 */ - if (no_prompt) + if (subj) + i = build_subject(req, subj, chtype, multirdn); + else if (no_prompt) i = auto_info(req, dn_sk, attr_sk, attribs, chtype); - else { - if (subj) - i = build_subject(req, subj, chtype, multirdn); - else - i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, - chtype); - } + else + i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, + chtype); if (!i) goto err; @@ -1107,19 +1028,19 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, ret = 1; err: - return (ret); + return ret; } /* * subject is expected to be in the format /type0=value0/type1=value1/type2=... * where characters may be escaped by \ */ -static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, +static int build_subject(X509_REQ *req, const char *subject, unsigned long chtype, int multirdn) { X509_NAME *n; - if (!(n = parse_name(subject, chtype, multirdn))) + if ((n = parse_name(subject, chtype, multirdn)) == NULL) return 0; if (!X509_REQ_set_subject_name(req, n)) { @@ -1131,8 +1052,8 @@ static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, } static int prompt_info(X509_REQ *req, - STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect, - STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, + STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, + STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, int attribs, unsigned long chtype) { int i; @@ -1163,7 +1084,8 @@ static int prompt_info(X509_REQ *req, if (sk_CONF_VALUE_num(dn_sk)) { i = -1; - start:for (;;) { + start: + for ( ; ; ) { i++; if (sk_CONF_VALUE_num(dn_sk) <= i) break; @@ -1188,35 +1110,36 @@ static int prompt_info(X509_REQ *req, if (*type == '+') { mval = -1; type++; - } else + } else { mval = 0; + } /* If OBJ not recognised ignore it */ if ((nid = OBJ_txt2nid(type)) == NID_undef) goto start; - if (BIO_snprintf(buf, sizeof(buf), "%s_default", v->name) - >= (int)sizeof(buf)) { - BIO_printf(bio_err, "Name '%s' too long\n", v->name); + if (!join(buf, sizeof(buf), v->name, "_default", "Name")) return 0; - } - if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { ERR_clear_error(); def = ""; } - BIO_snprintf(buf, sizeof(buf), "%s_value", v->name); + if (!join(buf, sizeof(buf), v->name, "_value", "Name")) + return 0; if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { ERR_clear_error(); value = NULL; } - BIO_snprintf(buf, sizeof(buf), "%s_min", v->name); + if (!join(buf, sizeof(buf), v->name, "_min", "Name")) + return 0; if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) { ERR_clear_error(); n_min = -1; } - BIO_snprintf(buf, sizeof(buf), "%s_max", v->name); + + if (!join(buf, sizeof(buf), v->name, "_max", "Name")) + return 0; if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { ERR_clear_error(); n_max = -1; @@ -1242,7 +1165,8 @@ static int prompt_info(X509_REQ *req, } i = -1; - start2: for (;;) { + start2: + for ( ; ; ) { i++; if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i)) break; @@ -1252,32 +1176,31 @@ static int prompt_info(X509_REQ *req, if ((nid = OBJ_txt2nid(type)) == NID_undef) goto start2; - if (BIO_snprintf(buf, sizeof(buf), "%s_default", type) - >= (int)sizeof(buf)) { - BIO_printf(bio_err, "Name '%s' too long\n", v->name); + if (!join(buf, sizeof(buf), type, "_default", "Name")) return 0; - } - if ((def = NCONF_get_string(req_conf, attr_sect, buf)) == NULL) { ERR_clear_error(); def = ""; } - BIO_snprintf(buf, sizeof(buf), "%s_value", type); + if (!join(buf, sizeof(buf), type, "_value", "Name")) + return 0; if ((value = NCONF_get_string(req_conf, attr_sect, buf)) == NULL) { ERR_clear_error(); value = NULL; } - BIO_snprintf(buf, sizeof(buf), "%s_min", type); + if (!join(buf, sizeof(buf), type,"_min", "Name")) + return 0; if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { ERR_clear_error(); n_min = -1; } - BIO_snprintf(buf, sizeof(buf), "%s_max", type); + if (!join(buf, sizeof(buf), type, "_max", "Name")) + return 0; if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) { ERR_clear_error(); n_max = -1; @@ -1302,7 +1225,7 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, STACK_OF(CONF_VALUE) *attr_sk, int attribs, unsigned long chtype) { - int i; + int i, spec_char, plus_char; char *p, *q; char *type; CONF_VALUE *v; @@ -1318,27 +1241,31 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, /* * Skip past any leading X. X: X, etc to allow for multiple instances */ - for (p = v->name; *p; p++) + for (p = v->name; *p; p++) { #ifndef CHARSET_EBCDIC - if ((*p == ':') || (*p == ',') || (*p == '.')) { + spec_char = ((*p == ':') || (*p == ',') || (*p == '.')); #else - if ((*p == os_toascii[':']) || (*p == os_toascii[',']) - || (*p == os_toascii['.'])) { + spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[',']) + || (*p == os_toascii['.'])); #endif + if (spec_char) { p++; if (*p) type = p; break; } + } #ifndef CHARSET_EBCDIC - if (*type == '+') { + plus_char = (*type == '+'); #else - if (*type == os_toascii['+']) { + plus_char = (*type == os_toascii['+']); #endif + if (plus_char) { type++; mval = -1; - } else + } else { mval = 0; + } if (!X509_NAME_add_entry_by_txt(subj, type, chtype, (unsigned char *)v->value, -1, -1, mval)) @@ -1365,79 +1292,65 @@ static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value, int nid, int n_min, int n_max, unsigned long chtype, int mval) { - int i, ret = 0; - MS_STATIC char buf[1024]; - start: - if (!batch) - BIO_printf(bio_err, "%s [%s]:", text, def); - (void)BIO_flush(bio_err); - if (value != NULL) { - BUF_strlcpy(buf, value, sizeof(buf)); - BUF_strlcat(buf, "\n", sizeof(buf)); - BIO_printf(bio_err, "%s\n", value); - } else { - buf[0] = '\0'; - if (!batch) { - if (!fgets(buf, sizeof(buf), stdin)) - return 0; - } else { - buf[0] = '\n'; - buf[1] = '\0'; - } - } + int ret = 0; + char buf[1024]; - if (buf[0] == '\0') - return (0); - else if (buf[0] == '\n') { - if ((def == NULL) || (def[0] == '\0')) - return (1); - BUF_strlcpy(buf, def, sizeof(buf)); - BUF_strlcat(buf, "\n", sizeof(buf)); - } else if ((buf[0] == '.') && (buf[1] == '\n')) - return (1); - - i = strlen(buf); - if (buf[i - 1] != '\n') { - BIO_printf(bio_err, "weird input :-(\n"); - return (0); - } - buf[--i] = '\0'; -#ifdef CHARSET_EBCDIC - ebcdic2ascii(buf, buf, i); -#endif - if (!req_check_len(i, n_min, n_max)) { - if (batch || value) - return 0; - goto start; - } + ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), + "DN value", "DN default"); + if ((ret == 0) || (ret == 1)) + return ret; + ret = 1; if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char *)buf, -1, -1, mval)) - goto err; - ret = 1; - err: - return (ret); + ret = 0; + + return ret; } static int add_attribute_object(X509_REQ *req, char *text, const char *def, char *value, int nid, int n_min, int n_max, unsigned long chtype) { - int i; - static char buf[1024]; + int ret = 0; + char buf[1024]; + + ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), + "Attribute value", "Attribute default"); + if ((ret == 0) || (ret == 1)) + return ret; + ret = 1; + if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, + (unsigned char *)buf, -1)) { + BIO_printf(bio_err, "Error adding attribute\n"); + ERR_print_errors(bio_err); + ret = 0; + } + + return ret; +} + + +static int build_data(char *text, const char *def, + char *value, int n_min, int n_max, + char *buf, const int buf_size, + const char *desc1, const char *desc2 + ) +{ + int i; start: if (!batch) BIO_printf(bio_err, "%s [%s]:", text, def); (void)BIO_flush(bio_err); if (value != NULL) { - BUF_strlcpy(buf, value, sizeof(buf)); - BUF_strlcat(buf, "\n", sizeof(buf)); + if (!join(buf, buf_size, value, "\n", desc1)) + return 0; BIO_printf(bio_err, "%s\n", value); } else { buf[0] = '\0'; if (!batch) { - if (!fgets(buf, sizeof(buf), stdin)) + if (!fgets(buf, buf_size, stdin)) return 0; } else { buf[0] = '\n'; @@ -1446,19 +1359,20 @@ static int add_attribute_object(X509_REQ *req, char *text, const char *def, } if (buf[0] == '\0') - return (0); - else if (buf[0] == '\n') { + return 0; + if (buf[0] == '\n') { if ((def == NULL) || (def[0] == '\0')) - return (1); - BUF_strlcpy(buf, def, sizeof(buf)); - BUF_strlcat(buf, "\n", sizeof(buf)); - } else if ((buf[0] == '.') && (buf[1] == '\n')) - return (1); + return 1; + if (!join(buf, buf_size, def, "\n", desc2)) + return 0; + } else if ((buf[0] == '.') && (buf[1] == '\n')) { + return 1; + } i = strlen(buf); if (buf[i - 1] != '\n') { BIO_printf(bio_err, "weird input :-(\n"); - return (0); + return 0; } buf[--i] = '\0'; #ifdef CHARSET_EBCDIC @@ -1469,17 +1383,7 @@ static int add_attribute_object(X509_REQ *req, char *text, const char *def, return 0; goto start; } - - if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, - (unsigned char *)buf, -1)) { - BIO_printf(bio_err, "Error adding attribute\n"); - ERR_print_errors(bio_err); - goto err; - } - - return (1); - err: - return (0); + return 2; } static int req_check_len(int len, int n_min, int n_max) @@ -1488,22 +1392,23 @@ static int req_check_len(int len, int n_min, int n_max) BIO_printf(bio_err, "string is too short, it needs to be at least %d bytes long\n", n_min); - return (0); + return 0; } if ((n_max >= 0) && (len > n_max)) { BIO_printf(bio_err, - "string is too long, it needs to be less than %d bytes long\n", + "string is too long, it needs to be no more than %d bytes long\n", n_max); - return (0); + return 0; } - return (1); + return 1; } /* Check if the end of a string matches 'end' */ static int check_end(const char *str, const char *end) { - int elen, slen; + size_t elen, slen; const char *tmp; + elen = strlen(end); slen = strlen(str); if (elen > slen) @@ -1512,7 +1417,25 @@ static int check_end(const char *str, const char *end) return strcmp(tmp, end); } -static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr, +/* + * Merge the two strings together into the result buffer checking for + * overflow and producing an error message if there is. + */ +static int join(char buf[], size_t buf_size, const char *name, + const char *tail, const char *desc) +{ + const size_t name_len = strlen(name), tail_len = strlen(tail); + + if (name_len + tail_len + 1 > buf_size) { + BIO_printf(bio_err, "%s '%s' too long\n", desc, name); + return 0; + } + memcpy(buf, name, name_len); + memcpy(buf + name_len, tail, tail_len + 1); + return 1; +} + +static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, int *pkey_type, long *pkeylen, char **palgnam, ENGINE *keygen_engine) { @@ -1529,15 +1452,15 @@ static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr, *pkey_type = EVP_PKEY_RSA; keylen = atol(gstr); *pkeylen = keylen; - } else if (!strncmp(gstr, "param:", 6)) + } else if (strncmp(gstr, "param:", 6) == 0) { paramfile = gstr + 6; - else { + } else { const char *p = strchr(gstr, ':'); int len; ENGINE *tmpeng; const EVP_PKEY_ASN1_METHOD *ameth; - if (p) + if (p != NULL) len = p - gstr; else len = strlen(gstr); @@ -1548,39 +1471,41 @@ static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr, ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len); - if (!ameth) { - BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr); + if (ameth == NULL) { + BIO_printf(bio_err, "Unknown algorithm %.*s\n", len, gstr); return NULL; } EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth); #ifndef OPENSSL_NO_ENGINE - if (tmpeng) - ENGINE_finish(tmpeng); + ENGINE_finish(tmpeng); #endif if (*pkey_type == EVP_PKEY_RSA) { - if (p) { + if (p != NULL) { keylen = atol(p + 1); *pkeylen = keylen; - } else + } else { keylen = *pkeylen; - } else if (p) + } + } else if (p != NULL) { paramfile = p + 1; + } } - if (paramfile) { + if (paramfile != NULL) { pbio = BIO_new_file(paramfile, "r"); - if (!pbio) { - BIO_printf(err, "Can't open parameter file %s\n", paramfile); + if (pbio == NULL) { + BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile); return NULL; } param = PEM_read_bio_Parameters(pbio, NULL); - if (!param) { + if (param == NULL) { X509 *x; + (void)BIO_reset(pbio); x = PEM_read_bio_X509(pbio, NULL, NULL, NULL); - if (x) { + if (x != NULL) { param = X509_get_pubkey(x); X509_free(x); } @@ -1588,59 +1513,61 @@ static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr, BIO_free(pbio); - if (!param) { - BIO_printf(err, "Error reading parameter file %s\n", paramfile); + if (param == NULL) { + BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile); return NULL; } - if (*pkey_type == -1) + if (*pkey_type == -1) { *pkey_type = EVP_PKEY_id(param); - else if (*pkey_type != EVP_PKEY_base_id(param)) { - BIO_printf(err, "Key Type does not match parameters\n"); + } else if (*pkey_type != EVP_PKEY_base_id(param)) { + BIO_printf(bio_err, "Key Type does not match parameters\n"); EVP_PKEY_free(param); return NULL; } } - if (palgnam) { + if (palgnam != NULL) { const EVP_PKEY_ASN1_METHOD *ameth; ENGINE *tmpeng; const char *anam; + ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type); - if (!ameth) { - BIO_puts(err, "Internal error: can't find key algorithm\n"); + if (ameth == NULL) { + BIO_puts(bio_err, "Internal error: can't find key algorithm\n"); return NULL; } EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth); - *palgnam = BUF_strdup(anam); + *palgnam = OPENSSL_strdup(anam); #ifndef OPENSSL_NO_ENGINE - if (tmpeng) - ENGINE_finish(tmpeng); + ENGINE_finish(tmpeng); #endif } - if (param) { + if (param != NULL) { gctx = EVP_PKEY_CTX_new(param, keygen_engine); *pkeylen = EVP_PKEY_bits(param); EVP_PKEY_free(param); - } else + } else { gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine); + } - if (!gctx) { - BIO_puts(err, "Error allocating keygen context\n"); - ERR_print_errors(err); + if (gctx == NULL) { + BIO_puts(bio_err, "Error allocating keygen context\n"); + ERR_print_errors(bio_err); return NULL; } if (EVP_PKEY_keygen_init(gctx) <= 0) { - BIO_puts(err, "Error initializing keygen context\n"); - ERR_print_errors(err); + BIO_puts(bio_err, "Error initializing keygen context\n"); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(gctx); return NULL; } #ifndef OPENSSL_NO_RSA if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) { if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) { - BIO_puts(err, "Error setting RSA keysize\n"); - ERR_print_errors(err); + BIO_puts(bio_err, "Error setting RSA keysize\n"); + ERR_print_errors(bio_err); EVP_PKEY_CTX_free(gctx); return NULL; } @@ -1666,24 +1593,32 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx) c = '\n'; BIO_write(b, &c, 1); (void)BIO_flush(b); -#ifdef LINT - p = n; -#endif return 1; } -static int do_sign_init(BIO *err, EVP_MD_CTX *ctx, EVP_PKEY *pkey, +static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) { EVP_PKEY_CTX *pkctx = NULL; - int i; - EVP_MD_CTX_init(ctx); + int i, def_nid; + + if (ctx == NULL) + return 0; + /* + * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory + * for this algorithm. + */ + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2 + && def_nid == NID_undef) { + /* The signing algorithm requires there to be no digest */ + md = NULL; + } if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) return 0; for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); if (pkey_ctrl_string(pkctx, sigopt) <= 0) { - BIO_printf(err, "parameter error \"%s\"\n", sigopt); + BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); ERR_print_errors(bio_err); return 0; } @@ -1691,41 +1626,39 @@ static int do_sign_init(BIO *err, EVP_MD_CTX *ctx, EVP_PKEY *pkey, return 1; } -int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md, +int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) { int rv; - EVP_MD_CTX mctx; - EVP_MD_CTX_init(&mctx); - rv = do_sign_init(err, &mctx, pkey, md, sigopts); + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + + rv = do_sign_init(mctx, pkey, md, sigopts); if (rv > 0) - rv = X509_sign_ctx(x, &mctx); - EVP_MD_CTX_cleanup(&mctx); + rv = X509_sign_ctx(x, mctx); + EVP_MD_CTX_free(mctx); return rv > 0 ? 1 : 0; } -int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, +int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) { int rv; - EVP_MD_CTX mctx; - EVP_MD_CTX_init(&mctx); - rv = do_sign_init(err, &mctx, pkey, md, sigopts); + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + rv = do_sign_init(mctx, pkey, md, sigopts); if (rv > 0) - rv = X509_REQ_sign_ctx(x, &mctx); - EVP_MD_CTX_cleanup(&mctx); + rv = X509_REQ_sign_ctx(x, mctx); + EVP_MD_CTX_free(mctx); return rv > 0 ? 1 : 0; } -int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, +int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) { int rv; - EVP_MD_CTX mctx; - EVP_MD_CTX_init(&mctx); - rv = do_sign_init(err, &mctx, pkey, md, sigopts); + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + rv = do_sign_init(mctx, pkey, md, sigopts); if (rv > 0) - rv = X509_CRL_sign_ctx(x, &mctx); - EVP_MD_CTX_cleanup(&mctx); + rv = X509_CRL_sign_ctx(x, mctx); + EVP_MD_CTX_free(mctx); return rv > 0 ? 1 : 0; } diff --git a/apps/rsa.c b/apps/rsa.c index ad3af39d4689..6458b3d9c5aa 100644 --- a/apps/rsa.c +++ b/apps/rsa.c @@ -1,68 +1,23 @@ -/* apps/rsa.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_RSA +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + # include <stdio.h> # include <stdlib.h> # include <string.h> # include <time.h> # include "apps.h" +# include "progs.h" # include <openssl/bio.h> # include <openssl/err.h> # include <openssl/rsa.h> @@ -71,201 +26,147 @@ # include <openssl/pem.h> # include <openssl/bn.h> -# undef PROG -# define PROG rsa_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, + OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN, + OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT, + /* Do not change the order here; see case statements below */ + OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, + OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER +} OPTION_CHOICE; -/*- - * -inform arg - input format - default PEM (one of DER, NET or PEM) - * -outform arg - output format - default PEM - * -in arg - input file - default stdin - * -out arg - output file - default stdout - * -des - encrypt output if PEM format with DES in cbc mode - * -des3 - encrypt output if PEM format - * -idea - encrypt output if PEM format - * -seed - encrypt output if PEM format - * -aes128 - encrypt output if PEM format - * -aes192 - encrypt output if PEM format - * -aes256 - encrypt output if PEM format - * -camellia128 - encrypt output if PEM format - * -camellia192 - encrypt output if PEM format - * -camellia256 - encrypt output if PEM format - * -text - print a text version - * -modulus - print the RSA key modulus - * -check - verify key consistency - * -pubin - Expect a public key in input file. - * -pubout - Output a public key. - */ - -int MAIN(int, char **); +const OPTIONS rsa_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', "Input format, one of DER NET PEM"}, + {"outform", OPT_OUTFORM, 'f', "Output format, one of DER NET PEM PVK"}, + {"in", OPT_IN, 's', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"pubout", OPT_PUBOUT, '-', "Output a public key"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"}, + {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"}, + {"noout", OPT_NOOUT, '-', "Don't print key out"}, + {"text", OPT_TEXT, '-', "Print the key in text"}, + {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, + {"check", OPT_CHECK, '-', "Verify key consistency"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, + {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, + {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; -int MAIN(int argc, char **argv) +int rsa_main(int argc, char **argv) { ENGINE *e = NULL; - int ret = 1; + BIO *out = NULL; RSA *rsa = NULL; - int i, badops = 0, sgckey = 0; const EVP_CIPHER *enc = NULL; - BIO *out = NULL; - int informat, outformat, text = 0, check = 0, noout = 0; - int pubin = 0, pubout = 0; - char *infile, *outfile, *prog; - char *passargin = NULL, *passargout = NULL; - char *passin = NULL, *passout = NULL; - char *engine = NULL; - int modulus = 0; - + char *infile = NULL, *outfile = NULL, *prog; + char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; + int i, private = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0; + int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1; +# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) int pvk_encr = 2; - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - infile = NULL; - outfile = NULL; - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-passout") == 0) { - if (--argc < 1) - goto bad; - passargout = *(++argv); - } -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } # endif - else if (strcmp(*argv, "-sgckey") == 0) - sgckey = 1; - else if (strcmp(*argv, "-pubin") == 0) + OPTION_CHOICE o; + + prog = opt_init(argc, argv, rsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rsa_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PUBIN: pubin = 1; - else if (strcmp(*argv, "-pubout") == 0) + break; + case OPT_PUBOUT: pubout = 1; - else if (strcmp(*argv, "-RSAPublicKey_in") == 0) + break; + case OPT_RSAPUBKEY_IN: pubin = 2; - else if (strcmp(*argv, "-RSAPublicKey_out") == 0) + break; + case OPT_RSAPUBKEY_OUT: pubout = 2; - else if (strcmp(*argv, "-pvk-strong") == 0) - pvk_encr = 2; - else if (strcmp(*argv, "-pvk-weak") == 0) - pvk_encr = 1; - else if (strcmp(*argv, "-pvk-none") == 0) - pvk_encr = 0; - else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_PVK_STRONG: /* pvk_encr:= 2 */ + case OPT_PVK_WEAK: /* pvk_encr:= 1 */ + case OPT_PVK_NONE: /* pvk_encr:= 0 */ +# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + pvk_encr = (o - OPT_PVK_NONE); +# endif + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-text") == 0) + break; + case OPT_TEXT: text = 1; - else if (strcmp(*argv, "-modulus") == 0) + break; + case OPT_MODULUS: modulus = 1; - else if (strcmp(*argv, "-check") == 0) + break; + case OPT_CHECK: check = 1; - else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto opthelp; break; } - argc--; - argv++; - } - - if (badops) { - bad: - BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, - " -inform arg input format - one of DER NET PEM\n"); - BIO_printf(bio_err, - " -outform arg output format - one of DER NET PEM\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -sgckey Use IIS SGC key format\n"); - BIO_printf(bio_err, - " -passin arg input file pass phrase source\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, - " -passout arg output file pass phrase source\n"); - BIO_printf(bio_err, - " -des encrypt PEM output with cbc des\n"); - BIO_printf(bio_err, - " -des3 encrypt PEM output with ede cbc des using 168 bit key\n"); -# ifndef OPENSSL_NO_IDEA - BIO_printf(bio_err, - " -idea encrypt PEM output with cbc idea\n"); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, - " -seed encrypt PEM output with cbc seed\n"); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, " -aes128, -aes192, -aes256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc aes\n"); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, " -camellia128, -camellia192, -camellia256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc camellia\n"); -# endif - BIO_printf(bio_err, " -text print the key in text\n"); - BIO_printf(bio_err, " -noout don't print key out\n"); - BIO_printf(bio_err, " -modulus print the RSA key modulus\n"); - BIO_printf(bio_err, " -check verify key consistency\n"); - BIO_printf(bio_err, - " -pubin expect a public key in input file\n"); - BIO_printf(bio_err, " -pubout output a public key\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -# endif - goto end; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - ERR_load_crypto_strings(); + private = (text && !pubin) || (!pubout && !noout) ? 1 : 0; - e = setup_engine(bio_err, engine, 0); - - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - if (check && pubin) { BIO_printf(bio_err, "Only private keys can be checked\n"); goto end; } - out = BIO_new(BIO_s_file()); - { EVP_PKEY *pkey; @@ -276,18 +177,14 @@ int MAIN(int argc, char **argv) tmpformat = FORMAT_PEMRSA; else if (informat == FORMAT_ASN1) tmpformat = FORMAT_ASN1RSA; - } else if (informat == FORMAT_NETSCAPE && sgckey) - tmpformat = FORMAT_IISSGC; - else + } else { tmpformat = informat; + } - pkey = load_pubkey(bio_err, infile, tmpformat, 1, - passin, e, "Public Key"); - } else - pkey = load_key(bio_err, infile, - (informat == FORMAT_NETSCAPE && sgckey ? - FORMAT_IISSGC : informat), 1, - passin, e, "Private Key"); + pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key"); + } else { + pkey = load_key(infile, informat, 1, passin, e, "Private Key"); + } if (pkey != NULL) rsa = EVP_PKEY_get1_RSA(pkey); @@ -299,54 +196,44 @@ int MAIN(int argc, char **argv) goto end; } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; - if (text) + if (text) { + assert(pubin || private); if (!RSA_print(out, rsa, 0)) { perror(outfile); ERR_print_errors(bio_err); goto end; } + } if (modulus) { + const BIGNUM *n; + RSA_get0_key(rsa, &n, NULL, NULL); BIO_printf(out, "Modulus="); - BN_print(out, rsa->n); + BN_print(out, n); BIO_printf(out, "\n"); } if (check) { - int r = RSA_check_key(rsa); + int r = RSA_check_key_ex(rsa, NULL); - if (r == 1) + if (r == 1) { BIO_printf(out, "RSA key ok\n"); - else if (r == 0) { + } else if (r == 0) { unsigned long err; while ((err = ERR_peek_error()) != 0 && ERR_GET_LIB(err) == ERR_LIB_RSA && - ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY && + ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX && ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) { BIO_printf(out, "RSA key error: %s\n", ERR_reason_error_string(err)); - ERR_get_error(); /* remove e from error stack */ + ERR_get_error(); /* remove err from error stack */ } - } - - if (r == -1 || ERR_peek_error() != 0) { /* should happen only if r == - * -1 */ + } else if (r == -1) { ERR_print_errors(bio_err); goto end; } @@ -363,46 +250,46 @@ int MAIN(int argc, char **argv) i = i2d_RSAPublicKey_bio(out, rsa); else i = i2d_RSA_PUBKEY_bio(out, rsa); - } else + } else { + assert(private); i = i2d_RSAPrivateKey_bio(out, rsa); - } -# ifndef OPENSSL_NO_RC4 - else if (outformat == FORMAT_NETSCAPE) { - unsigned char *p, *pp; - int size; - - i = 1; - size = i2d_RSA_NET(rsa, NULL, NULL, sgckey); - if ((p = (unsigned char *)OPENSSL_malloc(size)) == NULL) { - BIO_printf(bio_err, "Memory allocation failure\n"); - goto end; } - pp = p; - i2d_RSA_NET(rsa, &p, NULL, sgckey); - BIO_write(out, (char *)pp, size); - OPENSSL_free(pp); - } -# endif - else if (outformat == FORMAT_PEM) { + } else if (outformat == FORMAT_PEM) { if (pubout || pubin) { if (pubout == 2) i = PEM_write_bio_RSAPublicKey(out, rsa); else i = PEM_write_bio_RSA_PUBKEY(out, rsa); - } else + } else { + assert(private); i = PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, NULL, passout); -# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + } +# ifndef OPENSSL_NO_DSA } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { EVP_PKEY *pk; pk = EVP_PKEY_new(); EVP_PKEY_set1_RSA(pk, rsa); - if (outformat == FORMAT_PVK) + if (outformat == FORMAT_PVK) { + if (pubin) { + BIO_printf(bio_err, "PVK form impossible with public key input\n"); + EVP_PKEY_free(pk); + goto end; + } + assert(private); +# ifdef OPENSSL_NO_RC4 + BIO_printf(bio_err, "PVK format not supported\n"); + EVP_PKEY_free(pk); + goto end; +# else i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); - else if (pubin || pubout) +# endif + } else if (pubin || pubout) { i = i2b_PublicKey_bio(out, pk); - else + } else { + assert(private); i = i2b_PrivateKey_bio(out, pk); + } EVP_PKEY_free(pk); # endif } else { @@ -412,25 +299,15 @@ int MAIN(int argc, char **argv) if (i <= 0) { BIO_printf(bio_err, "unable to write key\n"); ERR_print_errors(bio_err); - } else + } else { ret = 0; + } end: release_engine(e); - if (out != NULL) - BIO_free_all(out); - if (rsa != NULL) - RSA_free(rsa); - if (passin) - OPENSSL_free(passin); - if (passout) - OPENSSL_free(passout); - apps_shutdown(); - OPENSSL_EXIT(ret); + BIO_free_all(out); + RSA_free(rsa); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; } -#else /* !OPENSSL_NO_RSA */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/rsautl.c b/apps/rsautl.c index 87d18063cc7f..5da8504d3c06 100644 --- a/apps/rsautl.c +++ b/apps/rsautl.c @@ -1,66 +1,19 @@ -/* rsautl.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2000. - */ -/* ==================================================================== - * Copyright (c) 2000 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_RSA +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else # include "apps.h" +# include "progs.h" # include <string.h> # include <openssl/err.h> # include <openssl/pem.h> @@ -75,146 +28,165 @@ # define KEY_PUBKEY 2 # define KEY_CERT 3 -static void usage(void); - -# undef PROG +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP, + OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931, + OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, + OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM, + OPT_R_ENUM +} OPTION_CHOICE; -# define PROG rsautl_main - -int MAIN(int argc, char **); +const OPTIONS rsautl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"inkey", OPT_INKEY, 's', "Input key"}, + {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, + {"pubin", OPT_PUBIN, '-', "Input is an RSA public"}, + {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"}, + {"ssl", OPT_SSL, '-', "Use SSL v2 padding"}, + {"raw", OPT_RAW, '-', "Use no padding"}, + {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"}, + {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"}, + {"sign", OPT_SIGN, '-', "Sign with private key"}, + {"verify", OPT_VERIFY, '-', "Verify with public key"}, + {"asn1parse", OPT_ASN1PARSE, '-', + "Run output through asn1parse; useful with -verify"}, + {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, + {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"}, + {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; -int MAIN(int argc, char **argv) +int rsautl_main(int argc, char **argv) { - ENGINE *e = NULL; BIO *in = NULL, *out = NULL; - char *infile = NULL, *outfile = NULL; - char *engine = NULL; - char *keyfile = NULL; - char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; - int keyform = FORMAT_PEM; - char need_priv = 0, badarg = 0, rev = 0; - char hexdump = 0, asn1parse = 0; - X509 *x; + ENGINE *e = NULL; EVP_PKEY *pkey = NULL; RSA *rsa = NULL; - unsigned char *rsa_in = NULL, *rsa_out = NULL, pad; - char *passargin = NULL, *passin = NULL; - int rsa_inlen, rsa_outlen = 0; - int keysize; - - int ret = 1; - - argc--; - argv++; - - if (!bio_err) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - pad = RSA_PKCS1_PADDING; + X509 *x; + char *infile = NULL, *outfile = NULL, *keyfile = NULL; + char *passinarg = NULL, *passin = NULL, *prog; + char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; + unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING; + int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1; + int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0; + OPTION_CHOICE o; - while (argc >= 1) { - if (!strcmp(*argv, "-in")) { - if (--argc < 1) - badarg = 1; - else - infile = *(++argv); - } else if (!strcmp(*argv, "-out")) { - if (--argc < 1) - badarg = 1; - else - outfile = *(++argv); - } else if (!strcmp(*argv, "-inkey")) { - if (--argc < 1) - badarg = 1; - else - keyfile = *(++argv); - } else if (!strcmp(*argv, "-passin")) { - if (--argc < 1) - badarg = 1; - else - passargin = *(++argv); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - badarg = 1; - else - keyform = str2fmt(*(++argv)); -# ifndef OPENSSL_NO_ENGINE - } else if (!strcmp(*argv, "-engine")) { - if (--argc < 1) - badarg = 1; - else - engine = *(++argv); -# endif - } else if (!strcmp(*argv, "-pubin")) { - key_type = KEY_PUBKEY; - } else if (!strcmp(*argv, "-certin")) { - key_type = KEY_CERT; - } else if (!strcmp(*argv, "-asn1parse")) + prog = opt_init(argc, argv, rsautl_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rsautl_options); + ret = 0; + goto end; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_ASN1PARSE: asn1parse = 1; - else if (!strcmp(*argv, "-hexdump")) + break; + case OPT_HEXDUMP: hexdump = 1; - else if (!strcmp(*argv, "-raw")) + break; + case OPT_RAW: pad = RSA_NO_PADDING; - else if (!strcmp(*argv, "-oaep")) + break; + case OPT_OAEP: pad = RSA_PKCS1_OAEP_PADDING; - else if (!strcmp(*argv, "-ssl")) + break; + case OPT_SSL: pad = RSA_SSLV23_PADDING; - else if (!strcmp(*argv, "-pkcs")) + break; + case OPT_PKCS: pad = RSA_PKCS1_PADDING; - else if (!strcmp(*argv, "-x931")) + break; + case OPT_X931: pad = RSA_X931_PADDING; - else if (!strcmp(*argv, "-sign")) { + break; + case OPT_SIGN: rsa_mode = RSA_SIGN; need_priv = 1; - } else if (!strcmp(*argv, "-verify")) + break; + case OPT_VERIFY: rsa_mode = RSA_VERIFY; - else if (!strcmp(*argv, "-rev")) + break; + case OPT_REV: rev = 1; - else if (!strcmp(*argv, "-encrypt")) + break; + case OPT_ENCRYPT: rsa_mode = RSA_ENCRYPT; - else if (!strcmp(*argv, "-decrypt")) { + break; + case OPT_DECRYPT: rsa_mode = RSA_DECRYPT; need_priv = 1; - } else - badarg = 1; - if (badarg) { - usage(); - goto end; + break; + case OPT_PUBIN: + key_type = KEY_PUBKEY; + break; + case OPT_CERTIN: + key_type = KEY_CERT; + break; + case OPT_INKEY: + keyfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; } - argc--; - argv++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; if (need_priv && (key_type != KEY_PRIVKEY)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } - e = setup_engine(bio_err, engine, 0); - if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } -/* FIXME: seed PRNG only if needed */ - app_RAND_load_file(NULL, bio_err, 0); - switch (key_type) { case KEY_PRIVKEY: - pkey = load_key(bio_err, keyfile, keyform, 0, - passin, e, "Private Key"); + pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: - pkey = load_pubkey(bio_err, keyfile, keyform, 0, - NULL, e, "Public Key"); + pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key"); break; case KEY_CERT: - x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate"); + x = load_cert(keyfile, keyformat, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); @@ -222,59 +194,35 @@ int MAIN(int argc, char **argv) break; } - if (!pkey) { + if (pkey == NULL) return 1; - } rsa = EVP_PKEY_get1_RSA(pkey); EVP_PKEY_free(pkey); - if (!rsa) { + if (rsa == NULL) { BIO_printf(bio_err, "Error getting RSA key\n"); ERR_print_errors(bio_err); goto end; } - if (infile) { - if (!(in = BIO_new_file(infile, "rb"))) { - BIO_printf(bio_err, "Error Reading Input File\n"); - ERR_print_errors(bio_err); - goto end; - } - } else - in = BIO_new_fp(stdin, BIO_NOCLOSE); - - if (outfile) { - if (!(out = BIO_new_file(outfile, "wb"))) { - BIO_printf(bio_err, "Error Writing Output File\n"); - ERR_print_errors(bio_err); - goto end; - } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -# ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -# endif - } + in = bio_open_default(infile, 'r', FORMAT_BINARY); + if (in == NULL) + goto end; + out = bio_open_default(outfile, 'w', FORMAT_BINARY); + if (out == NULL) + goto end; keysize = RSA_size(rsa); - rsa_in = OPENSSL_malloc(keysize * 2); - rsa_out = OPENSSL_malloc(keysize); - if (!rsa_in || !rsa_out) { - BIO_printf(bio_err, "Out of memory\n"); - ERR_print_errors(bio_err); - goto end; - } + rsa_in = app_malloc(keysize * 2, "hold rsa key"); + rsa_out = app_malloc(keysize, "output rsa key"); /* Read the input data */ rsa_inlen = BIO_read(in, rsa_in, keysize * 2); if (rsa_inlen < 0) { BIO_printf(bio_err, "Error reading input Data\n"); - exit(1); + goto end; } if (rev) { int i; @@ -304,7 +252,6 @@ int MAIN(int argc, char **argv) rsa_outlen = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; - } if (rsa_outlen < 0) { @@ -317,56 +264,19 @@ int MAIN(int argc, char **argv) if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { ERR_print_errors(bio_err); } - } else if (hexdump) + } else if (hexdump) { BIO_dump(out, (char *)rsa_out, rsa_outlen); - else + } else { BIO_write(out, rsa_out, rsa_outlen); + } end: RSA_free(rsa); release_engine(e); BIO_free(in); BIO_free_all(out); - if (rsa_in) - OPENSSL_free(rsa_in); - if (rsa_out) - OPENSSL_free(rsa_out); - if (passin) - OPENSSL_free(passin); + OPENSSL_free(rsa_in); + OPENSSL_free(rsa_out); + OPENSSL_free(passin); return ret; } - -static void usage() -{ - BIO_printf(bio_err, "Usage: rsautl [options]\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, "-inkey file input key\n"); - BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); - BIO_printf(bio_err, "-pubin input is an RSA public\n"); - BIO_printf(bio_err, - "-certin input is a certificate carrying an RSA public key\n"); - BIO_printf(bio_err, "-ssl use SSL v2 padding\n"); - BIO_printf(bio_err, "-raw use no padding\n"); - BIO_printf(bio_err, - "-pkcs use PKCS#1 v1.5 padding (default)\n"); - BIO_printf(bio_err, "-oaep use PKCS#1 OAEP\n"); - BIO_printf(bio_err, "-sign sign with private key\n"); - BIO_printf(bio_err, "-verify verify with public key\n"); - BIO_printf(bio_err, "-encrypt encrypt with public key\n"); - BIO_printf(bio_err, "-decrypt decrypt with private key\n"); - BIO_printf(bio_err, "-hexdump hex dump output\n"); -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); - BIO_printf(bio_err, "-passin arg pass phrase source\n"); -# endif - -} - -#else /* !OPENSSL_NO_RSA */ - -# if PEDANTIC -static void *dummy = &dummy; -# endif - #endif diff --git a/apps/s_apps.h b/apps/s_apps.h index 5ba1e1d6d86d..0a3bc962808b 100644 --- a/apps/s_apps.h +++ b/apps/s_apps.h @@ -1,117 +1,12 @@ -/* apps/s_apps.h */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -/* conflicts with winsock2 stuff on netware */ -#if !defined(OPENSSL_SYS_NETWARE) -# include <sys/types.h> -#endif + #include <openssl/opensslconf.h> #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) @@ -122,41 +17,15 @@ # define _kbhit kbhit #endif -#if defined(OPENSSL_SYS_VMS) && !defined(FD_SET) -/* - * VAX C does not defined fd_set and friends, but it's actually quite simple - */ -/* These definitions are borrowed from SOCKETSHR. /Richard Levitte */ -# define MAX_NOFILE 32 -# define NBBY 8 /* number of bits in a byte */ - -# ifndef FD_SETSIZE -# define FD_SETSIZE MAX_NOFILE -# endif /* FD_SETSIZE */ - -/* How many things we'll allow select to use. 0 if unlimited */ -# define MAXSELFD MAX_NOFILE -typedef int fd_mask; /* int here! VMS prototypes int, not long */ -# define NFDBITS (sizeof(fd_mask) * NBBY)/* bits per mask (power of 2!) */ -# define NFDSHIFT 5 /* Shift based on above */ - -typedef fd_mask fd_set; -# define FD_SET(n, p) (*(p) |= (1 << ((n) % NFDBITS))) -# define FD_CLR(n, p) (*(p) &= ~(1 << ((n) % NFDBITS))) -# define FD_ISSET(n, p) (*(p) & (1 << ((n) % NFDBITS))) -# define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p))) -#endif - -#define PORT 4433 -#define PORT_STR "4433" +#define PORT "4433" #define PROTOCOL "tcp" -int do_server(int port, int type, int *ret, - int (*cb) (char *hostname, int s, int stype, - unsigned char *context), unsigned char *context, - int naccept); +typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context); +int do_server(int *accept_sock, const char *host, const char *port, + int family, int type, int protocol, do_server_cb cb, + unsigned char *context, int naccept, BIO *bio_s_out); #ifdef HEADER_X509_H -int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); +int verify_callback(int ok, X509_STORE_CTX *ctx); #endif #ifdef HEADER_SSL_H int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); @@ -164,49 +33,57 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, STACK_OF(X509) *chain, int build_chain); int ssl_print_sigalgs(BIO *out, SSL *s); int ssl_print_point_formats(BIO *out, SSL *s); -int ssl_print_curves(BIO *out, SSL *s, int noshared); +int ssl_print_groups(BIO *out, SSL *s, int noshared); #endif int ssl_print_tmp_key(BIO *out, SSL *s); -int init_client(int *sock, char *server, int port, int type); +int init_client(int *sock, const char *host, const char *port, + const char *bindhost, const char *bindport, + int family, int type, int protocol); int should_retry(int i); -int extract_port(char *str, short *port_ptr); -int extract_host_port(char *str, char **host_ptr, unsigned char *ip, - short *p); -long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp, - int argi, long argl, long ret); +long bio_dump_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret); #ifdef HEADER_SSL_H -void MS_CALLBACK apps_ssl_info_callback(const SSL *s, int where, int ret); -void MS_CALLBACK msg_cb(int write_p, int version, int content_type, - const void *buf, size_t len, SSL *ssl, void *arg); -void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type, - unsigned char *data, int len, void *arg); +void apps_ssl_info_callback(const SSL *s, int where, int ret); +void msg_cb(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg); +void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data, + int len, void *arg); +#endif + +int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len); + +#ifdef __VMS /* 31 char symbol name limit */ +# define generate_stateless_cookie_callback generate_stateless_cookie_cb +# define verify_stateless_cookie_callback verify_stateless_cookie_cb #endif -int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie, - unsigned int *cookie_len); -int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie, - unsigned int cookie_len); +int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, + size_t *cookie_len); +int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, + size_t cookie_len); typedef struct ssl_excert_st SSL_EXCERT; void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc); void ssl_excert_free(SSL_EXCERT *exc); -int args_excert(char ***pargs, int *pargc, - int *badarg, BIO *err, SSL_EXCERT **pexc); -int load_excert(SSL_EXCERT **pexc, BIO *err); -void print_ssl_summary(BIO *bio, SSL *s); +int args_excert(int option, SSL_EXCERT **pexc); +int load_excert(SSL_EXCERT **pexc); +void print_verify_detail(SSL *s, BIO *bio); +void print_ssl_summary(SSL *s); #ifdef HEADER_SSL_H -int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx, - int *badarg, BIO *err, STACK_OF(OPENSSL_STRING) **pstr, - int *no_prot_opt); -int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx, - STACK_OF(OPENSSL_STRING) *str, int no_ecdhe, int no_jpake); +int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx); int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download); int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath, const char *vfyCAfile, const char *chCApath, const char *chCAfile, STACK_OF(X509_CRL) *crls, int crl_download); +void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose); +int set_keylog_file(SSL_CTX *ctx, const char *keylog_file); +void print_ca_names(BIO *bio, SSL *s); #endif diff --git a/apps/s_cb.c b/apps/s_cb.c index 7d719543579f..46b386428461 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -1,138 +1,46 @@ -/* apps/s_cb.c - callback functions used by s_client, s_server, and s_time */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ +/* callback functions used by s_client, s_server, and s_time */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* for memcpy() and strcmp() */ -#define USE_SOCKETS -#define NON_MAIN #include "apps.h" -#undef NON_MAIN -#undef USE_SOCKETS #include <openssl/err.h> #include <openssl/rand.h> #include <openssl/x509.h> #include <openssl/ssl.h> +#include <openssl/bn.h> +#ifndef OPENSSL_NO_DH +# include <openssl/dh.h> +#endif #include "s_apps.h" #define COOKIE_SECRET_LENGTH 16 -int verify_depth = 0; -int verify_quiet = 0; -int verify_error = X509_V_OK; -int verify_return_error = 0; -unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; -int cookie_initialized = 0; +VERIFY_CB_ARGS verify_args = { 0, 0, X509_V_OK, 0 }; + +#ifndef OPENSSL_NO_SOCK +static unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; +static int cookie_initialized = 0; +#endif +static BIO *bio_keylog = NULL; + +static const char *lookup(int val, const STRINT_PAIR* list, const char* def) +{ + for ( ; list->name; ++list) + if (list->retval == val) + return list->name; + return def; +} -int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) +int verify_callback(int ok, X509_STORE_CTX *ctx) { X509 *err_cert; int err, depth; @@ -141,73 +49,69 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); - if (!verify_quiet || !ok) { + if (!verify_args.quiet || !ok) { BIO_printf(bio_err, "depth=%d ", depth); - if (err_cert) { + if (err_cert != NULL) { X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert), - 0, XN_FLAG_ONELINE); + 0, get_nameopt()); BIO_puts(bio_err, "\n"); - } else + } else { BIO_puts(bio_err, "<no cert>\n"); + } } if (!ok) { BIO_printf(bio_err, "verify error:num=%d:%s\n", err, X509_verify_cert_error_string(err)); - if (verify_depth >= depth) { - if (!verify_return_error) + if (verify_args.depth >= depth) { + if (!verify_args.return_error) ok = 1; - verify_error = X509_V_OK; + verify_args.error = err; } else { ok = 0; - verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG; + verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG; } } switch (err) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: BIO_puts(bio_err, "issuer= "); X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), - 0, XN_FLAG_ONELINE); + 0, get_nameopt()); BIO_puts(bio_err, "\n"); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: BIO_printf(bio_err, "notBefore="); - ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert)); + ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert)); BIO_printf(bio_err, "\n"); break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: BIO_printf(bio_err, "notAfter="); - ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert)); + ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert)); BIO_printf(bio_err, "\n"); break; case X509_V_ERR_NO_EXPLICIT_POLICY: - if (!verify_quiet) - policies_print(bio_err, ctx); + if (!verify_args.quiet) + policies_print(ctx); break; } - if (err == X509_V_OK && ok == 2 && !verify_quiet) - policies_print(bio_err, ctx); - if (ok && !verify_quiet) + if (err == X509_V_OK && ok == 2 && !verify_args.quiet) + policies_print(ctx); + if (ok && !verify_args.quiet) BIO_printf(bio_err, "verify return:%d\n", ok); - return (ok); + return ok; } int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) { if (cert_file != NULL) { - /*- - SSL *ssl; - X509 *x509; - */ - if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) { BIO_printf(bio_err, "unable to get certificate from '%s'\n", cert_file); ERR_print_errors(bio_err); - return (0); + return 0; } if (key_file == NULL) key_file = cert_file; @@ -215,23 +119,8 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) BIO_printf(bio_err, "unable to get private key from '%s'\n", key_file); ERR_print_errors(bio_err); - return (0); - } - - /*- - In theory this is no longer needed - ssl=SSL_new(ctx); - x509=SSL_get_certificate(ssl); - - if (x509 != NULL) { - EVP_PKEY *pktmp; - pktmp = X509_get_pubkey(x509); - EVP_PKEY_copy_parameters(pktmp, - SSL_get_privatekey(ssl)); - EVP_PKEY_free(pktmp); + return 0; } - SSL_free(ssl); - */ /* * If we are using DSA, we can copy the parameters from the private @@ -245,10 +134,10 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) if (!SSL_CTX_check_private_key(ctx)) { BIO_printf(bio_err, "Private key does not match the certificate public key\n"); - return (0); + return 0; } } - return (1); + return 1; } int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, @@ -290,6 +179,18 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, return 1; } +static STRINT_PAIR cert_type_list[] = { + {"RSA sign", TLS_CT_RSA_SIGN}, + {"DSA sign", TLS_CT_DSS_SIGN}, + {"RSA fixed DH", TLS_CT_RSA_FIXED_DH}, + {"DSS fixed DH", TLS_CT_DSS_FIXED_DH}, + {"ECDSA sign", TLS_CT_ECDSA_SIGN}, + {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH}, + {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH}, + {"GOST01 Sign", TLS_CT_GOST01_SIGN}, + {NULL} +}; + static void ssl_print_client_cert_types(BIO *bio, SSL *s) { const unsigned char *p; @@ -300,57 +201,51 @@ static void ssl_print_client_cert_types(BIO *bio, SSL *s) BIO_puts(bio, "Client Certificate Types: "); for (i = 0; i < cert_type_num; i++) { unsigned char cert_type = p[i]; - char *cname; - switch (cert_type) { - case TLS_CT_RSA_SIGN: - cname = "RSA sign"; - break; + const char *cname = lookup((int)cert_type, cert_type_list, NULL); - case TLS_CT_DSS_SIGN: - cname = "DSA sign"; - break; + if (i) + BIO_puts(bio, ", "); + if (cname != NULL) + BIO_puts(bio, cname); + else + BIO_printf(bio, "UNKNOWN (%d),", cert_type); + } + BIO_puts(bio, "\n"); +} - case TLS_CT_RSA_FIXED_DH: - cname = "RSA fixed DH"; - break; +static const char *get_sigtype(int nid) +{ + switch (nid) { + case EVP_PKEY_RSA: + return "RSA"; - case TLS_CT_DSS_FIXED_DH: - cname = "DSS fixed DH"; - break; + case EVP_PKEY_RSA_PSS: + return "RSA-PSS"; - case TLS_CT_ECDSA_SIGN: - cname = "ECDSA sign"; - break; + case EVP_PKEY_DSA: + return "DSA"; - case TLS_CT_RSA_FIXED_ECDH: - cname = "RSA fixed ECDH"; - break; + case EVP_PKEY_EC: + return "ECDSA"; - case TLS_CT_ECDSA_FIXED_ECDH: - cname = "ECDSA fixed ECDH"; - break; + case NID_ED25519: + return "Ed25519"; - case TLS_CT_GOST94_SIGN: - cname = "GOST94 Sign"; - break; + case NID_ED448: + return "Ed448"; - case TLS_CT_GOST01_SIGN: - cname = "GOST01 Sign"; - break; + case NID_id_GostR3410_2001: + return "gost2001"; - default: - cname = NULL; - } + case NID_id_GostR3410_2012_256: + return "gost2012_256"; - if (i) - BIO_puts(bio, ", "); + case NID_id_GostR3410_2012_512: + return "gost2012_512"; - if (cname) - BIO_puts(bio, cname); - else - BIO_printf(bio, "UNKNOWN (%d),", cert_type); + default: + return NULL; } - BIO_puts(bio, "\n"); } static int do_print_sigalgs(BIO *out, SSL *s, int shared) @@ -358,7 +253,7 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared) int i, nsig, client; client = SSL_is_server(s) ? 0 : 1; if (shared) - nsig = SSL_get_shared_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL); + nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL); else nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL); if (nsig == 0) @@ -381,20 +276,15 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared) SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash); if (i) BIO_puts(out, ":"); - if (sign_nid == EVP_PKEY_RSA) - sstr = "RSA"; - else if (sign_nid == EVP_PKEY_DSA) - sstr = "DSA"; - else if (sign_nid == EVP_PKEY_EC) - sstr = "ECDSA"; + sstr = get_sigtype(sign_nid); if (sstr) - BIO_printf(out, "%s+", sstr); + BIO_printf(out, "%s", sstr); else - BIO_printf(out, "0x%02X+", (int)rsign); + BIO_printf(out, "0x%02X", (int)rsign); if (hash_nid != NID_undef) - BIO_printf(out, "%s", OBJ_nid2sn(hash_nid)); - else - BIO_printf(out, "0x%02X", (int)rhash); + BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid)); + else if (sstr == NULL) + BIO_printf(out, "+0x%02X", (int)rhash); } BIO_puts(out, "\n"); return 1; @@ -402,13 +292,15 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared) int ssl_print_sigalgs(BIO *out, SSL *s) { - int mdnid; + int nid; if (!SSL_is_server(s)) ssl_print_client_cert_types(out, s); do_print_sigalgs(out, s, 0); do_print_sigalgs(out, s, 1); - if (SSL_get_peer_signature_nid(s, &mdnid)) - BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(mdnid)); + if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef) + BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid)); + if (SSL_get_peer_signature_type_nid(s, &nid)) + BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid)); return 1; } @@ -443,67 +335,62 @@ int ssl_print_point_formats(BIO *out, SSL *s) } } - if (nformats <= 0) - BIO_puts(out, "NONE"); BIO_puts(out, "\n"); return 1; } -int ssl_print_curves(BIO *out, SSL *s, int noshared) +int ssl_print_groups(BIO *out, SSL *s, int noshared) { - int i, ncurves, *curves, nid; - const char *cname; - ncurves = SSL_get1_curves(s, NULL); - if (ncurves <= 0) - return 1; - curves = OPENSSL_malloc(ncurves * sizeof(int)); - if (!curves) { - BIO_puts(out, "Malloc error getting supported curves\n"); - return 0; - } - SSL_get1_curves(s, curves); + int i, ngroups, *groups, nid; + const char *gname; + ngroups = SSL_get1_groups(s, NULL); + if (ngroups <= 0) + return 1; + groups = app_malloc(ngroups * sizeof(int), "groups to print"); + SSL_get1_groups(s, groups); - BIO_puts(out, "Supported Elliptic Curves: "); - for (i = 0; i < ncurves; i++) { + BIO_puts(out, "Supported Elliptic Groups: "); + for (i = 0; i < ngroups; i++) { if (i) BIO_puts(out, ":"); - nid = curves[i]; + nid = groups[i]; /* If unrecognised print out hex version */ - if (nid & TLSEXT_nid_unknown) + if (nid & TLSEXT_nid_unknown) { BIO_printf(out, "0x%04X", nid & 0xFFFF); - else { + } else { + /* TODO(TLS1.3): Get group name here */ /* Use NIST name for curve if it exists */ - cname = EC_curve_nid2nist(nid); - if (!cname) - cname = OBJ_nid2sn(nid); - BIO_printf(out, "%s", cname); + gname = EC_curve_nid2nist(nid); + if (gname == NULL) + gname = OBJ_nid2sn(nid); + BIO_printf(out, "%s", gname); } } - if (ncurves == 0) - BIO_puts(out, "NONE"); - OPENSSL_free(curves); + OPENSSL_free(groups); if (noshared) { BIO_puts(out, "\n"); return 1; } - BIO_puts(out, "\nShared Elliptic curves: "); - ncurves = SSL_get_shared_curve(s, -1); - for (i = 0; i < ncurves; i++) { + BIO_puts(out, "\nShared Elliptic groups: "); + ngroups = SSL_get_shared_group(s, -1); + for (i = 0; i < ngroups; i++) { if (i) BIO_puts(out, ":"); - nid = SSL_get_shared_curve(s, i); - cname = EC_curve_nid2nist(nid); - if (!cname) - cname = OBJ_nid2sn(nid); - BIO_printf(out, "%s", cname); + nid = SSL_get_shared_group(s, i); + /* TODO(TLS1.3): Convert for DH groups */ + gname = EC_curve_nid2nist(nid); + if (gname == NULL) + gname = OBJ_nid2sn(nid); + BIO_printf(out, "%s", gname); } - if (ncurves == 0) + if (ngroups == 0) BIO_puts(out, "NONE"); BIO_puts(out, "\n"); return 1; } #endif + int ssl_print_tmp_key(BIO *out, SSL *s) { EVP_PKEY *key; @@ -518,7 +405,7 @@ int ssl_print_tmp_key(BIO *out, SSL *s) case EVP_PKEY_DH: BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key)); break; -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC case EVP_PKEY_EC: { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); @@ -527,39 +414,43 @@ int ssl_print_tmp_key(BIO *out, SSL *s) nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); EC_KEY_free(ec); cname = EC_curve_nid2nist(nid); - if (!cname) + if (cname == NULL) cname = OBJ_nid2sn(nid); BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key)); } + break; #endif + default: + BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)), + EVP_PKEY_bits(key)); } EVP_PKEY_free(key); return 1; } -long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp, - int argi, long argl, long ret) +long bio_dump_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret) { BIO *out; out = (BIO *)BIO_get_callback_arg(bio); if (out == NULL) - return (ret); + return ret; if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { BIO_printf(out, "read from %p [%p] (%lu bytes => %ld (0x%lX))\n", (void *)bio, (void *)argp, (unsigned long)argi, ret, ret); BIO_dump(out, argp, (int)ret); - return (ret); + return ret; } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { BIO_printf(out, "write to %p [%p] (%lu bytes => %ld (0x%lX))\n", (void *)bio, (void *)argp, (unsigned long)argi, ret, ret); BIO_dump(out, argp, (int)ret); } - return (ret); + return ret; } -void MS_CALLBACK apps_ssl_info_callback(const SSL *s, int where, int ret) +void apps_ssl_info_callback(const SSL *s, int where, int ret) { const char *str; int w; @@ -585,128 +476,110 @@ void MS_CALLBACK apps_ssl_info_callback(const SSL *s, int where, int ret) if (ret == 0) BIO_printf(bio_err, "%s:failed in %s\n", str, SSL_state_string_long(s)); - else if (ret < 0) { + else if (ret < 0) BIO_printf(bio_err, "%s:error in %s\n", str, SSL_state_string_long(s)); - } } } -void MS_CALLBACK msg_cb(int write_p, int version, int content_type, - const void *buf, size_t len, SSL *ssl, void *arg) -{ - BIO *bio = arg; - const char *str_write_p, *str_version, *str_content_type = - "", *str_details1 = "", *str_details2 = ""; - - str_write_p = write_p ? ">>>" : "<<<"; - - switch (version) { - case SSL2_VERSION: - str_version = "SSL 2.0"; - break; - case SSL3_VERSION: - str_version = "SSL 3.0 "; - break; - case TLS1_VERSION: - str_version = "TLS 1.0 "; - break; - case TLS1_1_VERSION: - str_version = "TLS 1.1 "; - break; - case TLS1_2_VERSION: - str_version = "TLS 1.2 "; - break; - case DTLS1_VERSION: - str_version = "DTLS 1.0 "; - break; - case DTLS1_BAD_VER: - str_version = "DTLS 1.0 (bad) "; - break; - default: - str_version = "???"; - } - - if (version == SSL2_VERSION) { - str_details1 = "???"; +static STRINT_PAIR ssl_versions[] = { + {"SSL 3.0", SSL3_VERSION}, + {"TLS 1.0", TLS1_VERSION}, + {"TLS 1.1", TLS1_1_VERSION}, + {"TLS 1.2", TLS1_2_VERSION}, + {"TLS 1.3", TLS1_3_VERSION}, + {"DTLS 1.0", DTLS1_VERSION}, + {"DTLS 1.0 (bad)", DTLS1_BAD_VER}, + {NULL} +}; - if (len > 0) { - switch (((const unsigned char *)buf)[0]) { - case 0: - str_details1 = ", ERROR:"; - str_details2 = " ???"; - if (len >= 3) { - unsigned err = - (((const unsigned char *)buf)[1] << 8) + - ((const unsigned char *)buf)[2]; +static STRINT_PAIR alert_types[] = { + {" close_notify", 0}, + {" end_of_early_data", 1}, + {" unexpected_message", 10}, + {" bad_record_mac", 20}, + {" decryption_failed", 21}, + {" record_overflow", 22}, + {" decompression_failure", 30}, + {" handshake_failure", 40}, + {" bad_certificate", 42}, + {" unsupported_certificate", 43}, + {" certificate_revoked", 44}, + {" certificate_expired", 45}, + {" certificate_unknown", 46}, + {" illegal_parameter", 47}, + {" unknown_ca", 48}, + {" access_denied", 49}, + {" decode_error", 50}, + {" decrypt_error", 51}, + {" export_restriction", 60}, + {" protocol_version", 70}, + {" insufficient_security", 71}, + {" internal_error", 80}, + {" inappropriate_fallback", 86}, + {" user_canceled", 90}, + {" no_renegotiation", 100}, + {" missing_extension", 109}, + {" unsupported_extension", 110}, + {" certificate_unobtainable", 111}, + {" unrecognized_name", 112}, + {" bad_certificate_status_response", 113}, + {" bad_certificate_hash_value", 114}, + {" unknown_psk_identity", 115}, + {" certificate_required", 116}, + {NULL} +}; - switch (err) { - case 0x0001: - str_details2 = " NO-CIPHER-ERROR"; - break; - case 0x0002: - str_details2 = " NO-CERTIFICATE-ERROR"; - break; - case 0x0004: - str_details2 = " BAD-CERTIFICATE-ERROR"; - break; - case 0x0006: - str_details2 = " UNSUPPORTED-CERTIFICATE-TYPE-ERROR"; - break; - } - } +static STRINT_PAIR handshakes[] = { + {", HelloRequest", SSL3_MT_HELLO_REQUEST}, + {", ClientHello", SSL3_MT_CLIENT_HELLO}, + {", ServerHello", SSL3_MT_SERVER_HELLO}, + {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST}, + {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET}, + {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA}, + {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS}, + {", Certificate", SSL3_MT_CERTIFICATE}, + {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE}, + {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST}, + {", ServerHelloDone", SSL3_MT_SERVER_DONE}, + {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY}, + {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE}, + {", Finished", SSL3_MT_FINISHED}, + {", CertificateUrl", SSL3_MT_CERTIFICATE_URL}, + {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS}, + {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA}, + {", KeyUpdate", SSL3_MT_KEY_UPDATE}, +#ifndef OPENSSL_NO_NEXTPROTONEG + {", NextProto", SSL3_MT_NEXT_PROTO}, +#endif + {", MessageHash", SSL3_MT_MESSAGE_HASH}, + {NULL} +}; - break; - case 1: - str_details1 = ", CLIENT-HELLO"; - break; - case 2: - str_details1 = ", CLIENT-MASTER-KEY"; - break; - case 3: - str_details1 = ", CLIENT-FINISHED"; - break; - case 4: - str_details1 = ", SERVER-HELLO"; - break; - case 5: - str_details1 = ", SERVER-VERIFY"; - break; - case 6: - str_details1 = ", SERVER-FINISHED"; - break; - case 7: - str_details1 = ", REQUEST-CERTIFICATE"; - break; - case 8: - str_details1 = ", CLIENT-CERTIFICATE"; - break; - } - } - } +void msg_cb(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg) +{ + BIO *bio = arg; + const char *str_write_p = write_p ? ">>>" : "<<<"; + const char *str_version = lookup(version, ssl_versions, "???"); + const char *str_content_type = "", *str_details1 = "", *str_details2 = ""; + const unsigned char* bp = buf; if (version == SSL3_VERSION || version == TLS1_VERSION || version == TLS1_1_VERSION || version == TLS1_2_VERSION || + version == TLS1_3_VERSION || version == DTLS1_VERSION || version == DTLS1_BAD_VER) { switch (content_type) { case 20: - str_content_type = "ChangeCipherSpec"; + str_content_type = ", ChangeCipherSpec"; break; case 21: - str_content_type = "Alert"; - break; - case 22: - str_content_type = "Handshake"; - break; - } - - if (content_type == 21) { /* Alert */ + str_content_type = ", Alert"; str_details1 = ", ???"; - if (len == 2) { - switch (((const unsigned char *)buf)[0]) { + switch (bp[0]) { case 1: str_details1 = ", warning"; break; @@ -714,147 +587,24 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, str_details1 = ", fatal"; break; } - - str_details2 = " ???"; - switch (((const unsigned char *)buf)[1]) { - case 0: - str_details2 = " close_notify"; - break; - case 10: - str_details2 = " unexpected_message"; - break; - case 20: - str_details2 = " bad_record_mac"; - break; - case 21: - str_details2 = " decryption_failed"; - break; - case 22: - str_details2 = " record_overflow"; - break; - case 30: - str_details2 = " decompression_failure"; - break; - case 40: - str_details2 = " handshake_failure"; - break; - case 42: - str_details2 = " bad_certificate"; - break; - case 43: - str_details2 = " unsupported_certificate"; - break; - case 44: - str_details2 = " certificate_revoked"; - break; - case 45: - str_details2 = " certificate_expired"; - break; - case 46: - str_details2 = " certificate_unknown"; - break; - case 47: - str_details2 = " illegal_parameter"; - break; - case 48: - str_details2 = " unknown_ca"; - break; - case 49: - str_details2 = " access_denied"; - break; - case 50: - str_details2 = " decode_error"; - break; - case 51: - str_details2 = " decrypt_error"; - break; - case 60: - str_details2 = " export_restriction"; - break; - case 70: - str_details2 = " protocol_version"; - break; - case 71: - str_details2 = " insufficient_security"; - break; - case 80: - str_details2 = " internal_error"; - break; - case 90: - str_details2 = " user_canceled"; - break; - case 100: - str_details2 = " no_renegotiation"; - break; - case 110: - str_details2 = " unsupported_extension"; - break; - case 111: - str_details2 = " certificate_unobtainable"; - break; - case 112: - str_details2 = " unrecognized_name"; - break; - case 113: - str_details2 = " bad_certificate_status_response"; - break; - case 114: - str_details2 = " bad_certificate_hash_value"; - break; - case 115: - str_details2 = " unknown_psk_identity"; - break; - } + str_details2 = lookup((int)bp[1], alert_types, " ???"); } - } - - if (content_type == 22) { /* Handshake */ + break; + case 22: + str_content_type = ", Handshake"; str_details1 = "???"; - - if (len > 0) { - switch (((const unsigned char *)buf)[0]) { - case 0: - str_details1 = ", HelloRequest"; - break; - case 1: - str_details1 = ", ClientHello"; - break; - case 2: - str_details1 = ", ServerHello"; - break; - case 3: - str_details1 = ", HelloVerifyRequest"; - break; - case 11: - str_details1 = ", Certificate"; - break; - case 12: - str_details1 = ", ServerKeyExchange"; - break; - case 13: - str_details1 = ", CertificateRequest"; - break; - case 14: - str_details1 = ", ServerHelloDone"; - break; - case 15: - str_details1 = ", CertificateVerify"; - break; - case 16: - str_details1 = ", ClientKeyExchange"; - break; - case 20: - str_details1 = ", Finished"; - break; - } - } - } + if (len > 0) + str_details1 = lookup((int)bp[0], handshakes, "???"); + break; + case 23: + str_content_type = ", ApplicationData"; + break; #ifndef OPENSSL_NO_HEARTBEATS - if (content_type == 24) { /* Heartbeat */ + case 24: str_details1 = ", Heartbeat"; if (len > 0) { - switch (((const unsigned char *)buf)[0]) { + switch (bp[0]) { case 1: str_details1 = ", HeartbeatRequest"; break; @@ -863,8 +613,9 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, break; } } - } + break; #endif + } } BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version, @@ -876,10 +627,6 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, BIO_printf(bio, " "); num = len; -#if 0 - if (num > 16) - num = 16; -#endif for (i = 0; i < num; i++) { if (i % 16 == 0 && i > 0) BIO_printf(bio, "\n "); @@ -892,129 +639,69 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, (void)BIO_flush(bio); } -void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type, - unsigned char *data, int len, void *arg) -{ - BIO *bio = arg; - char *extname; - - switch (type) { - case TLSEXT_TYPE_server_name: - extname = "server name"; - break; - - case TLSEXT_TYPE_max_fragment_length: - extname = "max fragment length"; - break; - - case TLSEXT_TYPE_client_certificate_url: - extname = "client certificate URL"; - break; - - case TLSEXT_TYPE_trusted_ca_keys: - extname = "trusted CA keys"; - break; - - case TLSEXT_TYPE_truncated_hmac: - extname = "truncated HMAC"; - break; - - case TLSEXT_TYPE_status_request: - extname = "status request"; - break; - - case TLSEXT_TYPE_user_mapping: - extname = "user mapping"; - break; - - case TLSEXT_TYPE_client_authz: - extname = "client authz"; - break; - - case TLSEXT_TYPE_server_authz: - extname = "server authz"; - break; - - case TLSEXT_TYPE_cert_type: - extname = "cert type"; - break; - - case TLSEXT_TYPE_elliptic_curves: - extname = "elliptic curves"; - break; - - case TLSEXT_TYPE_ec_point_formats: - extname = "EC point formats"; - break; - - case TLSEXT_TYPE_srp: - extname = "SRP"; - break; - - case TLSEXT_TYPE_signature_algorithms: - extname = "signature algorithms"; - break; - - case TLSEXT_TYPE_use_srtp: - extname = "use SRTP"; - break; - - case TLSEXT_TYPE_heartbeat: - extname = "heartbeat"; - break; - - case TLSEXT_TYPE_session_ticket: - extname = "session ticket"; - break; - - case TLSEXT_TYPE_renegotiate: - extname = "renegotiation info"; - break; - -#ifdef TLSEXT_TYPE_opaque_prf_input - case TLSEXT_TYPE_opaque_prf_input: - extname = "opaque PRF input"; - break; -#endif +static STRINT_PAIR tlsext_types[] = { + {"server name", TLSEXT_TYPE_server_name}, + {"max fragment length", TLSEXT_TYPE_max_fragment_length}, + {"client certificate URL", TLSEXT_TYPE_client_certificate_url}, + {"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys}, + {"truncated HMAC", TLSEXT_TYPE_truncated_hmac}, + {"status request", TLSEXT_TYPE_status_request}, + {"user mapping", TLSEXT_TYPE_user_mapping}, + {"client authz", TLSEXT_TYPE_client_authz}, + {"server authz", TLSEXT_TYPE_server_authz}, + {"cert type", TLSEXT_TYPE_cert_type}, + {"supported_groups", TLSEXT_TYPE_supported_groups}, + {"EC point formats", TLSEXT_TYPE_ec_point_formats}, + {"SRP", TLSEXT_TYPE_srp}, + {"signature algorithms", TLSEXT_TYPE_signature_algorithms}, + {"use SRTP", TLSEXT_TYPE_use_srtp}, + {"heartbeat", TLSEXT_TYPE_heartbeat}, + {"session ticket", TLSEXT_TYPE_session_ticket}, + {"renegotiation info", TLSEXT_TYPE_renegotiate}, + {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp}, + {"TLS padding", TLSEXT_TYPE_padding}, #ifdef TLSEXT_TYPE_next_proto_neg - case TLSEXT_TYPE_next_proto_neg: - extname = "next protocol"; - break; + {"next protocol", TLSEXT_TYPE_next_proto_neg}, +#endif +#ifdef TLSEXT_TYPE_encrypt_then_mac + {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac}, #endif #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation - case TLSEXT_TYPE_application_layer_protocol_negotiation: - extname = "application layer protocol negotiation"; - break; + {"application layer protocol negotiation", + TLSEXT_TYPE_application_layer_protocol_negotiation}, #endif +#ifdef TLSEXT_TYPE_extended_master_secret + {"extended master secret", TLSEXT_TYPE_extended_master_secret}, +#endif + {"key share", TLSEXT_TYPE_key_share}, + {"supported versions", TLSEXT_TYPE_supported_versions}, + {"psk", TLSEXT_TYPE_psk}, + {"psk kex modes", TLSEXT_TYPE_psk_kex_modes}, + {"certificate authorities", TLSEXT_TYPE_certificate_authorities}, + {"post handshake auth", TLSEXT_TYPE_post_handshake_auth}, + {NULL} +}; - case TLSEXT_TYPE_padding: - extname = "TLS padding"; - break; - - default: - extname = "unknown"; - break; - - } +void tlsext_cb(SSL *s, int client_server, int type, + const unsigned char *data, int len, void *arg) +{ + BIO *bio = arg; + const char *extname = lookup(type, tlsext_types, "unknown"); BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n", client_server ? "server" : "client", extname, type, len); - BIO_dump(bio, (char *)data, len); + BIO_dump(bio, (const char *)data, len); (void)BIO_flush(bio); } -int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie, - unsigned int *cookie_len) +#ifndef OPENSSL_NO_SOCK +int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len) { - unsigned char *buffer, result[EVP_MAX_MD_SIZE]; - unsigned int length, resultlength; - union { - struct sockaddr sa; - struct sockaddr_in s4; -#if OPENSSL_USE_IPV6 - struct sockaddr_in6 s6; -#endif - } peer; + unsigned char *buffer; + size_t length = 0; + unsigned short port; + BIO_ADDR *lpeer = NULL, *peer = NULL; /* Initialize a random secret */ if (!cookie_initialized) { @@ -1025,136 +712,76 @@ int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie, cookie_initialized = 1; } - /* Read peer information */ - (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + if (SSL_is_dtls(ssl)) { + lpeer = peer = BIO_ADDR_new(); + if (peer == NULL) { + BIO_printf(bio_err, "memory full\n"); + return 0; + } - /* Create buffer with peer's address and port */ - length = 0; - switch (peer.sa.sa_family) { - case AF_INET: - length += sizeof(struct in_addr); - length += sizeof(peer.s4.sin_port); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - length += sizeof(struct in6_addr); - length += sizeof(peer.s6.sin6_port); - break; -#endif - default: - OPENSSL_assert(0); - break; + /* Read peer information */ + (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer); + } else { + peer = ourpeer; } - buffer = OPENSSL_malloc(length); - if (buffer == NULL) { - BIO_printf(bio_err, "out of memory\n"); + /* Create buffer with peer's address and port */ + if (!BIO_ADDR_rawaddress(peer, NULL, &length)) { + BIO_printf(bio_err, "Failed getting peer address\n"); return 0; } + OPENSSL_assert(length != 0); + port = BIO_ADDR_rawport(peer); + length += sizeof(port); + buffer = app_malloc(length, "cookie generate buffer"); - switch (peer.sa.sa_family) { - case AF_INET: - memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port)); - memcpy(buffer + sizeof(peer.s4.sin_port), - &peer.s4.sin_addr, sizeof(struct in_addr)); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port)); - memcpy(buffer + sizeof(peer.s6.sin6_port), - &peer.s6.sin6_addr, sizeof(struct in6_addr)); - break; -#endif - default: - OPENSSL_assert(0); - break; - } + memcpy(buffer, &port, sizeof(port)); + BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL); /* Calculate HMAC of buffer using the secret */ HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, - buffer, length, result, &resultlength); - OPENSSL_free(buffer); + buffer, length, cookie, cookie_len); - memcpy(cookie, result, resultlength); - *cookie_len = resultlength; + OPENSSL_free(buffer); + BIO_ADDR_free(lpeer); return 1; } -int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie, - unsigned int cookie_len) +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len) { - unsigned char *buffer, result[EVP_MAX_MD_SIZE]; - unsigned int length, resultlength; - union { - struct sockaddr sa; - struct sockaddr_in s4; -#if OPENSSL_USE_IPV6 - struct sockaddr_in6 s6; -#endif - } peer; - - /* If secret isn't initialized yet, the cookie can't be valid */ - if (!cookie_initialized) - return 0; - - /* Read peer information */ - (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); - - /* Create buffer with peer's address and port */ - length = 0; - switch (peer.sa.sa_family) { - case AF_INET: - length += sizeof(struct in_addr); - length += sizeof(peer.s4.sin_port); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - length += sizeof(struct in6_addr); - length += sizeof(peer.s6.sin6_port); - break; -#endif - default: - OPENSSL_assert(0); - break; - } - buffer = OPENSSL_malloc(length); - - if (buffer == NULL) { - BIO_printf(bio_err, "out of memory\n"); - return 0; - } - - switch (peer.sa.sa_family) { - case AF_INET: - memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port)); - memcpy(buffer + sizeof(peer.s4.sin_port), - &peer.s4.sin_addr, sizeof(struct in_addr)); - break; -#if OPENSSL_USE_IPV6 - case AF_INET6: - memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port)); - memcpy(buffer + sizeof(peer.s6.sin6_port), - &peer.s6.sin6_addr, sizeof(struct in6_addr)); - break; -#endif - default: - OPENSSL_assert(0); - break; - } - - /* Calculate HMAC of buffer using the secret */ - HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, - buffer, length, result, &resultlength); - OPENSSL_free(buffer); + unsigned char result[EVP_MAX_MD_SIZE]; + unsigned int resultlength; - if (cookie_len == resultlength + /* Note: we check cookie_initialized because if it's not, + * it cannot be valid */ + if (cookie_initialized + && generate_cookie_callback(ssl, result, &resultlength) + && cookie_len == resultlength && memcmp(result, cookie, resultlength) == 0) return 1; return 0; } +int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, + size_t *cookie_len) +{ + unsigned int temp; + int res = generate_cookie_callback(ssl, cookie, &temp); + *cookie_len = temp; + return res; +} + +int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, + size_t cookie_len) +{ + return verify_cookie_callback(ssl, cookie, cookie_len); +} + +#endif + /* * Example of extended certificate handling. Where the standard support of * one certificate per algorithm is not sufficient an application can decide @@ -1176,37 +803,32 @@ struct ssl_excert_st { struct ssl_excert_st *next, *prev; }; -struct chain_flags { - int flag; - const char *name; -}; - -struct chain_flags chain_flags_list[] = { - {CERT_PKEY_VALID, "Overall Validity"}, - {CERT_PKEY_SIGN, "Sign with EE key"}, - {CERT_PKEY_EE_SIGNATURE, "EE signature"}, - {CERT_PKEY_CA_SIGNATURE, "CA signature"}, - {CERT_PKEY_EE_PARAM, "EE key parameters"}, - {CERT_PKEY_CA_PARAM, "CA key parameters"}, - {CERT_PKEY_EXPLICIT_SIGN, "Explicity sign with EE key"}, - {CERT_PKEY_ISSUER_NAME, "Issuer Name"}, - {CERT_PKEY_CERT_TYPE, "Certificate Type"}, - {0, NULL} +static STRINT_PAIR chain_flags[] = { + {"Overall Validity", CERT_PKEY_VALID}, + {"Sign with EE key", CERT_PKEY_SIGN}, + {"EE signature", CERT_PKEY_EE_SIGNATURE}, + {"CA signature", CERT_PKEY_CA_SIGNATURE}, + {"EE key parameters", CERT_PKEY_EE_PARAM}, + {"CA key parameters", CERT_PKEY_CA_PARAM}, + {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN}, + {"Issuer Name", CERT_PKEY_ISSUER_NAME}, + {"Certificate Type", CERT_PKEY_CERT_TYPE}, + {NULL} }; -static void print_chain_flags(BIO *out, SSL *s, int flags) +static void print_chain_flags(SSL *s, int flags) { - struct chain_flags *ctmp = chain_flags_list; - while (ctmp->name) { - BIO_printf(out, "\t%s: %s\n", ctmp->name, - flags & ctmp->flag ? "OK" : "NOT OK"); - ctmp++; - } - BIO_printf(out, "\tSuite B: "); + STRINT_PAIR *pp; + + for (pp = chain_flags; pp->name; ++pp) + BIO_printf(bio_err, "\t%s: %s\n", + pp->name, + (flags & pp->retval) ? "OK" : "NOT OK"); + BIO_printf(bio_err, "\tSuite B: "); if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS) - BIO_puts(out, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n"); + BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n"); else - BIO_printf(out, "not tested\n"); + BIO_printf(bio_err, "not tested\n"); } /* @@ -1221,37 +843,39 @@ static int set_cert_cb(SSL *ssl, void *arg) static int retry_cnt; if (retry_cnt < 5) { retry_cnt++; - fprintf(stderr, "Certificate callback retry test: count %d\n", - retry_cnt); + BIO_printf(bio_err, + "Certificate callback retry test: count %d\n", + retry_cnt); return -1; } #endif SSL_certs_clear(ssl); - if (!exc) + if (exc == NULL) return 1; /* * Go to end of list and traverse backwards since we prepend newer * entries this retains the original order. */ - while (exc->next) + while (exc->next != NULL) exc = exc->next; i = 0; - while (exc) { + while (exc != NULL) { i++; rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain); BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i); X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0, - XN_FLAG_ONELINE); + get_nameopt()); BIO_puts(bio_err, "\n"); - - print_chain_flags(bio_err, ssl, rv); + print_chain_flags(ssl, rv); if (rv & CERT_PKEY_VALID) { - SSL_use_certificate(ssl, exc->cert); - SSL_use_PrivateKey(ssl, exc->key); + if (!SSL_use_certificate(ssl, exc->cert) + || !SSL_use_PrivateKey(ssl, exc->key)) { + return 0; + } /* * NB: we wouldn't normally do this as it is not efficient * building chains on each connection better to cache the chain @@ -1260,8 +884,9 @@ static int set_cert_cb(SSL *ssl, void *arg) if (exc->build_chain) { if (!SSL_build_cert_chain(ssl, 0)) return 0; - } else if (exc->chain) + } else if (exc->chain != NULL) { SSL_set1_chain(ssl, exc->chain); + } } exc = exc->prev; } @@ -1275,18 +900,9 @@ void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc) static int ssl_excert_prepend(SSL_EXCERT **pexc) { - SSL_EXCERT *exc; - exc = OPENSSL_malloc(sizeof(SSL_EXCERT)); - if (!exc) - return 0; - exc->certfile = NULL; - exc->keyfile = NULL; - exc->chainfile = NULL; - exc->cert = NULL; - exc->key = NULL; - exc->chain = NULL; - exc->prev = NULL; - exc->build_chain = 0; + SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert"); + + memset(exc, 0, sizeof(*exc)); exc->next = *pexc; *pexc = exc; @@ -1306,306 +922,287 @@ static int ssl_excert_prepend(SSL_EXCERT **pexc) void ssl_excert_free(SSL_EXCERT *exc) { SSL_EXCERT *curr; + + if (exc == NULL) + return; while (exc) { - if (exc->cert) - X509_free(exc->cert); - if (exc->key) - EVP_PKEY_free(exc->key); - if (exc->chain) - sk_X509_pop_free(exc->chain, X509_free); + X509_free(exc->cert); + EVP_PKEY_free(exc->key); + sk_X509_pop_free(exc->chain, X509_free); curr = exc; exc = exc->next; OPENSSL_free(curr); } } -int load_excert(SSL_EXCERT **pexc, BIO *err) +int load_excert(SSL_EXCERT **pexc) { SSL_EXCERT *exc = *pexc; - if (!exc) + if (exc == NULL) return 1; /* If nothing in list, free and set to NULL */ - if (!exc->certfile && !exc->next) { + if (exc->certfile == NULL && exc->next == NULL) { ssl_excert_free(exc); *pexc = NULL; return 1; } for (; exc; exc = exc->next) { - if (!exc->certfile) { - BIO_printf(err, "Missing filename\n"); + if (exc->certfile == NULL) { + BIO_printf(bio_err, "Missing filename\n"); return 0; } - exc->cert = load_cert(err, exc->certfile, exc->certform, - NULL, NULL, "Server Certificate"); - if (!exc->cert) + exc->cert = load_cert(exc->certfile, exc->certform, + "Server Certificate"); + if (exc->cert == NULL) return 0; - if (exc->keyfile) { - exc->key = load_key(err, exc->keyfile, exc->keyform, + if (exc->keyfile != NULL) { + exc->key = load_key(exc->keyfile, exc->keyform, 0, NULL, NULL, "Server Key"); } else { - exc->key = load_key(err, exc->certfile, exc->certform, + exc->key = load_key(exc->certfile, exc->certform, 0, NULL, NULL, "Server Key"); } - if (!exc->key) + if (exc->key == NULL) return 0; - if (exc->chainfile) { - exc->chain = load_certs(err, - exc->chainfile, FORMAT_PEM, - NULL, NULL, "Server Chain"); - if (!exc->chain) + if (exc->chainfile != NULL) { + if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL, + "Server Chain")) return 0; } } return 1; } -int args_excert(char ***pargs, int *pargc, - int *badarg, BIO *err, SSL_EXCERT **pexc) +enum range { OPT_X_ENUM }; + +int args_excert(int opt, SSL_EXCERT **pexc) { - char *arg = **pargs, *argn = (*pargs)[1]; SSL_EXCERT *exc = *pexc; - int narg = 2; - if (!exc) { - if (ssl_excert_prepend(&exc)) - *pexc = exc; - else { - BIO_printf(err, "Error initialising xcert\n"); - *badarg = 1; + + assert(opt > OPT_X__FIRST); + assert(opt < OPT_X__LAST); + + if (exc == NULL) { + if (!ssl_excert_prepend(&exc)) { + BIO_printf(bio_err, " %s: Error initialising xcert\n", + opt_getprog()); goto err; } + *pexc = exc; } - if (strcmp(arg, "-xcert") == 0) { - if (!argn) { - *badarg = 1; - return 1; - } - if (exc->certfile && !ssl_excert_prepend(&exc)) { - BIO_printf(err, "Error adding xcert\n"); - *badarg = 1; + + switch ((enum range)opt) { + case OPT_X__FIRST: + case OPT_X__LAST: + return 0; + case OPT_X_CERT: + if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) { + BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog()); goto err; } - exc->certfile = argn; - } else if (strcmp(arg, "-xkey") == 0) { - if (!argn) { - *badarg = 1; - return 1; - } - if (exc->keyfile) { - BIO_printf(err, "Key already specified\n"); - *badarg = 1; - return 1; - } - exc->keyfile = argn; - } else if (strcmp(arg, "-xchain") == 0) { - if (!argn) { - *badarg = 1; - return 1; - } - if (exc->chainfile) { - BIO_printf(err, "Chain already specified\n"); - *badarg = 1; - return 1; - } - exc->chainfile = argn; - } else if (strcmp(arg, "-xchain_build") == 0) { - narg = 1; - exc->build_chain = 1; - } else if (strcmp(arg, "-xcertform") == 0) { - if (!argn) { - *badarg = 1; + *pexc = exc; + exc->certfile = opt_arg(); + break; + case OPT_X_KEY: + if (exc->keyfile != NULL) { + BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog()); goto err; } - exc->certform = str2fmt(argn); - } else if (strcmp(arg, "-xkeyform") == 0) { - if (!argn) { - *badarg = 1; + exc->keyfile = opt_arg(); + break; + case OPT_X_CHAIN: + if (exc->chainfile != NULL) { + BIO_printf(bio_err, "%s: Chain already specified\n", + opt_getprog()); goto err; } - exc->keyform = str2fmt(argn); - } else - return 0; - - (*pargs) += narg; - - if (pargc) - *pargc -= narg; - - *pexc = exc; - + exc->chainfile = opt_arg(); + break; + case OPT_X_CHAIN_BUILD: + exc->build_chain = 1; + break; + case OPT_X_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform)) + return 0; + break; + case OPT_X_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform)) + return 0; + break; + } return 1; err: - ERR_print_errors(err); + ERR_print_errors(bio_err); ssl_excert_free(exc); *pexc = NULL; - return 1; + return 0; } -static void print_raw_cipherlist(BIO *bio, SSL *s) +static void print_raw_cipherlist(SSL *s) { const unsigned char *rlist; - static const unsigned char scsv_id[] = { 0, 0, 0xFF }; + static const unsigned char scsv_id[] = { 0, 0xFF }; size_t i, rlistlen, num; if (!SSL_is_server(s)) return; num = SSL_get0_raw_cipherlist(s, NULL); + OPENSSL_assert(num == 2); rlistlen = SSL_get0_raw_cipherlist(s, &rlist); - BIO_puts(bio, "Client cipher list: "); + BIO_puts(bio_err, "Client cipher list: "); for (i = 0; i < rlistlen; i += num, rlist += num) { const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist); if (i) - BIO_puts(bio, ":"); - if (c) - BIO_puts(bio, SSL_CIPHER_get_name(c)); - else if (!memcmp(rlist, scsv_id - num + 3, num)) - BIO_puts(bio, "SCSV"); - else { + BIO_puts(bio_err, ":"); + if (c != NULL) { + BIO_puts(bio_err, SSL_CIPHER_get_name(c)); + } else if (memcmp(rlist, scsv_id, num) == 0) { + BIO_puts(bio_err, "SCSV"); + } else { size_t j; - BIO_puts(bio, "0x"); + BIO_puts(bio_err, "0x"); for (j = 0; j < num; j++) - BIO_printf(bio, "%02X", rlist[j]); + BIO_printf(bio_err, "%02X", rlist[j]); } } - BIO_puts(bio, "\n"); + BIO_puts(bio_err, "\n"); } -void print_ssl_summary(BIO *bio, SSL *s) +/* + * Hex encoder for TLSA RRdata, not ':' delimited. + */ +static char *hexencode(const unsigned char *data, size_t len) +{ + static const char *hex = "0123456789abcdef"; + char *out; + char *cp; + size_t outlen = 2 * len + 1; + int ilen = (int) outlen; + + if (outlen < len || ilen < 0 || outlen != (size_t)ilen) { + BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n", + opt_getprog(), len); + exit(1); + } + cp = out = app_malloc(ilen, "TLSA hex data buffer"); + + while (len-- > 0) { + *cp++ = hex[(*data >> 4) & 0x0f]; + *cp++ = hex[*data++ & 0x0f]; + } + *cp = '\0'; + return out; +} + +void print_verify_detail(SSL *s, BIO *bio) +{ + int mdpth; + EVP_PKEY *mspki; + long verify_err = SSL_get_verify_result(s); + + if (verify_err == X509_V_OK) { + const char *peername = SSL_get0_peername(s); + + BIO_printf(bio, "Verification: OK\n"); + if (peername != NULL) + BIO_printf(bio, "Verified peername: %s\n", peername); + } else { + const char *reason = X509_verify_cert_error_string(verify_err); + + BIO_printf(bio, "Verification error: %s\n", reason); + } + + if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) { + uint8_t usage, selector, mtype; + const unsigned char *data = NULL; + size_t dlen = 0; + char *hexdata; + + mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen); + + /* + * The TLSA data field can be quite long when it is a certificate, + * public key or even a SHA2-512 digest. Because the initial octets of + * ASN.1 certificates and public keys contain mostly boilerplate OIDs + * and lengths, we show the last 12 bytes of the data instead, as these + * are more likely to distinguish distinct TLSA records. + */ +#define TLSA_TAIL_SIZE 12 + if (dlen > TLSA_TAIL_SIZE) + hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE); + else + hexdata = hexencode(data, dlen); + BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n", + usage, selector, mtype, + (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata, + (mspki != NULL) ? "signed the certificate" : + mdpth ? "matched TA certificate" : "matched EE certificate", + mdpth); + OPENSSL_free(hexdata); + } +} + +void print_ssl_summary(SSL *s) { const SSL_CIPHER *c; X509 *peer; - /* - * const char *pnam = SSL_is_server(s) ? "client" : "server"; - */ - BIO_printf(bio, "Protocol version: %s\n", SSL_get_version(s)); - print_raw_cipherlist(bio, s); + + BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s)); + print_raw_cipherlist(s); c = SSL_get_current_cipher(s); - BIO_printf(bio, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); - do_print_sigalgs(bio, s, 0); + BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); + do_print_sigalgs(bio_err, s, 0); peer = SSL_get_peer_certificate(s); - if (peer) { + if (peer != NULL) { int nid; - BIO_puts(bio, "Peer certificate: "); - X509_NAME_print_ex(bio, X509_get_subject_name(peer), - 0, XN_FLAG_ONELINE); - BIO_puts(bio, "\n"); + + BIO_puts(bio_err, "Peer certificate: "); + X509_NAME_print_ex(bio_err, X509_get_subject_name(peer), + 0, get_nameopt()); + BIO_puts(bio_err, "\n"); if (SSL_get_peer_signature_nid(s, &nid)) - BIO_printf(bio, "Hash used: %s\n", OBJ_nid2sn(nid)); - } else - BIO_puts(bio, "No peer certificate\n"); - if (peer) - X509_free(peer); + BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid)); + if (SSL_get_peer_signature_type_nid(s, &nid)) + BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid)); + print_verify_detail(s, bio_err); + } else { + BIO_puts(bio_err, "No peer certificate\n"); + } + X509_free(peer); #ifndef OPENSSL_NO_EC - ssl_print_point_formats(bio, s); + ssl_print_point_formats(bio_err, s); if (SSL_is_server(s)) - ssl_print_curves(bio, s, 1); + ssl_print_groups(bio_err, s, 1); else - ssl_print_tmp_key(bio, s); + ssl_print_tmp_key(bio_err, s); #else if (!SSL_is_server(s)) - ssl_print_tmp_key(bio, s); + ssl_print_tmp_key(bio_err, s); #endif } -int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx, - int *badarg, BIO *err, STACK_OF(OPENSSL_STRING) **pstr, - int *no_prot_opt) -{ - char *arg = **pargs, *argn = (*pargs)[1]; - int rv; - - if (strcmp(arg, "-no_ssl2") == 0 || strcmp(arg, "-no_ssl3") == 0 - || strcmp(arg, "-no_tls1") == 0 || strcmp(arg, "-no_tls1_1") == 0 - || strcmp(arg, "-no_tls1_2") == 0) { - *no_prot_opt = 1; - } - - /* Attempt to run SSL configuration command */ - rv = SSL_CONF_cmd_argv(cctx, pargc, pargs); - /* If parameter not recognised just return */ - if (rv == 0) - return 0; - /* see if missing argument error */ - if (rv == -3) { - BIO_printf(err, "%s needs an argument\n", arg); - *badarg = 1; - goto end; - } - /* Check for some other error */ - if (rv < 0) { - BIO_printf(err, "Error with command: \"%s %s\"\n", - arg, argn ? argn : ""); - *badarg = 1; - goto end; - } - /* Store command and argument */ - /* If only one argument processed store value as NULL */ - if (rv == 1) - argn = NULL; - if (!*pstr) - *pstr = sk_OPENSSL_STRING_new_null(); - if (!*pstr || !sk_OPENSSL_STRING_push(*pstr, arg) || - !sk_OPENSSL_STRING_push(*pstr, argn)) { - BIO_puts(err, "Memory allocation failure\n"); - goto end; - } - - end: - if (*badarg) - ERR_print_errors(err); - - return 1; -} - -int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx, - STACK_OF(OPENSSL_STRING) *str, int no_ecdhe, int no_jpake) +int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, + SSL_CTX *ctx) { int i; + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) { - const char *param = sk_OPENSSL_STRING_value(str, i); - const char *value = sk_OPENSSL_STRING_value(str, i + 1); - /* - * If no_ecdhe or named curve already specified don't need a default. - */ - if (!no_ecdhe && !strcmp(param, "-named_curve")) - no_ecdhe = 1; -#ifndef OPENSSL_NO_JPAKE - if (!no_jpake && !strcmp(param, "-cipher")) { - BIO_puts(err, "JPAKE sets cipher to PSK\n"); - return 0; - } -#endif - if (SSL_CONF_cmd(cctx, param, value) <= 0) { - BIO_printf(err, "Error with command: \"%s %s\"\n", - param, value ? value : ""); - ERR_print_errors(err); - return 0; - } - } - /* - * This is a special case to keep existing s_server functionality: if we - * don't have any curve specified *and* we haven't disabled ECDHE then - * use P-256. - */ - if (!no_ecdhe) { - if (SSL_CONF_cmd(cctx, "-named_curve", "P-256") <= 0) { - BIO_puts(err, "Error setting EC curve\n"); - ERR_print_errors(err); - return 0; - } - } -#ifndef OPENSSL_NO_JPAKE - if (!no_jpake) { - if (SSL_CONF_cmd(cctx, "-cipher", "PSK") <= 0) { - BIO_puts(err, "Error setting cipher to PSK\n"); - ERR_print_errors(err); + const char *flag = sk_OPENSSL_STRING_value(str, i); + const char *arg = sk_OPENSSL_STRING_value(str, i + 1); + if (SSL_CONF_cmd(cctx, flag, arg) <= 0) { + if (arg != NULL) + BIO_printf(bio_err, "Error with command: \"%s %s\"\n", + flag, arg); + else + BIO_printf(bio_err, "Error with command: \"%s\"\n", flag); + ERR_print_errors(bio_err); return 0; } } -#endif if (!SSL_CONF_CTX_finish(cctx)) { - BIO_puts(err, "Error finishing context\n"); - ERR_print_errors(err); + BIO_puts(bio_err, "Error finishing context\n"); + ERR_print_errors(bio_err); return 0; } return 1; @@ -1639,8 +1236,10 @@ int ssl_load_stores(SSL_CTX *ctx, { X509_STORE *vfy = NULL, *ch = NULL; int rv = 0; - if (vfyCApath || vfyCAfile) { + if (vfyCApath != NULL || vfyCAfile != NULL) { vfy = X509_STORE_new(); + if (vfy == NULL) + goto err; if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath)) goto err; add_crls_store(vfy, crls); @@ -1648,17 +1247,234 @@ int ssl_load_stores(SSL_CTX *ctx, if (crl_download) store_setup_crl_download(vfy); } - if (chCApath || chCAfile) { + if (chCApath != NULL || chCAfile != NULL) { ch = X509_STORE_new(); + if (ch == NULL) + goto err; if (!X509_STORE_load_locations(ch, chCAfile, chCApath)) goto err; SSL_CTX_set1_chain_cert_store(ctx, ch); } rv = 1; err: - if (vfy) - X509_STORE_free(vfy); - if (ch) - X509_STORE_free(ch); + X509_STORE_free(vfy); + X509_STORE_free(ch); + return rv; +} + +/* Verbose print out of security callback */ + +typedef struct { + BIO *out; + int verbose; + int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, + void *other, void *ex); +} security_debug_ex; + +static STRINT_PAIR callback_types[] = { + {"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED}, + {"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED}, + {"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK}, +#ifndef OPENSSL_NO_DH + {"Temp DH key bits", SSL_SECOP_TMP_DH}, +#endif + {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED}, + {"Shared Curve", SSL_SECOP_CURVE_SHARED}, + {"Check Curve", SSL_SECOP_CURVE_CHECK}, + {"Supported Signature Algorithm digest", SSL_SECOP_SIGALG_SUPPORTED}, + {"Shared Signature Algorithm digest", SSL_SECOP_SIGALG_SHARED}, + {"Check Signature Algorithm digest", SSL_SECOP_SIGALG_CHECK}, + {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK}, + {"Certificate chain EE key", SSL_SECOP_EE_KEY}, + {"Certificate chain CA key", SSL_SECOP_CA_KEY}, + {"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY}, + {"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY}, + {"Certificate chain CA digest", SSL_SECOP_CA_MD}, + {"Peer chain CA digest", SSL_SECOP_PEER_CA_MD}, + {"SSL compression", SSL_SECOP_COMPRESSION}, + {"Session ticket", SSL_SECOP_TICKET}, + {NULL} +}; + +static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex) +{ + security_debug_ex *sdb = ex; + int rv, show_bits = 1, cert_md = 0; + const char *nm; + rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex); + if (rv == 1 && sdb->verbose < 2) + return 1; + BIO_puts(sdb->out, "Security callback: "); + + nm = lookup(op, callback_types, NULL); + switch (op) { + case SSL_SECOP_TICKET: + case SSL_SECOP_COMPRESSION: + show_bits = 0; + nm = NULL; + break; + case SSL_SECOP_VERSION: + BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???")); + show_bits = 0; + nm = NULL; + break; + case SSL_SECOP_CA_MD: + case SSL_SECOP_PEER_CA_MD: + cert_md = 1; + break; + } + if (nm != NULL) + BIO_printf(sdb->out, "%s=", nm); + + switch (op & SSL_SECOP_OTHER_TYPE) { + + case SSL_SECOP_OTHER_CIPHER: + BIO_puts(sdb->out, SSL_CIPHER_get_name(other)); + break; + +#ifndef OPENSSL_NO_EC + case SSL_SECOP_OTHER_CURVE: + { + const char *cname; + cname = EC_curve_nid2nist(nid); + if (cname == NULL) + cname = OBJ_nid2sn(nid); + BIO_puts(sdb->out, cname); + } + break; +#endif +#ifndef OPENSSL_NO_DH + case SSL_SECOP_OTHER_DH: + { + DH *dh = other; + BIO_printf(sdb->out, "%d", DH_bits(dh)); + break; + } +#endif + case SSL_SECOP_OTHER_CERT: + { + if (cert_md) { + int sig_nid = X509_get_signature_nid(other); + BIO_puts(sdb->out, OBJ_nid2sn(sig_nid)); + } else { + EVP_PKEY *pkey = X509_get0_pubkey(other); + const char *algname = ""; + EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, + &algname, EVP_PKEY_get0_asn1(pkey)); + BIO_printf(sdb->out, "%s, bits=%d", + algname, EVP_PKEY_bits(pkey)); + } + break; + } + case SSL_SECOP_OTHER_SIGALG: + { + const unsigned char *salg = other; + const char *sname = NULL; + switch (salg[1]) { + case TLSEXT_signature_anonymous: + sname = "anonymous"; + break; + case TLSEXT_signature_rsa: + sname = "RSA"; + break; + case TLSEXT_signature_dsa: + sname = "DSA"; + break; + case TLSEXT_signature_ecdsa: + sname = "ECDSA"; + break; + } + + BIO_puts(sdb->out, OBJ_nid2sn(nid)); + if (sname) + BIO_printf(sdb->out, ", algorithm=%s", sname); + else + BIO_printf(sdb->out, ", algid=%d", salg[1]); + break; + } + + } + + if (show_bits) + BIO_printf(sdb->out, ", security bits=%d", bits); + BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no"); return rv; } + +void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose) +{ + static security_debug_ex sdb; + + sdb.out = bio_err; + sdb.verbose = verbose; + sdb.old_cb = SSL_CTX_get_security_callback(ctx); + SSL_CTX_set_security_callback(ctx, security_callback_debug); + SSL_CTX_set0_security_ex_data(ctx, &sdb); +} + +static void keylog_callback(const SSL *ssl, const char *line) +{ + if (bio_keylog == NULL) { + BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n"); + return; + } + + /* + * There might be concurrent writers to the keylog file, so we must ensure + * that the given line is written at once. + */ + BIO_printf(bio_keylog, "%s\n", line); + (void)BIO_flush(bio_keylog); +} + +int set_keylog_file(SSL_CTX *ctx, const char *keylog_file) +{ + /* Close any open files */ + BIO_free_all(bio_keylog); + bio_keylog = NULL; + + if (ctx == NULL || keylog_file == NULL) { + /* Keylogging is disabled, OK. */ + return 0; + } + + /* + * Append rather than write in order to allow concurrent modification. + * Furthermore, this preserves existing keylog files which is useful when + * the tool is run multiple times. + */ + bio_keylog = BIO_new_file(keylog_file, "a"); + if (bio_keylog == NULL) { + BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file); + return 1; + } + + /* Write a header for seekable, empty files (this excludes pipes). */ + if (BIO_tell(bio_keylog) == 0) { + BIO_puts(bio_keylog, + "# SSL/TLS secrets log file, generated by OpenSSL\n"); + (void)BIO_flush(bio_keylog); + } + SSL_CTX_set_keylog_callback(ctx, keylog_callback); + return 0; +} + +void print_ca_names(BIO *bio, SSL *s) +{ + const char *cs = SSL_is_server(s) ? "server" : "client"; + const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s); + int i; + + if (sk == NULL || sk_X509_NAME_num(sk) == 0) { + BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs); + return; + } + + BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs); + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt()); + BIO_write(bio, "\n", 1); + } +} diff --git a/apps/s_client.c b/apps/s_client.c index c85566855fef..dcaa10cf44eb 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -1,149 +1,22 @@ -/* apps/s_client.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ -/* ==================================================================== +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2005 Nokia. All rights reserved. * - * The portions of the attached software ("Contribution") is developed by - * Nokia Corporation and is licensed pursuant to the OpenSSL open source - * license. - * - * The Contribution, originally written by Mika Kousa and Pasi Eronen of - * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites - * support (see RFC 4279) to OpenSSL. - * - * No patent licenses or other rights except those expressly stated in - * the OpenSSL open source license shall be deemed granted or received - * expressly, by implication, estoppel, or otherwise. - * - * No assurances are provided by Nokia that the Contribution does not - * infringe the patent or other intellectual property rights of any third - * party or that the license provides you with all the necessary rights - * to make use of the Contribution. - * - * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN - * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA - * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY - * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR - * OTHERWISE. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <assert.h> +#include "e_os.h" #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #include <openssl/e_os2.h> -#ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -#endif + +#ifndef OPENSSL_NO_SOCK /* * With IPv6, it looks like Digital has mixed up the proper order of @@ -156,8 +29,8 @@ typedef unsigned int u_int; #endif -#define USE_SOCKETS #include "apps.h" +#include "progs.h" #include <openssl/x509.h> #include <openssl/ssl.h> #include <openssl/err.h> @@ -165,78 +38,83 @@ typedef unsigned int u_int; #include <openssl/rand.h> #include <openssl/ocsp.h> #include <openssl/bn.h> +#include <openssl/async.h> #ifndef OPENSSL_NO_SRP # include <openssl/srp.h> #endif +#ifndef OPENSSL_NO_CT +# include <openssl/ct.h> +#endif #include "s_apps.h" #include "timeouts.h" +#include "internal/sockets.h" -#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) -/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ -# undef FIONBIO -#endif - -#if defined(OPENSSL_SYS_BEOS_R5) -# include <fcntl.h> +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include <sanitizer/msan_interface.h> +# endif #endif -#undef PROG -#define PROG s_client_main - -/* - * #define SSL_HOST_NAME "www.netscape.com" - */ -/* - * #define SSL_HOST_NAME "193.118.187.102" - */ -#define SSL_HOST_NAME "localhost" - -/* no default cert. */ -/* - * #define TEST_CERT "client.pem" - */ - #undef BUFSIZZ #define BUFSIZZ 1024*8 +#define S_CLIENT_IRC_READ_TIMEOUT 8 -extern int verify_depth; -extern int verify_error; -extern int verify_return_error; -extern int verify_quiet; - -#ifdef FIONBIO -static int c_nbio = 0; -#endif -static int c_Pause = 0; +static char *prog; static int c_debug = 0; -#ifndef OPENSSL_NO_TLSEXT -static int c_tlsextdebug = 0; -static int c_status_req = 0; -#endif -static int c_msg = 0; static int c_showcerts = 0; - static char *keymatexportlabel = NULL; static int keymatexportlen = 20; +static BIO *bio_c_out = NULL; +static int c_quiet = 0; +static char *sess_out = NULL; +static SSL_SESSION *psksess = NULL; -static void sc_usage(void); static void print_stuff(BIO *berr, SSL *con, int full); -#ifndef OPENSSL_NO_TLSEXT +#ifndef OPENSSL_NO_OCSP static int ocsp_resp_cb(SSL *s, void *arg); #endif -static BIO *bio_c_out = NULL; -static BIO *bio_c_msg = NULL; -static int c_quiet = 0; -static int c_ign_eof = 0; -static int c_brief = 0; +static int ldap_ExtendedResponse_parse(const char *buf, long rem); + +static int saved_errno; + +static void save_errno(void) +{ + saved_errno = errno; + errno = 0; +} + +static int restore_errno(void) +{ + int ret = errno; + errno = saved_errno; + return ret; +} + +static void do_ssl_shutdown(SSL *ssl) +{ + int ret; + + do { + /* We only do unidirectional shutdown */ + ret = SSL_shutdown(ssl); + if (ret < 0) { + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_ASYNC_JOB: + /* We just do busy waiting. Nothing clever */ + continue; + } + ret = 0; + } + } while (ret < 0); +} -#ifndef OPENSSL_NO_PSK /* Default PSK identity and key */ static char *psk_identity = "Client_identity"; -/* - * char *psk_key=NULL; by default PSK is not used - */ +#ifndef OPENSSL_NO_PSK static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, @@ -253,8 +131,9 @@ static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity, if (c_debug) BIO_printf(bio_c_out, "NULL received PSK identity hint, continuing anyway\n"); - } else if (c_debug) + } else if (c_debug) { BIO_printf(bio_c_out, "Received PSK identity hint '%s'\n", hint); + } /* * lookup PSK identity and PSK key based on the given identity hint here @@ -267,13 +146,13 @@ static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity, ret); /* convert the PSK key to binary */ - key = string_to_hex(psk_key, &key_len); + key = OPENSSL_hexstr2buf(psk_key, &key_len); if (key == NULL) { BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", psk_key); return 0; } - if ((unsigned long)key_len > (unsigned long)max_psk_len) { + if (max_psk_len > INT_MAX || key_len > (long)max_psk_len) { BIO_printf(bio_err, "psk buffer of callback is too small (%d) for key (%ld)\n", max_psk_len, key_len); @@ -295,158 +174,70 @@ static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity, } #endif -static void sc_usage(void) +const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; +const unsigned char tls13_aes256gcmsha384_id[] = { 0x13, 0x02 }; + +static int psk_use_session_cb(SSL *s, const EVP_MD *md, + const unsigned char **id, size_t *idlen, + SSL_SESSION **sess) { - BIO_printf(bio_err, "usage: s_client args\n"); - BIO_printf(bio_err, "\n"); - BIO_printf(bio_err, " -host host - use -connect instead\n"); - BIO_printf(bio_err, " -port port - use -connect instead\n"); - BIO_printf(bio_err, - " -connect host:port - who to connect to (default is %s:%s)\n", - SSL_HOST_NAME, PORT_STR); - BIO_printf(bio_err, - " -verify_hostname host - check peer certificate matches \"host\"\n"); - BIO_printf(bio_err, - " -verify_email email - check peer certificate matches \"email\"\n"); - BIO_printf(bio_err, - " -verify_ip ipaddr - check peer certificate matches \"ipaddr\"\n"); + SSL_SESSION *usesess = NULL; + const SSL_CIPHER *cipher = NULL; - BIO_printf(bio_err, - " -verify arg - turn on peer certificate verification\n"); - BIO_printf(bio_err, - " -verify_return_error - return verification errors\n"); - BIO_printf(bio_err, - " -cert arg - certificate file to use, PEM format assumed\n"); - BIO_printf(bio_err, - " -certform arg - certificate format (PEM or DER) PEM default\n"); - BIO_printf(bio_err, - " -key arg - Private key file to use, in cert file if\n"); - BIO_printf(bio_err, " not specified but cert file is.\n"); - BIO_printf(bio_err, - " -keyform arg - key format (PEM or DER) PEM default\n"); - BIO_printf(bio_err, - " -pass arg - private key file pass phrase source\n"); - BIO_printf(bio_err, " -CApath arg - PEM format directory of CA's\n"); - BIO_printf(bio_err, " -CAfile arg - PEM format file of CA's\n"); - BIO_printf(bio_err, - " -no_alt_chains - only ever use the first certificate chain found\n"); - BIO_printf(bio_err, - " -reconnect - Drop and re-make the connection with the same Session-ID\n"); - BIO_printf(bio_err, - " -pause - sleep(1) after each read(2) and write(2) system call\n"); - BIO_printf(bio_err, - " -prexit - print session information even on connection failure\n"); - BIO_printf(bio_err, - " -showcerts - show all certificates in the chain\n"); - BIO_printf(bio_err, " -debug - extra output\n"); -#ifdef WATT32 - BIO_printf(bio_err, " -wdebug - WATT-32 tcp debugging\n"); -#endif - BIO_printf(bio_err, " -msg - Show protocol messages\n"); - BIO_printf(bio_err, " -nbio_test - more ssl protocol testing\n"); - BIO_printf(bio_err, " -state - print the 'ssl' states\n"); -#ifdef FIONBIO - BIO_printf(bio_err, " -nbio - Run with non-blocking IO\n"); -#endif - BIO_printf(bio_err, - " -crlf - convert LF from terminal into CRLF\n"); - BIO_printf(bio_err, " -quiet - no s_client output\n"); - BIO_printf(bio_err, - " -ign_eof - ignore input eof (default when -quiet)\n"); - BIO_printf(bio_err, " -no_ign_eof - don't ignore input eof\n"); -#ifndef OPENSSL_NO_PSK - BIO_printf(bio_err, " -psk_identity arg - PSK identity\n"); - BIO_printf(bio_err, " -psk arg - PSK in hex (without 0x)\n"); -# ifndef OPENSSL_NO_JPAKE - BIO_printf(bio_err, " -jpake arg - JPAKE secret to use\n"); -# endif -#endif -#ifndef OPENSSL_NO_SRP - BIO_printf(bio_err, - " -srpuser user - SRP authentification for 'user'\n"); - BIO_printf(bio_err, " -srppass arg - password for 'user'\n"); - BIO_printf(bio_err, - " -srp_lateuser - SRP username into second ClientHello message\n"); - BIO_printf(bio_err, - " -srp_moregroups - Tolerate other than the known g N values.\n"); - BIO_printf(bio_err, - " -srp_strength int - minimal length in bits for N (default %d).\n", - SRP_MINIMAL_N); -#endif - BIO_printf(bio_err, " -ssl2 - just use SSLv2\n"); -#ifndef OPENSSL_NO_SSL3_METHOD - BIO_printf(bio_err, " -ssl3 - just use SSLv3\n"); -#endif - BIO_printf(bio_err, " -tls1_2 - just use TLSv1.2\n"); - BIO_printf(bio_err, " -tls1_1 - just use TLSv1.1\n"); - BIO_printf(bio_err, " -tls1 - just use TLSv1\n"); - BIO_printf(bio_err, " -dtls1 - just use DTLSv1\n"); - BIO_printf(bio_err, " -fallback_scsv - send TLS_FALLBACK_SCSV\n"); - BIO_printf(bio_err, " -mtu - set the link layer MTU\n"); - BIO_printf(bio_err, - " -no_tls1_2/-no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n"); - BIO_printf(bio_err, - " -bugs - Switch on all SSL implementation bug workarounds\n"); - BIO_printf(bio_err, - " -cipher - preferred cipher to use, use the 'openssl ciphers'\n"); - BIO_printf(bio_err, - " command to see what is available\n"); - BIO_printf(bio_err, - " -starttls prot - use the STARTTLS command before starting TLS\n"); - BIO_printf(bio_err, - " for those protocols that support it, where\n"); - BIO_printf(bio_err, - " 'prot' defines which one to assume. Currently,\n"); - BIO_printf(bio_err, - " only \"smtp\", \"pop3\", \"imap\", \"ftp\" and \"xmpp\"\n"); - BIO_printf(bio_err, " are supported.\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine id - Initialise and use the specified engine\n"); -#endif - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, " -sess_out arg - file to write SSL session to\n"); - BIO_printf(bio_err, " -sess_in arg - file to read SSL session from\n"); -#ifndef OPENSSL_NO_TLSEXT - BIO_printf(bio_err, - " -servername host - Set TLS extension servername in ClientHello\n"); - BIO_printf(bio_err, - " -tlsextdebug - hex dump of all TLS extensions received\n"); - BIO_printf(bio_err, - " -status - request certificate status from server\n"); - BIO_printf(bio_err, - " -no_ticket - disable use of RFC4507bis session tickets\n"); - BIO_printf(bio_err, - " -serverinfo types - send empty ClientHello extensions (comma-separated numbers)\n"); - BIO_printf(bio_err, - " -curves arg - Elliptic curves to advertise (colon-separated list)\n"); - BIO_printf(bio_err, - " -sigalgs arg - Signature algorithms to support (colon-separated list)\n"); - BIO_printf(bio_err, - " -client_sigalgs arg - Signature algorithms to support for client\n"); - BIO_printf(bio_err, - " certificate authentication (colon-separated list)\n"); -#endif -#ifndef OPENSSL_NO_NEXTPROTONEG - BIO_printf(bio_err, - " -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n"); -#endif - BIO_printf(bio_err, - " -alpn arg - enable ALPN extension, considering named protocols supported (comma-separated list)\n"); - BIO_printf(bio_err, - " -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); -#ifndef OPENSSL_NO_SRTP - BIO_printf(bio_err, - " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); -#endif - BIO_printf(bio_err, - " -keymatexport label - Export keying material using label\n"); - BIO_printf(bio_err, - " -keymatexportlen len - Export len bytes of keying material (default 20)\n"); -} + if (psksess != NULL) { + SSL_SESSION_up_ref(psksess); + usesess = psksess; + } else { + long key_len; + unsigned char *key = OPENSSL_hexstr2buf(psk_key, &key_len); + + if (key == NULL) { + BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", + psk_key); + return 0; + } + + /* We default to SHA-256 */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); + OPENSSL_free(key); + return 0; + } + + usesess = SSL_SESSION_new(); + if (usesess == NULL + || !SSL_SESSION_set1_master_key(usesess, key, key_len) + || !SSL_SESSION_set_cipher(usesess, cipher) + || !SSL_SESSION_set_protocol_version(usesess, TLS1_3_VERSION)) { + OPENSSL_free(key); + goto err; + } + OPENSSL_free(key); + } + + cipher = SSL_SESSION_get0_cipher(usesess); + if (cipher == NULL) + goto err; + + if (md != NULL && SSL_CIPHER_get_handshake_digest(cipher) != md) { + /* PSK not usable, ignore it */ + *id = NULL; + *idlen = 0; + *sess = NULL; + SSL_SESSION_free(usesess); + } else { + *sess = usesess; + *id = (unsigned char *)psk_identity; + *idlen = strlen(psk_identity); + } + + return 1; -#ifndef OPENSSL_NO_TLSEXT + err: + SSL_SESSION_free(usesess); + return 0; +} /* This is a context that we pass to callbacks */ typedef struct tlsextctx_st { @@ -454,7 +245,7 @@ typedef struct tlsextctx_st { int ack; } tlsextctx; -static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) +static int ssl_servername_cb(SSL *s, int *ad, void *arg) { tlsextctx *p = (tlsextctx *) arg; const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); @@ -466,7 +257,7 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) return SSL_TLSEXT_ERR_OK; } -# ifndef OPENSSL_NO_SRP +#ifndef OPENSSL_NO_SRP /* This is a context that we pass to all callbacks */ typedef struct srp_arg_st { @@ -475,33 +266,30 @@ typedef struct srp_arg_st { int msg; /* copy from c_msg */ int debug; /* copy from c_debug */ int amp; /* allow more groups */ - int strength /* minimal size for N */ ; + int strength; /* minimal size for N */ } SRP_ARG; -# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64 +# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64 -static int srp_Verify_N_and_g(BIGNUM *N, BIGNUM *g) +static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) { BN_CTX *bn_ctx = BN_CTX_new(); BIGNUM *p = BN_new(); BIGNUM *r = BN_new(); int ret = g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && - BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) && + BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && p != NULL && BN_rshift1(p, N) && /* p = (N-1)/2 */ - BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) && + BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && r != NULL && /* verify g^((N-1)/2) == -1 (mod N) */ BN_mod_exp(r, g, p, N, bn_ctx) && BN_add_word(r, 1) && BN_cmp(r, N) == 0; - if (r) - BN_free(r); - if (p) - BN_free(p); - if (bn_ctx) - BN_CTX_free(bn_ctx); + BN_free(r); + BN_free(p); + BN_CTX_free(bn_ctx); return ret; } @@ -512,7 +300,7 @@ static int srp_Verify_N_and_g(BIGNUM *N, BIGNUM *g) * The callback is only called for a non default group. * * An application does not need the call back at all if - * only the stanard groups are used. In real life situations, + * only the standard groups are used. In real life situations, * client and server already share well known groups, * thus there is no need to verify them. * Furthermore, in case that a server actually proposes a group that @@ -521,11 +309,12 @@ static int srp_Verify_N_and_g(BIGNUM *N, BIGNUM *g) * primality tests are rather cpu consuming. */ -static int MS_CALLBACK ssl_srp_verify_param_cb(SSL *s, void *arg) +static int ssl_srp_verify_param_cb(SSL *s, void *arg) { SRP_ARG *srp_arg = (SRP_ARG *)arg; BIGNUM *N = NULL, *g = NULL; - if (!(N = SSL_get_srp_N(s)) || !(g = SSL_get_srp_g(s))) + + if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL)) return 0; if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) { BIO_printf(bio_err, "SRP parameters:\n"); @@ -556,20 +345,15 @@ static int MS_CALLBACK ssl_srp_verify_param_cb(SSL *s, void *arg) return 0; } -# define PWD_STRLEN 1024 +# define PWD_STRLEN 1024 -static char *MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg) +static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) { SRP_ARG *srp_arg = (SRP_ARG *)arg; - char *pass = (char *)OPENSSL_malloc(PWD_STRLEN + 1); + char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer"); PW_CB_DATA cb_tmp; int l; - if (!pass) { - BIO_printf(bio_err, "Malloc failure\n"); - return NULL; - } - cb_tmp.password = (char *)srp_arg->srppassin; cb_tmp.prompt_info = "SRP user"; if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) { @@ -582,16 +366,13 @@ static char *MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg) return pass; } -# endif -# ifndef OPENSSL_NO_SRTP -char *srtp_profiles = NULL; -# endif +#endif -# ifndef OPENSSL_NO_NEXTPROTONEG +#ifndef OPENSSL_NO_NEXTPROTONEG /* This the context that we pass to next_proto_cb */ typedef struct tlsextnextprotoctx_st { unsigned char *data; - unsigned short len; + size_t len; int status; } tlsextnextprotoctx; @@ -620,7 +401,7 @@ static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len); return SSL_TLSEXT_ERR_OK; } -# endif /* ndef OPENSSL_NO_NEXTPROTONEG */ +#endif /* ndef OPENSSL_NO_NEXTPROTONEG */ static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, @@ -630,7 +411,7 @@ static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type, unsigned char ext_buf[4 + 65536]; /* Reconstruct the type/len fields prior to extension data */ - inlen &= 0xffff; /* for formal memcpy correctness */ + inlen &= 0xffff; /* for formal memcmpy correctness */ ext_buf[0] = (unsigned char)(ext_type >> 8); ext_buf[1] = (unsigned char)(ext_type); ext_buf[2] = (unsigned char)(inlen >> 8); @@ -643,538 +424,1188 @@ static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type, return 1; } +/* + * Hex decoder that tolerates optional whitespace. Returns number of bytes + * produced, advances inptr to end of input string. + */ +static ossl_ssize_t hexdecode(const char **inptr, void *result) +{ + unsigned char **out = (unsigned char **)result; + const char *in = *inptr; + unsigned char *ret = app_malloc(strlen(in) / 2, "hexdecode"); + unsigned char *cp = ret; + uint8_t byte; + int nibble = 0; + + if (ret == NULL) + return -1; + + for (byte = 0; *in; ++in) { + int x; + + if (isspace(_UC(*in))) + continue; + x = OPENSSL_hexchar2int(*in); + if (x < 0) { + OPENSSL_free(ret); + return 0; + } + byte |= (char)x; + if ((nibble ^= 1) == 0) { + *cp++ = byte; + byte = 0; + } else { + byte <<= 4; + } + } + if (nibble != 0) { + OPENSSL_free(ret); + return 0; + } + *inptr = in; + + return cp - (*out = ret); +} + +/* + * Decode unsigned 0..255, returns 1 on success, <= 0 on failure. Advances + * inptr to next field skipping leading whitespace. + */ +static ossl_ssize_t checked_uint8(const char **inptr, void *out) +{ + uint8_t *result = (uint8_t *)out; + const char *in = *inptr; + char *endp; + long v; + int e; + + save_errno(); + v = strtol(in, &endp, 10); + e = restore_errno(); + + if (((v == LONG_MIN || v == LONG_MAX) && e == ERANGE) || + endp == in || !isspace(_UC(*endp)) || + v != (*result = (uint8_t) v)) { + return -1; + } + for (in = endp; isspace(_UC(*in)); ++in) + continue; + + *inptr = in; + return 1; +} + +struct tlsa_field { + void *var; + const char *name; + ossl_ssize_t (*parser)(const char **, void *); +}; + +static int tlsa_import_rr(SSL *con, const char *rrdata) +{ + /* Not necessary to re-init these values; the "parsers" do that. */ + static uint8_t usage; + static uint8_t selector; + static uint8_t mtype; + static unsigned char *data; + static struct tlsa_field tlsa_fields[] = { + { &usage, "usage", checked_uint8 }, + { &selector, "selector", checked_uint8 }, + { &mtype, "mtype", checked_uint8 }, + { &data, "data", hexdecode }, + { NULL, } + }; + struct tlsa_field *f; + int ret; + const char *cp = rrdata; + ossl_ssize_t len = 0; + + for (f = tlsa_fields; f->var; ++f) { + /* Returns number of bytes produced, advances cp to next field */ + if ((len = f->parser(&cp, f->var)) <= 0) { + BIO_printf(bio_err, "%s: warning: bad TLSA %s field in: %s\n", + prog, f->name, rrdata); + return 0; + } + } + /* The data field is last, so len is its length */ + ret = SSL_dane_tlsa_add(con, usage, selector, mtype, data, len); + OPENSSL_free(data); + + if (ret == 0) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "%s: warning: unusable TLSA rrdata: %s\n", + prog, rrdata); + return 0; + } + if (ret < 0) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "%s: warning: error loading TLSA rrdata: %s\n", + prog, rrdata); + return 0; + } + return ret; +} + +static int tlsa_import_rrset(SSL *con, STACK_OF(OPENSSL_STRING) *rrset) +{ + int num = sk_OPENSSL_STRING_num(rrset); + int count = 0; + int i; + + for (i = 0; i < num; ++i) { + char *rrdata = sk_OPENSSL_STRING_value(rrset, i); + if (tlsa_import_rr(con, rrdata) > 0) + ++count; + } + return count > 0; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_BIND, OPT_UNIX, + OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT, + OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN, + OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, + OPT_BRIEF, OPT_PREXIT, OPT_CRLF, OPT_QUIET, OPT_NBIO, + OPT_SSL_CLIENT_ENGINE, OPT_IGN_EOF, OPT_NO_IGN_EOF, + OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_WDEBUG, + OPT_MSG, OPT_MSGFILE, OPT_ENGINE, OPT_TRACE, OPT_SECURITY_DEBUG, + OPT_SECURITY_DEBUG_VERBOSE, OPT_SHOWCERTS, OPT_NBIO_TEST, OPT_STATE, + OPT_PSK_IDENTITY, OPT_PSK, OPT_PSK_SESS, +#ifndef OPENSSL_NO_SRP + OPT_SRPUSER, OPT_SRPPASS, OPT_SRP_STRENGTH, OPT_SRP_LATEUSER, + OPT_SRP_MOREGROUPS, +#endif + OPT_SSL3, OPT_SSL_CONFIG, + OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, + OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS, + OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, + OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, + OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN, + OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC, + OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST, + OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, + OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE, + OPT_V_ENUM, + OPT_X_ENUM, + OPT_S_ENUM, + OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN, +#ifndef OPENSSL_NO_CT + OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, +#endif + OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, + OPT_ENABLE_PHA, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS s_client_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"host", OPT_HOST, 's', "Use -connect instead"}, + {"port", OPT_PORT, 'p', "Use -connect instead"}, + {"connect", OPT_CONNECT, 's', + "TCP/IP where to connect (default is :" PORT ")"}, + {"bind", OPT_BIND, 's', "bind local address for connection"}, + {"proxy", OPT_PROXY, 's', + "Connect to via specified proxy to the real server"}, +#ifdef AF_UNIX + {"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"}, +#endif + {"4", OPT_4, '-', "Use IPv4 only"}, +#ifdef AF_INET6 + {"6", OPT_6, '-', "Use IPv6 only"}, +#endif + {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"}, + {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"}, + {"certform", OPT_CERTFORM, 'F', + "Certificate format (PEM or DER) PEM default"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"key", OPT_KEY, 's', "Private key file to use, if not in -cert file"}, + {"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"}, + {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"requestCAfile", OPT_REQCAFILE, '<', + "PEM format file of CA names to send to the server"}, + {"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"}, + {"dane_tlsa_rrdata", OPT_DANE_TLSA_RRDATA, 's', + "DANE TLSA rrdata presentation form"}, + {"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-', + "Disable name checks when matching DANE-EE(3) TLSA records"}, + {"reconnect", OPT_RECONNECT, '-', + "Drop and re-make the connection with the same Session-ID"}, + {"showcerts", OPT_SHOWCERTS, '-', + "Show all certificates sent by the server"}, + {"debug", OPT_DEBUG, '-', "Extra output"}, + {"msg", OPT_MSG, '-', "Show protocol messages"}, + {"msgfile", OPT_MSGFILE, '>', + "File to send output of -msg or -trace, instead of stdout"}, + {"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"}, + {"state", OPT_STATE, '-', "Print the ssl states"}, + {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"}, + {"quiet", OPT_QUIET, '-', "No s_client output"}, + {"ign_eof", OPT_IGN_EOF, '-', "Ignore input eof (default when -quiet)"}, + {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Don't ignore input eof"}, + {"starttls", OPT_STARTTLS, 's', + "Use the appropriate STARTTLS command before starting TLS"}, + {"xmpphost", OPT_XMPPHOST, 's', + "Alias of -name option for \"-starttls xmpp[-server]\""}, + OPT_R_OPTIONS, + {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"}, + {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"}, +#ifndef OPENSSL_NO_SRTP + {"use_srtp", OPT_USE_SRTP, 's', + "Offer SRTP key management with a colon-separated profile list"}, +#endif + {"keymatexport", OPT_KEYMATEXPORT, 's', + "Export keying material using label"}, + {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', + "Export len bytes of keying material (default 20)"}, + {"maxfraglen", OPT_MAXFRAGLEN, 'p', + "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"}, + {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"}, + {"name", OPT_PROTOHOST, 's', + "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""}, + {"CRL", OPT_CRL, '<', "CRL file to use"}, + {"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"}, + {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"}, + {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', + "Close connection on verification error"}, + {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"}, + {"brief", OPT_BRIEF, '-', + "Restrict output to brief summary of connection parameters"}, + {"prexit", OPT_PREXIT, '-', + "Print session information when the program exits"}, + {"security_debug", OPT_SECURITY_DEBUG, '-', + "Enable security debug messages"}, + {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-', + "Output more security debug output"}, + {"cert_chain", OPT_CERT_CHAIN, '<', + "Certificate chain file (in PEM format)"}, + {"chainCApath", OPT_CHAINCAPATH, '/', + "Use dir as certificate store path to build CA certificate chain"}, + {"verifyCApath", OPT_VERIFYCAPATH, '/', + "Use dir as certificate store path to verify CA certificate"}, + {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"}, + {"chainCAfile", OPT_CHAINCAFILE, '<', + "CA file for certificate chain (PEM format)"}, + {"verifyCAfile", OPT_VERIFYCAFILE, '<', + "CA file for certificate verification (PEM format)"}, + {"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"}, + {"servername", OPT_SERVERNAME, 's', + "Set TLS extension servername (SNI) in ClientHello (default)"}, + {"noservername", OPT_NOSERVERNAME, '-', + "Do not send the server name (SNI) extension in the ClientHello"}, + {"tlsextdebug", OPT_TLSEXTDEBUG, '-', + "Hex dump of all TLS extensions received"}, +#ifndef OPENSSL_NO_OCSP + {"status", OPT_STATUS, '-', "Request certificate status from server"}, +#endif + {"serverinfo", OPT_SERVERINFO, 's', + "types Send empty ClientHello extensions (comma-separated numbers)"}, + {"alpn", OPT_ALPN, 's', + "Enable ALPN extension, considering named protocols supported (comma-separated list)"}, + {"async", OPT_ASYNC, '-', "Support asynchronous operation"}, + {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified configuration file"}, + {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, + {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', + "Size used to split data for encrypt pipelines"}, + {"max_pipelines", OPT_MAX_PIPELINES, 'p', + "Maximum number of encrypt/decrypt pipelines to be used"}, + {"read_buf", OPT_READ_BUF, 'p', + "Default read buffer size to be used for connections"}, + OPT_S_OPTIONS, + OPT_V_OPTIONS, + OPT_X_OPTIONS, +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "Just use SSLv3"}, #endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "Just use TLSv1"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"}, +#endif +#ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"}, +#endif +#ifndef OPENSSL_NO_DTLS + {"dtls", OPT_DTLS, '-', "Use any version of DTLS"}, + {"timeout", OPT_TIMEOUT, '-', + "Enable send/receive timeout on DTLS connections"}, + {"mtu", OPT_MTU, 'p', "Set the link layer MTU"}, +#endif +#ifndef OPENSSL_NO_DTLS1 + {"dtls1", OPT_DTLS1, '-', "Just use DTLSv1"}, +#endif +#ifndef OPENSSL_NO_DTLS1_2 + {"dtls1_2", OPT_DTLS1_2, '-', "Just use DTLSv1.2"}, +#endif +#ifndef OPENSSL_NO_SCTP + {"sctp", OPT_SCTP, '-', "Use SCTP"}, +#endif +#ifndef OPENSSL_NO_SSL_TRACE + {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"}, +#endif +#ifdef WATT32 + {"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"}, +#endif + {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, + {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"}, + {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, + {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, +#ifndef OPENSSL_NO_SRP + {"srpuser", OPT_SRPUSER, 's', "SRP authentication for 'user'"}, + {"srppass", OPT_SRPPASS, 's', "Password for 'user'"}, + {"srp_lateuser", OPT_SRP_LATEUSER, '-', + "SRP username into second ClientHello message"}, + {"srp_moregroups", OPT_SRP_MOREGROUPS, '-', + "Tolerate other than the known g N values."}, + {"srp_strength", OPT_SRP_STRENGTH, 'p', "Minimal length in bits for N"}, +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + {"nextprotoneg", OPT_NEXTPROTONEG, 's', + "Enable NPN extension, considering named protocols supported (comma-separated list)"}, +#endif +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's', + "Specify engine to be used for client certificate operations"}, +#endif +#ifndef OPENSSL_NO_CT + {"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"}, + {"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"}, + {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"}, +#endif + {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, + {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"}, + {"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"}, + {NULL, OPT_EOF, 0x00, NULL} +}; -enum { - PROTO_OFF = 0, +typedef enum PROTOCOL_choice { + PROTO_OFF, PROTO_SMTP, PROTO_POP3, PROTO_IMAP, PROTO_FTP, - PROTO_XMPP + PROTO_TELNET, + PROTO_XMPP, + PROTO_XMPP_SERVER, + PROTO_CONNECT, + PROTO_IRC, + PROTO_MYSQL, + PROTO_POSTGRES, + PROTO_LMTP, + PROTO_NNTP, + PROTO_SIEVE, + PROTO_LDAP +} PROTOCOL_CHOICE; + +static const OPT_PAIR services[] = { + {"smtp", PROTO_SMTP}, + {"pop3", PROTO_POP3}, + {"imap", PROTO_IMAP}, + {"ftp", PROTO_FTP}, + {"xmpp", PROTO_XMPP}, + {"xmpp-server", PROTO_XMPP_SERVER}, + {"telnet", PROTO_TELNET}, + {"irc", PROTO_IRC}, + {"mysql", PROTO_MYSQL}, + {"postgres", PROTO_POSTGRES}, + {"lmtp", PROTO_LMTP}, + {"nntp", PROTO_NNTP}, + {"sieve", PROTO_SIEVE}, + {"ldap", PROTO_LDAP}, + {NULL, 0} }; -int MAIN(int, char **); +#define IS_INET_FLAG(o) \ + (o == OPT_4 || o == OPT_6 || o == OPT_HOST || o == OPT_PORT || o == OPT_CONNECT) +#define IS_UNIX_FLAG(o) (o == OPT_UNIX) -int MAIN(int argc, char **argv) +#define IS_PROT_FLAG(o) \ + (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \ + || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2) + +/* Free |*dest| and optionally set it to a copy of |source|. */ +static void freeandcopy(char **dest, const char *source) { - int build_chain = 0; - SSL *con = NULL; -#ifndef OPENSSL_NO_KRB5 - KSSL_CTX *kctx; -#endif - int s, k, width, state = 0; - char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL; - int cbuf_len, cbuf_off; - int sbuf_len, sbuf_off; - fd_set readfds, writefds; - short port = PORT; - int full_log = 1; - char *host = SSL_HOST_NAME; - char *cert_file = NULL, *key_file = NULL, *chain_file = NULL; - int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; - char *passarg = NULL, *pass = NULL; - X509 *cert = NULL; + OPENSSL_free(*dest); + *dest = NULL; + if (source != NULL) + *dest = OPENSSL_strdup(source); +} + +static int new_session_cb(SSL *s, SSL_SESSION *sess) +{ + + if (sess_out != NULL) { + BIO *stmp = BIO_new_file(sess_out, "w"); + + if (stmp == NULL) { + BIO_printf(bio_err, "Error writing session file %s\n", sess_out); + } else { + PEM_write_bio_SSL_SESSION(stmp, sess); + BIO_free(stmp); + } + } + + /* + * Session data gets dumped on connection for TLSv1.2 and below, and on + * arrival of the NewSessionTicket for TLSv1.3. + */ + if (SSL_version(s) == TLS1_3_VERSION) { + BIO_printf(bio_c_out, + "---\nPost-Handshake New Session Ticket arrived:\n"); + SSL_SESSION_print(bio_c_out, sess); + BIO_printf(bio_c_out, "---\n"); + } + + /* + * We always return a "fail" response so that the session gets freed again + * because we haven't used the reference. + */ + return 0; +} + +int s_client_main(int argc, char **argv) +{ + BIO *sbio; EVP_PKEY *key = NULL; - STACK_OF(X509) *chain = NULL; - char *CApath = NULL, *CAfile = NULL; - char *chCApath = NULL, *chCAfile = NULL; - char *vfyCApath = NULL, *vfyCAfile = NULL; - int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE; - int crlf = 0; - int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; + SSL *con = NULL; SSL_CTX *ctx = NULL; - int ret = 1, in_init = 1, i, nbio_test = 0; - int starttls_proto = PROTO_OFF; - int prexit = 0; + STACK_OF(X509) *chain = NULL; + X509 *cert = NULL; X509_VERIFY_PARAM *vpm = NULL; - int badarg = 0; - const SSL_METHOD *meth = NULL; - int socket_type = SOCK_STREAM; - BIO *sbio; - char *inrand = NULL; - int mbuf_len = 0; + SSL_EXCERT *exc = NULL; + SSL_CONF_CTX *cctx = NULL; + STACK_OF(OPENSSL_STRING) *ssl_args = NULL; + char *dane_tlsa_domain = NULL; + STACK_OF(OPENSSL_STRING) *dane_tlsa_rrset = NULL; + int dane_ee_no_name = 0; + STACK_OF(X509_CRL) *crls = NULL; + const SSL_METHOD *meth = TLS_client_method(); + const char *CApath = NULL, *CAfile = NULL; + char *cbuf = NULL, *sbuf = NULL; + char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL; + char *cert_file = NULL, *key_file = NULL, *chain_file = NULL; + char *chCApath = NULL, *chCAfile = NULL, *host = NULL; + char *port = OPENSSL_strdup(PORT); + char *bindhost = NULL, *bindport = NULL; + char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; + char *ReqCAfile = NULL; + char *sess_in = NULL, *crl_file = NULL, *p; + const char *protohost = NULL; struct timeval timeout, *timeoutp; - char *engine_id = NULL; - ENGINE *e = NULL; + fd_set readfds, writefds; + int noCApath = 0, noCAfile = 0; + int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_PEM; + int key_format = FORMAT_PEM, crlf = 0, full_log = 1, mbuf_len = 0; + int prexit = 0; + int sdebug = 0; + int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0; + int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0; + int sbuf_len, sbuf_off, cmdletters = 1; + int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; + int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0; + int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) + int at_eof = 0; +#endif + int read_buf_len = 0; + int fallback_scsv = 0; + OPTION_CHOICE o; +#ifndef OPENSSL_NO_DTLS + int enable_timeouts = 0; + long socket_mtu = 0; +#endif #ifndef OPENSSL_NO_ENGINE - char *ssl_client_engine_id = NULL; ENGINE *ssl_client_engine = NULL; #endif -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) + ENGINE *e = NULL; +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) struct timeval tv; -# if defined(OPENSSL_SYS_BEOS_R5) - int stdin_set = 0; -# endif #endif -#ifndef OPENSSL_NO_TLSEXT - char *servername = NULL; - tlsextctx tlsextcbp = { NULL, 0 }; -# ifndef OPENSSL_NO_NEXTPROTONEG - const char *next_proto_neg_in = NULL; -# endif + const char *servername = NULL; + int noservername = 0; const char *alpn_in = NULL; -# define MAX_SI_TYPES 100 + tlsextctx tlsextcbp = { NULL, 0 }; + const char *ssl_config = NULL; +#define MAX_SI_TYPES 100 unsigned short serverinfo_types[MAX_SI_TYPES]; - int serverinfo_types_count = 0; -#endif - char *sess_in = NULL; - char *sess_out = NULL; - struct sockaddr peer; - int peerlen = sizeof(peer); - int fallback_scsv = 0; - int enable_timeouts = 0; - long socket_mtu = 0; -#ifndef OPENSSL_NO_JPAKE - static char *jpake_secret = NULL; -# define no_jpake !jpake_secret -#else -# define no_jpake 1 + int serverinfo_count = 0, start = 0, len; +#ifndef OPENSSL_NO_NEXTPROTONEG + const char *next_proto_neg_in = NULL; #endif #ifndef OPENSSL_NO_SRP char *srppass = NULL; int srp_lateuser = 0; SRP_ARG srp_arg = { NULL, NULL, 0, 0, 0, 1024 }; #endif - SSL_EXCERT *exc = NULL; - - SSL_CONF_CTX *cctx = NULL; - STACK_OF(OPENSSL_STRING) *ssl_args = NULL; - - char *crl_file = NULL; - int crl_format = FORMAT_PEM; - int crl_download = 0; - STACK_OF(X509_CRL) *crls = NULL; - int prot_opt = 0, no_prot_opt = 0; +#ifndef OPENSSL_NO_SRTP + char *srtp_profiles = NULL; +#endif +#ifndef OPENSSL_NO_CT + char *ctlog_file = NULL; + int ct_validation = 0; +#endif + int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0; + int async = 0; + unsigned int max_send_fragment = 0; + unsigned int split_send_fragment = 0, max_pipelines = 0; + enum { use_inet, use_unix, use_unknown } connect_type = use_unknown; + int count4or6 = 0; + uint8_t maxfraglen = 0; + int c_nbio = 0, c_msg = 0, c_ign_eof = 0, c_brief = 0; + int c_tlsextdebug = 0; +#ifndef OPENSSL_NO_OCSP + int c_status_req = 0; +#endif + BIO *bio_c_msg = NULL; + const char *keylog_file = NULL, *early_data_file = NULL; +#ifndef OPENSSL_NO_DTLS + int isdtls = 0; +#endif + char *psksessf = NULL; + int enable_pha = 0; - meth = SSLv23_client_method(); + FD_ZERO(&readfds); + FD_ZERO(&writefds); +/* Known false-positive of MemorySanitizer. */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(&readfds, sizeof(readfds)); + __msan_unpoison(&writefds, sizeof(writefds)); +# endif +#endif - apps_startup(); - c_Pause = 0; + prog = opt_progname(argv[0]); c_quiet = 0; - c_ign_eof = 0; c_debug = 0; - c_msg = 0; c_showcerts = 0; - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - + c_nbio = 0; + vpm = X509_VERIFY_PARAM_new(); cctx = SSL_CONF_CTX_new(); - if (!cctx) - goto end; - SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT); - SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CMDLINE); - if (((cbuf = OPENSSL_malloc(BUFSIZZ)) == NULL) || - ((sbuf = OPENSSL_malloc(BUFSIZZ)) == NULL) || - ((mbuf = OPENSSL_malloc(BUFSIZZ)) == NULL)) { - BIO_printf(bio_err, "out of memory\n"); + if (vpm == NULL || cctx == NULL) { + BIO_printf(bio_err, "%s: out of memory\n", prog); goto end; } - verify_depth = 0; - verify_error = X509_V_OK; -#ifdef FIONBIO - c_nbio = 0; -#endif + cbuf = app_malloc(BUFSIZZ, "cbuf"); + sbuf = app_malloc(BUFSIZZ, "sbuf"); + mbuf = app_malloc(BUFSIZZ, "mbuf"); + + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT | SSL_CONF_FLAG_CMDLINE); + + prog = opt_init(argc, argv, s_client_options); + while ((o = opt_next()) != OPT_EOF) { + /* Check for intermixing flags. */ + if (connect_type == use_unix && IS_INET_FLAG(o)) { + BIO_printf(bio_err, + "%s: Intermixed protocol flags (unix and internet domains)\n", + prog); + goto end; + } + if (connect_type == use_inet && IS_UNIX_FLAG(o)) { + BIO_printf(bio_err, + "%s: Intermixed protocol flags (internet and unix domains)\n", + prog); + goto end; + } + + if (IS_PROT_FLAG(o) && ++prot_opt > 1) { + BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); + goto end; + } + if (IS_NO_PROT_FLAG(o)) + no_prot_opt++; + if (prot_opt == 1 && no_prot_opt) { + BIO_printf(bio_err, + "Cannot supply both a protocol flag and '-no_<prot>'\n"); + goto end; + } - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-host") == 0) { - if (--argc < 1) - goto bad; - host = *(++argv); - } else if (strcmp(*argv, "-port") == 0) { - if (--argc < 1) - goto bad; - port = atoi(*(++argv)); - if (port == 0) - goto bad; - } else if (strcmp(*argv, "-connect") == 0) { - if (--argc < 1) - goto bad; - if (!extract_host_port(*(++argv), &host, NULL, &port)) - goto bad; - } else if (strcmp(*argv, "-verify") == 0) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(s_client_options); + ret = 0; + goto end; + case OPT_4: + connect_type = use_inet; + socket_family = AF_INET; + count4or6++; + break; +#ifdef AF_INET6 + case OPT_6: + connect_type = use_inet; + socket_family = AF_INET6; + count4or6++; + break; +#endif + case OPT_HOST: + connect_type = use_inet; + freeandcopy(&host, opt_arg()); + break; + case OPT_PORT: + connect_type = use_inet; + freeandcopy(&port, opt_arg()); + break; + case OPT_CONNECT: + connect_type = use_inet; + freeandcopy(&connectstr, opt_arg()); + break; + case OPT_BIND: + freeandcopy(&bindstr, opt_arg()); + break; + case OPT_PROXY: + proxystr = opt_arg(); + starttls_proto = PROTO_CONNECT; + break; +#ifdef AF_UNIX + case OPT_UNIX: + connect_type = use_unix; + socket_family = AF_UNIX; + freeandcopy(&host, opt_arg()); + break; +#endif + case OPT_XMPPHOST: + /* fall through, since this is an alias */ + case OPT_PROTOHOST: + protohost = opt_arg(); + break; + case OPT_VERIFY: verify = SSL_VERIFY_PEER; - if (--argc < 1) - goto bad; - verify_depth = atoi(*(++argv)); + verify_args.depth = atoi(opt_arg()); if (!c_quiet) - BIO_printf(bio_err, "verify depth is %d\n", verify_depth); - } else if (strcmp(*argv, "-cert") == 0) { - if (--argc < 1) - goto bad; - cert_file = *(++argv); - } else if (strcmp(*argv, "-CRL") == 0) { - if (--argc < 1) - goto bad; - crl_file = *(++argv); - } else if (strcmp(*argv, "-crl_download") == 0) + BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth); + break; + case OPT_CERT: + cert_file = opt_arg(); + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_CRL: + crl_file = opt_arg(); + break; + case OPT_CRL_DOWNLOAD: crl_download = 1; - else if (strcmp(*argv, "-sess_out") == 0) { - if (--argc < 1) - goto bad; - sess_out = *(++argv); - } else if (strcmp(*argv, "-sess_in") == 0) { - if (--argc < 1) - goto bad; - sess_in = *(++argv); - } else if (strcmp(*argv, "-certform") == 0) { - if (--argc < 1) - goto bad; - cert_format = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-CRLform") == 0) { - if (--argc < 1) - goto bad; - crl_format = str2fmt(*(++argv)); - } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { - if (badarg) - goto bad; - continue; - } else if (strcmp(*argv, "-verify_return_error") == 0) - verify_return_error = 1; - else if (strcmp(*argv, "-verify_quiet") == 0) - verify_quiet = 1; - else if (strcmp(*argv, "-brief") == 0) { - c_brief = 1; - verify_quiet = 1; - c_quiet = 1; - } else if (args_excert(&argv, &argc, &badarg, bio_err, &exc)) { - if (badarg) - goto bad; - continue; - } else if (args_ssl(&argv, &argc, cctx, &badarg, bio_err, &ssl_args, - &no_prot_opt)) { - if (badarg) - goto bad; - continue; - } else if (strcmp(*argv, "-prexit") == 0) + break; + case OPT_SESS_OUT: + sess_out = opt_arg(); + break; + case OPT_SESS_IN: + sess_in = opt_arg(); + break; + case OPT_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format)) + goto opthelp; + break; + case OPT_CRLFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format)) + goto opthelp; + break; + case OPT_VERIFY_RET_ERROR: + verify_args.return_error = 1; + break; + case OPT_VERIFY_QUIET: + verify_args.quiet = 1; + break; + case OPT_BRIEF: + c_brief = verify_args.quiet = c_quiet = 1; + break; + case OPT_S_CASES: + if (ssl_args == NULL) + ssl_args = sk_OPENSSL_STRING_new_null(); + if (ssl_args == NULL + || !sk_OPENSSL_STRING_push(ssl_args, opt_flag()) + || !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_X_CASES: + if (!args_excert(o, &exc)) + goto end; + break; + case OPT_PREXIT: prexit = 1; - else if (strcmp(*argv, "-crlf") == 0) + break; + case OPT_CRLF: crlf = 1; - else if (strcmp(*argv, "-quiet") == 0) { - c_quiet = 1; - c_ign_eof = 1; - } else if (strcmp(*argv, "-ign_eof") == 0) + break; + case OPT_QUIET: + c_quiet = c_ign_eof = 1; + break; + case OPT_NBIO: + c_nbio = 1; + break; + case OPT_NOCMDS: + cmdletters = 0; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 1); + break; + case OPT_SSL_CLIENT_ENGINE: +#ifndef OPENSSL_NO_ENGINE + ssl_client_engine = ENGINE_by_id(opt_arg()); + if (ssl_client_engine == NULL) { + BIO_printf(bio_err, "Error getting client auth engine\n"); + goto opthelp; + } +#endif + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_IGN_EOF: c_ign_eof = 1; - else if (strcmp(*argv, "-no_ign_eof") == 0) + break; + case OPT_NO_IGN_EOF: c_ign_eof = 0; - else if (strcmp(*argv, "-pause") == 0) - c_Pause = 1; - else if (strcmp(*argv, "-debug") == 0) + break; + case OPT_DEBUG: c_debug = 1; -#ifndef OPENSSL_NO_TLSEXT - else if (strcmp(*argv, "-tlsextdebug") == 0) + break; + case OPT_TLSEXTDEBUG: c_tlsextdebug = 1; - else if (strcmp(*argv, "-status") == 0) + break; + case OPT_STATUS: +#ifndef OPENSSL_NO_OCSP c_status_req = 1; #endif + break; + case OPT_WDEBUG: #ifdef WATT32 - else if (strcmp(*argv, "-wdebug") == 0) dbug_init(); #endif - else if (strcmp(*argv, "-msg") == 0) + break; + case OPT_MSG: c_msg = 1; - else if (strcmp(*argv, "-msgfile") == 0) { - if (--argc < 1) - goto bad; - bio_c_msg = BIO_new_file(*(++argv), "w"); - } + break; + case OPT_MSGFILE: + bio_c_msg = BIO_new_file(opt_arg(), "w"); + break; + case OPT_TRACE: #ifndef OPENSSL_NO_SSL_TRACE - else if (strcmp(*argv, "-trace") == 0) c_msg = 2; #endif - else if (strcmp(*argv, "-showcerts") == 0) + break; + case OPT_SECURITY_DEBUG: + sdebug = 1; + break; + case OPT_SECURITY_DEBUG_VERBOSE: + sdebug = 2; + break; + case OPT_SHOWCERTS: c_showcerts = 1; - else if (strcmp(*argv, "-nbio_test") == 0) + break; + case OPT_NBIO_TEST: nbio_test = 1; - else if (strcmp(*argv, "-state") == 0) + break; + case OPT_STATE: state = 1; -#ifndef OPENSSL_NO_PSK - else if (strcmp(*argv, "-psk_identity") == 0) { - if (--argc < 1) - goto bad; - psk_identity = *(++argv); - } else if (strcmp(*argv, "-psk") == 0) { - size_t j; - - if (--argc < 1) - goto bad; - psk_key = *(++argv); - for (j = 0; j < strlen(psk_key); j++) { - if (isxdigit((unsigned char)psk_key[j])) + break; + case OPT_PSK_IDENTITY: + psk_identity = opt_arg(); + break; + case OPT_PSK: + for (p = psk_key = opt_arg(); *p; p++) { + if (isxdigit(_UC(*p))) continue; - BIO_printf(bio_err, "Not a hex number '%s'\n", *argv); - goto bad; + BIO_printf(bio_err, "Not a hex number '%s'\n", psk_key); + goto end; } - } -#endif + break; + case OPT_PSK_SESS: + psksessf = opt_arg(); + break; #ifndef OPENSSL_NO_SRP - else if (strcmp(*argv, "-srpuser") == 0) { - if (--argc < 1) - goto bad; - srp_arg.srplogin = *(++argv); - meth = TLSv1_client_method(); - } else if (strcmp(*argv, "-srppass") == 0) { - if (--argc < 1) - goto bad; - srppass = *(++argv); - meth = TLSv1_client_method(); - } else if (strcmp(*argv, "-srp_strength") == 0) { - if (--argc < 1) - goto bad; - srp_arg.strength = atoi(*(++argv)); + case OPT_SRPUSER: + srp_arg.srplogin = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRPPASS: + srppass = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRP_STRENGTH: + srp_arg.strength = atoi(opt_arg()); BIO_printf(bio_err, "SRP minimal length for N is %d\n", srp_arg.strength); - meth = TLSv1_client_method(); - } else if (strcmp(*argv, "-srp_lateuser") == 0) { + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRP_LATEUSER: srp_lateuser = 1; - meth = TLSv1_client_method(); - } else if (strcmp(*argv, "-srp_moregroups") == 0) { + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRP_MOREGROUPS: srp_arg.amp = 1; - meth = TLSv1_client_method(); - } -#endif -#ifndef OPENSSL_NO_SSL2 - else if (strcmp(*argv, "-ssl2") == 0) { - meth = SSLv2_client_method(); - prot_opt++; - } -#endif -#ifndef OPENSSL_NO_SSL3_METHOD - else if (strcmp(*argv, "-ssl3") == 0) { - meth = SSLv3_client_method(); - prot_opt++; - } + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; #endif -#ifndef OPENSSL_NO_TLS1 - else if (strcmp(*argv, "-tls1_2") == 0) { - meth = TLSv1_2_client_method(); - prot_opt++; - } else if (strcmp(*argv, "-tls1_1") == 0) { - meth = TLSv1_1_client_method(); - prot_opt++; - } else if (strcmp(*argv, "-tls1") == 0) { - meth = TLSv1_client_method(); - prot_opt++; - } + case OPT_SSL_CONFIG: + ssl_config = opt_arg(); + break; + case OPT_SSL3: + min_version = SSL3_VERSION; + max_version = SSL3_VERSION; + break; + case OPT_TLS1_3: + min_version = TLS1_3_VERSION; + max_version = TLS1_3_VERSION; + break; + case OPT_TLS1_2: + min_version = TLS1_2_VERSION; + max_version = TLS1_2_VERSION; + break; + case OPT_TLS1_1: + min_version = TLS1_1_VERSION; + max_version = TLS1_1_VERSION; + break; + case OPT_TLS1: + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + break; + case OPT_DTLS: +#ifndef OPENSSL_NO_DTLS + meth = DTLS_client_method(); + socket_type = SOCK_DGRAM; + isdtls = 1; #endif + break; + case OPT_DTLS1: #ifndef OPENSSL_NO_DTLS1 - else if (strcmp(*argv, "-dtls") == 0) { meth = DTLS_client_method(); + min_version = DTLS1_VERSION; + max_version = DTLS1_VERSION; socket_type = SOCK_DGRAM; - prot_opt++; - } else if (strcmp(*argv, "-dtls1") == 0) { - meth = DTLSv1_client_method(); - socket_type = SOCK_DGRAM; - prot_opt++; - } else if (strcmp(*argv, "-dtls1_2") == 0) { - meth = DTLSv1_2_client_method(); + isdtls = 1; +#endif + break; + case OPT_DTLS1_2: +#ifndef OPENSSL_NO_DTLS1_2 + meth = DTLS_client_method(); + min_version = DTLS1_2_VERSION; + max_version = DTLS1_2_VERSION; socket_type = SOCK_DGRAM; - prot_opt++; - } else if (strcmp(*argv, "-timeout") == 0) + isdtls = 1; +#endif + break; + case OPT_SCTP: +#ifndef OPENSSL_NO_SCTP + protocol = IPPROTO_SCTP; +#endif + break; + case OPT_TIMEOUT: +#ifndef OPENSSL_NO_DTLS enable_timeouts = 1; - else if (strcmp(*argv, "-mtu") == 0) { - if (--argc < 1) - goto bad; - socket_mtu = atol(*(++argv)); - } #endif - else if (strcmp(*argv, "-fallback_scsv") == 0) { + break; + case OPT_MTU: +#ifndef OPENSSL_NO_DTLS + socket_mtu = atol(opt_arg()); +#endif + break; + case OPT_FALLBACKSCSV: fallback_scsv = 1; - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - goto bad; - key_format = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-pass") == 0) { - if (--argc < 1) - goto bad; - passarg = *(++argv); - } else if (strcmp(*argv, "-cert_chain") == 0) { - if (--argc < 1) - goto bad; - chain_file = *(++argv); - } else if (strcmp(*argv, "-key") == 0) { - if (--argc < 1) - goto bad; - key_file = *(++argv); - } else if (strcmp(*argv, "-reconnect") == 0) { + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format)) + goto opthelp; + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_CERT_CHAIN: + chain_file = opt_arg(); + break; + case OPT_KEY: + key_file = opt_arg(); + break; + case OPT_RECONNECT: reconnect = 5; - } else if (strcmp(*argv, "-CApath") == 0) { - if (--argc < 1) - goto bad; - CApath = *(++argv); - } else if (strcmp(*argv, "-chainCApath") == 0) { - if (--argc < 1) - goto bad; - chCApath = *(++argv); - } else if (strcmp(*argv, "-verifyCApath") == 0) { - if (--argc < 1) - goto bad; - vfyCApath = *(++argv); - } else if (strcmp(*argv, "-build_chain") == 0) + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_CHAINCAPATH: + chCApath = opt_arg(); + break; + case OPT_VERIFYCAPATH: + vfyCApath = opt_arg(); + break; + case OPT_BUILD_CHAIN: build_chain = 1; - else if (strcmp(*argv, "-CAfile") == 0) { - if (--argc < 1) - goto bad; - CAfile = *(++argv); - } else if (strcmp(*argv, "-chainCAfile") == 0) { - if (--argc < 1) - goto bad; - chCAfile = *(++argv); - } else if (strcmp(*argv, "-verifyCAfile") == 0) { - if (--argc < 1) - goto bad; - vfyCAfile = *(++argv); - } -#ifndef OPENSSL_NO_TLSEXT -# ifndef OPENSSL_NO_NEXTPROTONEG - else if (strcmp(*argv, "-nextprotoneg") == 0) { - if (--argc < 1) - goto bad; - next_proto_neg_in = *(++argv); - } -# endif - else if (strcmp(*argv, "-alpn") == 0) { - if (--argc < 1) - goto bad; - alpn_in = *(++argv); - } else if (strcmp(*argv, "-serverinfo") == 0) { - char *c; - int start = 0; - int len; - - if (--argc < 1) - goto bad; - c = *(++argv); - serverinfo_types_count = 0; - len = strlen(c); - for (i = 0; i <= len; ++i) { - if (i == len || c[i] == ',') { - serverinfo_types[serverinfo_types_count] - = atoi(c + start); - serverinfo_types_count++; + break; + case OPT_REQCAFILE: + ReqCAfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; +#ifndef OPENSSL_NO_CT + case OPT_NOCT: + ct_validation = 0; + break; + case OPT_CT: + ct_validation = 1; + break; + case OPT_CTLOG_FILE: + ctlog_file = opt_arg(); + break; +#endif + case OPT_CHAINCAFILE: + chCAfile = opt_arg(); + break; + case OPT_VERIFYCAFILE: + vfyCAfile = opt_arg(); + break; + case OPT_DANE_TLSA_DOMAIN: + dane_tlsa_domain = opt_arg(); + break; + case OPT_DANE_TLSA_RRDATA: + if (dane_tlsa_rrset == NULL) + dane_tlsa_rrset = sk_OPENSSL_STRING_new_null(); + if (dane_tlsa_rrset == NULL || + !sk_OPENSSL_STRING_push(dane_tlsa_rrset, opt_arg())) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + break; + case OPT_DANE_EE_NO_NAME: + dane_ee_no_name = 1; + break; + case OPT_NEXTPROTONEG: +#ifndef OPENSSL_NO_NEXTPROTONEG + next_proto_neg_in = opt_arg(); +#endif + break; + case OPT_ALPN: + alpn_in = opt_arg(); + break; + case OPT_SERVERINFO: + p = opt_arg(); + len = strlen(p); + for (start = 0, i = 0; i <= len; ++i) { + if (i == len || p[i] == ',') { + serverinfo_types[serverinfo_count] = atoi(p + start); + if (++serverinfo_count == MAX_SI_TYPES) + break; start = i + 1; } - if (serverinfo_types_count == MAX_SI_TYPES) - break; } - } -#endif -#ifdef FIONBIO - else if (strcmp(*argv, "-nbio") == 0) { - c_nbio = 1; - } + break; + case OPT_STARTTLS: + if (!opt_pair(opt_arg(), services, &starttls_proto)) + goto end; + break; + case OPT_SERVERNAME: + servername = opt_arg(); + break; + case OPT_NOSERVERNAME: + noservername = 1; + break; + case OPT_USE_SRTP: +#ifndef OPENSSL_NO_SRTP + srtp_profiles = opt_arg(); #endif - else if (strcmp(*argv, "-starttls") == 0) { - if (--argc < 1) - goto bad; - ++argv; - if (strcmp(*argv, "smtp") == 0) - starttls_proto = PROTO_SMTP; - else if (strcmp(*argv, "pop3") == 0) - starttls_proto = PROTO_POP3; - else if (strcmp(*argv, "imap") == 0) - starttls_proto = PROTO_IMAP; - else if (strcmp(*argv, "ftp") == 0) - starttls_proto = PROTO_FTP; - else if (strcmp(*argv, "xmpp") == 0) - starttls_proto = PROTO_XMPP; - else - goto bad; + break; + case OPT_KEYMATEXPORT: + keymatexportlabel = opt_arg(); + break; + case OPT_KEYMATEXPORTLEN: + keymatexportlen = atoi(opt_arg()); + break; + case OPT_ASYNC: + async = 1; + break; + case OPT_MAXFRAGLEN: + len = atoi(opt_arg()); + switch (len) { + case 512: + maxfraglen = TLSEXT_max_fragment_length_512; + break; + case 1024: + maxfraglen = TLSEXT_max_fragment_length_1024; + break; + case 2048: + maxfraglen = TLSEXT_max_fragment_length_2048; + break; + case 4096: + maxfraglen = TLSEXT_max_fragment_length_4096; + break; + default: + BIO_printf(bio_err, + "%s: Max Fragment Len %u is out of permitted values", + prog, len); + goto opthelp; + } + break; + case OPT_MAX_SEND_FRAG: + max_send_fragment = atoi(opt_arg()); + break; + case OPT_SPLIT_SEND_FRAG: + split_send_fragment = atoi(opt_arg()); + break; + case OPT_MAX_PIPELINES: + max_pipelines = atoi(opt_arg()); + break; + case OPT_READ_BUF: + read_buf_len = atoi(opt_arg()); + break; + case OPT_KEYLOG_FILE: + keylog_file = opt_arg(); + break; + case OPT_EARLY_DATA: + early_data_file = opt_arg(); + break; + case OPT_ENABLE_PHA: + enable_pha = 1; + break; } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine_id = *(++argv); - } else if (strcmp(*argv, "-ssl_client_engine") == 0) { - if (--argc < 1) - goto bad; - ssl_client_engine_id = *(++argv); + } + if (count4or6 >= 2) { + BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog); + goto opthelp; + } + if (noservername) { + if (servername != NULL) { + BIO_printf(bio_err, + "%s: Can't use -servername and -noservername together\n", + prog); + goto opthelp; } -#endif - else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); + if (dane_tlsa_domain != NULL) { + BIO_printf(bio_err, + "%s: Can't use -dane_tlsa_domain and -noservername together\n", + prog); + goto opthelp; } -#ifndef OPENSSL_NO_TLSEXT - else if (strcmp(*argv, "-servername") == 0) { - if (--argc < 1) - goto bad; - servername = *(++argv); - /* meth=TLSv1_client_method(); */ + } + argc = opt_num_rest(); + if (argc == 1) { + /* If there's a positional argument, it's the equivalent of + * OPT_CONNECT. + * Don't allow -connect and a separate argument. + */ + if (connectstr != NULL) { + BIO_printf(bio_err, + "%s: must not provide both -connect option and target parameter\n", + prog); + goto opthelp; } + connect_type = use_inet; + freeandcopy(&connectstr, *opt_rest()); + } else if (argc != 0) { + goto opthelp; + } + +#ifndef OPENSSL_NO_NEXTPROTONEG + if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { + BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n"); + goto opthelp; + } #endif -#ifndef OPENSSL_NO_JPAKE - else if (strcmp(*argv, "-jpake") == 0) { - if (--argc < 1) - goto bad; - jpake_secret = *++argv; + if (proxystr != NULL) { + int res; + char *tmp_host = host, *tmp_port = port; + if (connectstr == NULL) { + BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog); + goto opthelp; } -#endif -#ifndef OPENSSL_NO_SRTP - else if (strcmp(*argv, "-use_srtp") == 0) { - if (--argc < 1) - goto bad; - srtp_profiles = *(++argv); + res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST); + if (tmp_host != host) + OPENSSL_free(tmp_host); + if (tmp_port != port) + OPENSSL_free(tmp_port); + if (!res) { + BIO_printf(bio_err, + "%s: -proxy argument malformed or ambiguous\n", prog); + goto end; } -#endif - else if (strcmp(*argv, "-keymatexport") == 0) { - if (--argc < 1) - goto bad; - keymatexportlabel = *(++argv); - } else if (strcmp(*argv, "-keymatexportlen") == 0) { - if (--argc < 1) - goto bad; - keymatexportlen = atoi(*(++argv)); - if (keymatexportlen == 0) - goto bad; - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badop = 1; - break; + } else { + int res = 1; + char *tmp_host = host, *tmp_port = port; + if (connectstr != NULL) + res = BIO_parse_hostserv(connectstr, &host, &port, + BIO_PARSE_PRIO_HOST); + if (tmp_host != host) + OPENSSL_free(tmp_host); + if (tmp_port != port) + OPENSSL_free(tmp_port); + if (!res) { + BIO_printf(bio_err, + "%s: -connect argument or target parameter malformed or ambiguous\n", + prog); + goto end; } - argc--; - argv++; - } - if (badop) { - bad: - sc_usage(); - goto end; } -#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) - if (jpake_secret) { - if (psk_key) { - BIO_printf(bio_err, "Can't use JPAKE and PSK together\n"); + + if (bindstr != NULL) { + int res; + res = BIO_parse_hostserv(bindstr, &bindhost, &bindport, + BIO_PARSE_PRIO_HOST); + if (!res) { + BIO_printf(bio_err, + "%s: -bind argument parameter malformed or ambiguous\n", + prog); goto end; } - psk_identity = "JPAKE"; } -#endif - if (prot_opt > 1) { - BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); +#ifdef AF_UNIX + if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) { + BIO_printf(bio_err, + "Can't use unix sockets and datagrams together\n"); goto end; } +#endif - if (prot_opt == 1 && no_prot_opt) { - BIO_printf(bio_err, "Cannot supply both a protocol flag and " - "\"-no_<prot>\"\n"); - goto end; +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + if (socket_type != SOCK_DGRAM) { + BIO_printf(bio_err, "Can't use -sctp without DTLS\n"); + goto end; + } + /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */ + socket_type = SOCK_STREAM; } +#endif - OpenSSL_add_ssl_algorithms(); - SSL_load_error_strings(); - -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +#if !defined(OPENSSL_NO_NEXTPROTONEG) next_proto.status = -1; if (next_proto_neg_in) { next_proto.data = @@ -1187,17 +1618,7 @@ int MAIN(int argc, char **argv) next_proto.data = NULL; #endif - e = setup_engine(bio_err, engine_id, 1); -#ifndef OPENSSL_NO_ENGINE - if (ssl_client_engine_id) { - ssl_client_engine = ENGINE_by_id(ssl_client_engine_id); - if (!ssl_client_engine) { - BIO_printf(bio_err, "Error getting client auth engine\n"); - goto end; - } - } -#endif - if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { + if (!app_passwd(passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } @@ -1205,44 +1626,39 @@ int MAIN(int argc, char **argv) if (key_file == NULL) key_file = cert_file; - if (key_file) { - - key = load_key(bio_err, key_file, key_format, 0, pass, e, + if (key_file != NULL) { + key = load_key(key_file, key_format, 0, pass, e, "client certificate private key file"); - if (!key) { + if (key == NULL) { ERR_print_errors(bio_err); goto end; } - } - if (cert_file) { - cert = load_cert(bio_err, cert_file, cert_format, - NULL, e, "client certificate file"); - - if (!cert) { + if (cert_file != NULL) { + cert = load_cert(cert_file, cert_format, "client certificate file"); + if (cert == NULL) { ERR_print_errors(bio_err); goto end; } } - if (chain_file) { - chain = load_certs(bio_err, chain_file, FORMAT_PEM, - NULL, e, "client certificate chain"); - if (!chain) + if (chain_file != NULL) { + if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL, + "client certificate chain")) goto end; } - if (crl_file) { + if (crl_file != NULL) { X509_CRL *crl; crl = load_crl(crl_file, crl_format); - if (!crl) { + if (crl == NULL) { BIO_puts(bio_err, "Error loading CRL\n"); ERR_print_errors(bio_err); goto end; } crls = sk_X509_CRL_new_null(); - if (!crls || !sk_X509_CRL_push(crls, crl)) { + if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { BIO_puts(bio_err, "Error adding CRL\n"); ERR_print_errors(bio_err); X509_CRL_free(crl); @@ -1250,30 +1666,19 @@ int MAIN(int argc, char **argv) } } - if (!load_excert(&exc, bio_err)) + if (!load_excert(&exc)) goto end; - if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL - && !RAND_status()) { - BIO_printf(bio_err, - "warning, not much extra random data, consider using the -rand option\n"); - } - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - if (bio_c_out == NULL) { if (c_quiet && !c_debug) { bio_c_out = BIO_new(BIO_s_null()); - if (c_msg && !bio_c_msg) - bio_c_msg = BIO_new_fp(stdout, BIO_NOCLOSE); - } else { - if (bio_c_out == NULL) - bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE); - } + if (c_msg && bio_c_msg == NULL) + bio_c_msg = dup_bio_out(FORMAT_TEXT); + } else if (bio_c_out == NULL) + bio_c_out = dup_bio_out(FORMAT_TEXT); } #ifndef OPENSSL_NO_SRP - if (!app_passwd(bio_err, srppass, NULL, &srp_arg.srppassin, NULL)) { + if (!app_passwd(srppass, NULL, &srp_arg.srppassin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } @@ -1285,20 +1690,90 @@ int MAIN(int argc, char **argv) goto end; } - if (vpm) - SSL_CTX_set1_param(ctx, vpm); + SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); + + if (sdebug) + ssl_ctx_security_debug(ctx, sdebug); + + if (!config_ctx(cctx, ssl_args, ctx)) + goto end; + + if (ssl_config != NULL) { + if (SSL_CTX_config(ctx, ssl_config) == 0) { + BIO_printf(bio_err, "Error using configuration \"%s\"\n", + ssl_config); + ERR_print_errors(bio_err); + goto end; + } + } + + if (min_version != 0 + && SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + goto end; + if (max_version != 0 + && SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto end; - if (!args_ssl_call(ctx, bio_err, cctx, ssl_args, 1, no_jpake)) { + if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { + BIO_printf(bio_err, "Error setting verify params\n"); ERR_print_errors(bio_err); goto end; } + if (async) { + SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); + } + + if (max_send_fragment > 0 + && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { + BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n", + prog, max_send_fragment); + goto end; + } + + if (split_send_fragment > 0 + && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) { + BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n", + prog, split_send_fragment); + goto end; + } + + if (max_pipelines > 0 + && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) { + BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n", + prog, max_pipelines); + goto end; + } + + if (read_buf_len > 0) { + SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len); + } + + if (maxfraglen > 0 + && !SSL_CTX_set_tlsext_max_fragment_length(ctx, maxfraglen)) { + BIO_printf(bio_err, + "%s: Max Fragment Length code %u is out of permitted values" + "\n", prog, maxfraglen); + goto end; + } + if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, crls, crl_download)) { BIO_printf(bio_err, "Error loading store locations\n"); ERR_print_errors(bio_err); goto end; } + if (ReqCAfile != NULL) { + STACK_OF(X509_NAME) *nm = sk_X509_NAME_new_null(); + + if (nm == NULL || !SSL_add_file_cert_subjects_to_stack(nm, ReqCAfile)) { + sk_X509_NAME_pop_free(nm, X509_NAME_free); + BIO_printf(bio_err, "Error loading CA names\n"); + ERR_print_errors(bio_err); + goto end; + } + SSL_CTX_set0_CA_list(ctx, nm); + } #ifndef OPENSSL_NO_ENGINE if (ssl_client_engine) { if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) { @@ -1312,74 +1787,116 @@ int MAIN(int argc, char **argv) #endif #ifndef OPENSSL_NO_PSK -# ifdef OPENSSL_NO_JPAKE - if (psk_key != NULL) -# else - if (psk_key != NULL || jpake_secret) -# endif - { + if (psk_key != NULL) { if (c_debug) - BIO_printf(bio_c_out, - "PSK key given or JPAKE in use, setting client callback\n"); + BIO_printf(bio_c_out, "PSK key given, setting client callback\n"); SSL_CTX_set_psk_client_callback(ctx, psk_client_cb); } #endif + if (psksessf != NULL) { + BIO *stmp = BIO_new_file(psksessf, "r"); + + if (stmp == NULL) { + BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); + BIO_free(stmp); + if (psksess == NULL) { + BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + } + if (psk_key != NULL || psksess != NULL) + SSL_CTX_set_psk_use_session_callback(ctx, psk_use_session_cb); + #ifndef OPENSSL_NO_SRTP - if (srtp_profiles != NULL) - SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); + if (srtp_profiles != NULL) { + /* Returns 0 on success! */ + if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) { + BIO_printf(bio_err, "Error setting SRTP profile\n"); + ERR_print_errors(bio_err); + goto end; + } + } #endif - if (exc) + + if (exc != NULL) ssl_ctx_set_excert(ctx, exc); -#if !defined(OPENSSL_NO_TLSEXT) -# if !defined(OPENSSL_NO_NEXTPROTONEG) - if (next_proto.data) +#if !defined(OPENSSL_NO_NEXTPROTONEG) + if (next_proto.data != NULL) SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); -# endif +#endif if (alpn_in) { - unsigned short alpn_len; + size_t alpn_len; unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in); if (alpn == NULL) { BIO_printf(bio_err, "Error parsing -alpn argument\n"); goto end; } - SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); + /* Returns 0 on success! */ + if (SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len) != 0) { + BIO_printf(bio_err, "Error setting ALPN\n"); + goto end; + } OPENSSL_free(alpn); } -#endif -#ifndef OPENSSL_NO_TLSEXT - for (i = 0; i < serverinfo_types_count; i++) { - SSL_CTX_add_client_custom_ext(ctx, - serverinfo_types[i], - NULL, NULL, NULL, - serverinfo_cli_parse_cb, NULL); + + for (i = 0; i < serverinfo_count; i++) { + if (!SSL_CTX_add_client_custom_ext(ctx, + serverinfo_types[i], + NULL, NULL, NULL, + serverinfo_cli_parse_cb, NULL)) { + BIO_printf(bio_err, + "Warning: Unable to add custom extension %u, skipping\n", + serverinfo_types[i]); + } } -#endif if (state) SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); -#if 0 - else - SSL_CTX_set_cipher_list(ctx, getenv("SSL_CIPHER")); + +#ifndef OPENSSL_NO_CT + /* Enable SCT processing, without early connection termination */ + if (ct_validation && + !SSL_CTX_enable_ct(ctx, SSL_CT_VALIDATION_PERMISSIVE)) { + ERR_print_errors(bio_err); + goto end; + } + + if (!ctx_set_ctlog_list_file(ctx, ctlog_file)) { + if (ct_validation) { + ERR_print_errors(bio_err); + goto end; + } + + /* + * If CT validation is not enabled, the log list isn't needed so don't + * show errors or abort. We try to load it regardless because then we + * can show the names of the logs any SCTs came from (SCTs may be seen + * even with validation disabled). + */ + ERR_clear_error(); + } #endif SSL_CTX_set_verify(ctx, verify, verify_callback); - if ((CAfile || CApath) - && !SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) { - ERR_print_errors(bio_err); - } - if (!SSL_CTX_set_default_verify_paths(ctx)) { + if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { ERR_print_errors(bio_err); + goto end; } ssl_ctx_add_crls(ctx, crls, crl_download); + if (!set_cert_key_stuff(ctx, cert, key, chain, build_chain)) goto end; -#ifndef OPENSSL_NO_TLSEXT - if (servername != NULL) { + if (!noservername) { tlsextcbp.biodebug = bio_err; SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); @@ -1400,86 +1917,141 @@ int MAIN(int argc, char **argv) ssl_srp_verify_param_cb); } # endif -#endif + + if (dane_tlsa_domain != NULL) { + if (SSL_CTX_dane_enable(ctx) <= 0) { + BIO_printf(bio_err, + "%s: Error enabling DANE TLSA authentication.\n", + prog); + ERR_print_errors(bio_err); + goto end; + } + } + + /* + * In TLSv1.3 NewSessionTicket messages arrive after the handshake and can + * come at any time. Therefore we use a callback to write out the session + * when we know about it. This approach works for < TLSv1.3 as well. + */ + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT + | SSL_SESS_CACHE_NO_INTERNAL_STORE); + SSL_CTX_sess_set_new_cb(ctx, new_session_cb); + + if (set_keylog_file(ctx, keylog_file)) + goto end; con = SSL_new(ctx); - if (sess_in) { + if (con == NULL) + goto end; + + if (enable_pha) + SSL_set_post_handshake_auth(con, 1); + + if (sess_in != NULL) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); - if (!stmp) { + if (stmp == NULL) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); BIO_free(stmp); - if (!sess) { + if (sess == NULL) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } - SSL_set_session(con, sess); + if (!SSL_set_session(con, sess)) { + BIO_printf(bio_err, "Can't set session\n"); + ERR_print_errors(bio_err); + goto end; + } + SSL_SESSION_free(sess); } if (fallback_scsv) SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV); -#ifndef OPENSSL_NO_TLSEXT - if (servername != NULL) { + if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) { + if (servername == NULL) + servername = (host == NULL) ? "localhost" : host; if (!SSL_set_tlsext_host_name(con, servername)) { BIO_printf(bio_err, "Unable to set TLS servername extension.\n"); ERR_print_errors(bio_err); goto end; } } -#endif -#ifndef OPENSSL_NO_KRB5 - if (con && (kctx = kssl_ctx_new()) != NULL) { - SSL_set0_kssl_ctx(con, kctx); - kssl_ctx_setstring(kctx, KSSL_SERVER, host); + + if (dane_tlsa_domain != NULL) { + if (SSL_dane_enable(con, dane_tlsa_domain) <= 0) { + BIO_printf(bio_err, "%s: Error enabling DANE TLSA " + "authentication.\n", prog); + ERR_print_errors(bio_err); + goto end; + } + if (dane_tlsa_rrset == NULL) { + BIO_printf(bio_err, "%s: DANE TLSA authentication requires at " + "least one -dane_tlsa_rrdata option.\n", prog); + goto end; + } + if (tlsa_import_rrset(con, dane_tlsa_rrset) <= 0) { + BIO_printf(bio_err, "%s: Failed to import any TLSA " + "records.\n", prog); + goto end; + } + if (dane_ee_no_name) + SSL_dane_set_flags(con, DANE_FLAG_NO_DANE_EE_NAMECHECKS); + } else if (dane_tlsa_rrset != NULL) { + BIO_printf(bio_err, "%s: DANE TLSA authentication requires the " + "-dane_tlsa_domain option.\n", prog); + goto end; } -#endif /* OPENSSL_NO_KRB5 */ -/* SSL_set_cipher_list(con,"RC4-MD5"); */ -#if 0 -# ifdef TLSEXT_TYPE_opaque_prf_input - SSL_set_tlsext_opaque_prf_input(con, "Test client", 11); -# endif -#endif re_start: - - if (init_client(&s, host, port, socket_type) == 0) { + if (init_client(&s, host, port, bindhost, bindport, socket_family, + socket_type, protocol) == 0) { BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error()); - SHUTDOWN(s); + BIO_closesocket(s); goto end; } BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); -#ifdef FIONBIO if (c_nbio) { - unsigned long l = 1; - BIO_printf(bio_c_out, "turning on non blocking io\n"); - if (BIO_socket_ioctl(s, FIONBIO, &l) < 0) { + if (!BIO_socket_nbio(s, 1)) { ERR_print_errors(bio_err); goto end; } + BIO_printf(bio_c_out, "Turned on non blocking io\n"); } -#endif - if (c_Pause & 0x01) - SSL_set_debug(con, 1); +#ifndef OPENSSL_NO_DTLS + if (isdtls) { + union BIO_sock_info_u peer_info; - if (socket_type == SOCK_DGRAM) { +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) + sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE); + else +#endif + sbio = BIO_new_dgram(s, BIO_NOCLOSE); - sbio = BIO_new_dgram(s, BIO_NOCLOSE); - if (getsockname(s, &peer, (void *)&peerlen) < 0) { + if ((peer_info.addr = BIO_ADDR_new()) == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + BIO_closesocket(s); + goto end; + } + if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); - SHUTDOWN(s); + BIO_ADDR_free(peer_info.addr); + BIO_closesocket(s); goto end; } - (void)BIO_ctrl_set_connected(sbio, 1, &peer); + (void)BIO_ctrl_set_connected(sbio, peer_info.addr); + BIO_ADDR_free(peer_info.addr); + peer_info.addr = NULL; if (enable_timeouts) { timeout.tv_sec = 0; @@ -1504,10 +2076,12 @@ int MAIN(int argc, char **argv) BIO_free(sbio); goto shut; } - } else + } else { /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); + } } else +#endif /* OPENSSL_NO_DTLS */ sbio = BIO_new_socket(s, BIO_NOCLOSE); if (nbio_test) { @@ -1518,7 +2092,6 @@ int MAIN(int argc, char **argv) } if (c_debug) { - SSL_set_debug(con, 1); BIO_set_callback(sbio, bio_dump_callback); BIO_set_callback_arg(sbio, (char *)bio_c_out); } @@ -1531,32 +2104,18 @@ int MAIN(int argc, char **argv) SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_msg ? bio_c_msg : bio_c_out); } -#ifndef OPENSSL_NO_TLSEXT + if (c_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_c_out); } +#ifndef OPENSSL_NO_OCSP if (c_status_req) { SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); -# if 0 - { - STACK_OF(OCSP_RESPID) *ids = sk_OCSP_RESPID_new_null(); - OCSP_RESPID *id = OCSP_RESPID_new(); - id->value.byKey = ASN1_OCTET_STRING_new(); - id->type = V_OCSP_RESPID_KEY; - ASN1_STRING_set(id->value.byKey, "Hello World", -1); - sk_OCSP_RESPID_push(ids, id); - SSL_set_tlsext_status_ids(con, ids); - } -# endif } #endif -#ifndef OPENSSL_NO_JPAKE - if (jpake_secret) - jpake_client_auth(bio_c_out, sbio, jpake_secret); -#endif SSL_set_bio(con, sbio, sbio); SSL_set_connect_state(con); @@ -1578,148 +2137,608 @@ int MAIN(int argc, char **argv) sbuf_len = 0; sbuf_off = 0; - /* This is an ugly hack that does a lot of assumptions */ - /* - * We do have to handle multi-line responses which may come in a single - * packet or not. We therefore have to use BIO_gets() which does need a - * buffering BIO. So during the initial chitchat we do push a buffering - * BIO into the chain that is removed again later on to not disturb the - * rest of the s_client operation. - */ - if (starttls_proto == PROTO_SMTP) { - int foundit = 0; - BIO *fbio = BIO_new(BIO_f_buffer()); - BIO_push(fbio, sbio); - /* wait for multi-line response to end from SMTP */ - do { - mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + switch ((PROTOCOL_CHOICE) starttls_proto) { + case PROTO_OFF: + break; + case PROTO_LMTP: + case PROTO_SMTP: + { + /* + * This is an ugly hack that does a lot of assumptions. We do + * have to handle multi-line responses which may come in a single + * packet or not. We therefore have to use BIO_gets() which does + * need a buffering BIO. So during the initial chitchat we do + * push a buffering BIO into the chain that is removed again + * later on to not disturb the rest of the s_client operation. + */ + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + /* Wait for multi-line response to end from LMTP or SMTP */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + } while (mbuf_len > 3 && mbuf[3] == '-'); + if (protohost == NULL) + protohost = "mail.example.com"; + if (starttls_proto == (int)PROTO_LMTP) + BIO_printf(fbio, "LHLO %s\r\n", protohost); + else + BIO_printf(fbio, "EHLO %s\r\n", protohost); + (void)BIO_flush(fbio); + /* + * Wait for multi-line response to end LHLO LMTP or EHLO SMTP + * response. + */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } while (mbuf_len > 3 && mbuf[3] == '-'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, "STARTTLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); } - while (mbuf_len > 3 && mbuf[3] == '-'); - /* STARTTLS command requires EHLO... */ - BIO_printf(fbio, "EHLO openssl.client.net\r\n"); - (void)BIO_flush(fbio); - /* wait for multi-line response to end EHLO SMTP response */ - do { - mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); - if (strstr(mbuf, "STARTTLS")) - foundit = 1; + break; + case PROTO_POP3: + { + BIO_read(sbio, mbuf, BUFSIZZ); + BIO_printf(sbio, "STLS\r\n"); + mbuf_len = BIO_read(sbio, sbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } } - while (mbuf_len > 3 && mbuf[3] == '-'); - (void)BIO_flush(fbio); - BIO_pop(fbio); - BIO_free(fbio); - if (!foundit) - BIO_printf(bio_err, - "didn't found starttls in server response," - " try anyway...\n"); - BIO_printf(sbio, "STARTTLS\r\n"); - BIO_read(sbio, sbuf, BUFSIZZ); - } else if (starttls_proto == PROTO_POP3) { - BIO_read(sbio, mbuf, BUFSIZZ); - BIO_printf(sbio, "STLS\r\n"); - BIO_read(sbio, sbuf, BUFSIZZ); - } else if (starttls_proto == PROTO_IMAP) { - int foundit = 0; - BIO *fbio = BIO_new(BIO_f_buffer()); - BIO_push(fbio, sbio); - BIO_gets(fbio, mbuf, BUFSIZZ); - /* STARTTLS command requires CAPABILITY... */ - BIO_printf(fbio, ". CAPABILITY\r\n"); - (void)BIO_flush(fbio); - /* wait for multi-line CAPABILITY response */ - do { - mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); - if (strstr(mbuf, "STARTTLS")) - foundit = 1; + break; + case PROTO_IMAP: + { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + BIO_gets(fbio, mbuf, BUFSIZZ); + /* STARTTLS command requires CAPABILITY... */ + BIO_printf(fbio, ". CAPABILITY\r\n"); + (void)BIO_flush(fbio); + /* wait for multi-line CAPABILITY response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } + while (mbuf_len > 3 && mbuf[0] != '.'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, ". STARTTLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); } - while (mbuf_len > 3 && mbuf[0] != '.'); - (void)BIO_flush(fbio); - BIO_pop(fbio); - BIO_free(fbio); - if (!foundit) - BIO_printf(bio_err, - "didn't found STARTTLS in server response," - " try anyway...\n"); - BIO_printf(sbio, ". STARTTLS\r\n"); - BIO_read(sbio, sbuf, BUFSIZZ); - } else if (starttls_proto == PROTO_FTP) { - BIO *fbio = BIO_new(BIO_f_buffer()); - BIO_push(fbio, sbio); - /* wait for multi-line response to end from FTP */ - do { + break; + case PROTO_FTP: + { + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + /* wait for multi-line response to end from FTP */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + } + while (mbuf_len > 3 && mbuf[3] == '-'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + BIO_printf(sbio, "AUTH TLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } + break; + case PROTO_XMPP: + case PROTO_XMPP_SERVER: + { + int seen = 0; + BIO_printf(sbio, "<stream:stream " + "xmlns:stream='http://etherx.jabber.org/streams' " + "xmlns='jabber:%s' to='%s' version='1.0'>", + starttls_proto == PROTO_XMPP ? "client" : "server", + protohost ? protohost : host); + seen = BIO_read(sbio, mbuf, BUFSIZZ); + if (seen < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + mbuf[seen] = '\0'; + while (!strstr + (mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'") + && !strstr(mbuf, + "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"")) + { + seen = BIO_read(sbio, mbuf, BUFSIZZ); + + if (seen <= 0) + goto shut; + + mbuf[seen] = '\0'; + } + BIO_printf(sbio, + "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); + seen = BIO_read(sbio, sbuf, BUFSIZZ); + if (seen < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto shut; + } + sbuf[seen] = '\0'; + if (!strstr(sbuf, "<proceed")) + goto shut; + mbuf[0] = '\0'; + } + break; + case PROTO_TELNET: + { + static const unsigned char tls_do[] = { + /* IAC DO START_TLS */ + 255, 253, 46 + }; + static const unsigned char tls_will[] = { + /* IAC WILL START_TLS */ + 255, 251, 46 + }; + static const unsigned char tls_follows[] = { + /* IAC SB START_TLS FOLLOWS IAC SE */ + 255, 250, 46, 1, 255, 240 + }; + int bytes; + + /* Telnet server should demand we issue START_TLS */ + bytes = BIO_read(sbio, mbuf, BUFSIZZ); + if (bytes != 3 || memcmp(mbuf, tls_do, 3) != 0) + goto shut; + /* Agree to issue START_TLS and send the FOLLOWS sub-command */ + BIO_write(sbio, tls_will, 3); + BIO_write(sbio, tls_follows, 6); + (void)BIO_flush(sbio); + /* Telnet server also sent the FOLLOWS sub-command */ + bytes = BIO_read(sbio, mbuf, BUFSIZZ); + if (bytes != 6 || memcmp(mbuf, tls_follows, 6) != 0) + goto shut; + } + break; + case PROTO_CONNECT: + { + enum { + error_proto, /* Wrong protocol, not even HTTP */ + error_connect, /* CONNECT failed */ + success + } foundit = error_connect; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr); + (void)BIO_flush(fbio); + /* + * The first line is the HTTP response. According to RFC 7230, + * it's formated exactly like this: + * + * HTTP/d.d ddd Reason text\r\n + */ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (mbuf_len < (int)strlen("HTTP/1.0 200")) { + BIO_printf(bio_err, + "%s: HTTP CONNECT failed, insufficient response " + "from proxy (got %d octets)\n", prog, mbuf_len); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + goto shut; + } + if (mbuf[8] != ' ') { + BIO_printf(bio_err, + "%s: HTTP CONNECT failed, incorrect response " + "from proxy\n", prog); + foundit = error_proto; + } else if (mbuf[9] != '2') { + BIO_printf(bio_err, "%s: HTTP CONNECT failed: %s ", prog, + &mbuf[9]); + } else { + foundit = success; + } + if (foundit != error_proto) { + /* Read past all following headers */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + } while (mbuf_len > 2); + } + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (foundit != success) { + goto shut; + } } - while (mbuf_len > 3 && mbuf[3] == '-'); - (void)BIO_flush(fbio); - BIO_pop(fbio); - BIO_free(fbio); - BIO_printf(sbio, "AUTH TLS\r\n"); - BIO_read(sbio, sbuf, BUFSIZZ); - } - if (starttls_proto == PROTO_XMPP) { - int seen = 0; - BIO_printf(sbio, "<stream:stream " - "xmlns:stream='http://etherx.jabber.org/streams' " - "xmlns='jabber:client' to='%s' version='1.0'>", host); - seen = BIO_read(sbio, mbuf, BUFSIZZ); - mbuf[seen] = 0; - while (!strstr - (mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) { - if (strstr(mbuf, "/stream:features>")) + break; + case PROTO_IRC: + { + int numeric; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + BIO_printf(fbio, "STARTTLS\r\n"); + (void)BIO_flush(fbio); + width = SSL_get_fd(con) + 1; + + do { + numeric = 0; + + FD_ZERO(&readfds); + openssl_fdset(SSL_get_fd(con), &readfds); + timeout.tv_sec = S_CLIENT_IRC_READ_TIMEOUT; + timeout.tv_usec = 0; + /* + * If the IRCd doesn't respond within + * S_CLIENT_IRC_READ_TIMEOUT seconds, assume + * it doesn't support STARTTLS. Many IRCds + * will not give _any_ sort of response to a + * STARTTLS command when it's not supported. + */ + if (!BIO_get_buffer_num_lines(fbio) + && !BIO_pending(fbio) + && !BIO_pending(sbio) + && select(width, (void *)&readfds, NULL, NULL, + &timeout) < 1) { + BIO_printf(bio_err, + "Timeout waiting for response (%d seconds).\n", + S_CLIENT_IRC_READ_TIMEOUT); + break; + } + + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (mbuf_len < 1 || sscanf(mbuf, "%*s %d", &numeric) != 1) + break; + /* :example.net 451 STARTTLS :You have not registered */ + /* :example.net 421 STARTTLS :Unknown command */ + if ((numeric == 451 || numeric == 421) + && strstr(mbuf, "STARTTLS") != NULL) { + BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf); + break; + } + if (numeric == 691) { + BIO_printf(bio_err, "STARTTLS negotiation failed: "); + ERR_print_errors(bio_err); + break; + } + } while (numeric != 670); + + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (numeric != 670) { + BIO_printf(bio_err, "Server does not support STARTTLS.\n"); + ret = 1; goto shut; - seen = BIO_read(sbio, mbuf, BUFSIZZ); - if (seen <= 0) + } + } + break; + case PROTO_MYSQL: + { + /* SSL request packet */ + static const unsigned char ssl_req[] = { + /* payload_length, sequence_id */ + 0x20, 0x00, 0x00, 0x01, + /* payload */ + /* capability flags, CLIENT_SSL always set */ + 0x85, 0xae, 0x7f, 0x00, + /* max-packet size */ + 0x00, 0x00, 0x00, 0x01, + /* character set */ + 0x21, + /* string[23] reserved (all [0]) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int bytes = 0; + int ssl_flg = 0x800; + int pos; + const unsigned char *packet = (const unsigned char *)sbuf; + + /* Receiving Initial Handshake packet. */ + bytes = BIO_read(sbio, (void *)packet, BUFSIZZ); + if (bytes < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto shut; + /* Packet length[3], Packet number[1] + minimum payload[17] */ + } else if (bytes < 21) { + BIO_printf(bio_err, "MySQL packet too short.\n"); + goto shut; + } else if (bytes != (4 + packet[0] + + (packet[1] << 8) + + (packet[2] << 16))) { + BIO_printf(bio_err, "MySQL packet length does not match.\n"); + goto shut; + /* protocol version[1] */ + } else if (packet[4] != 0xA) { + BIO_printf(bio_err, + "Only MySQL protocol version 10 is supported.\n"); + goto shut; + } + + pos = 5; + /* server version[string+NULL] */ + for (;;) { + if (pos >= bytes) { + BIO_printf(bio_err, "Cannot confirm server version. "); + goto shut; + } else if (packet[pos++] == '\0') { + break; + } + } + + /* make sure we have at least 15 bytes left in the packet */ + if (pos + 15 > bytes) { + BIO_printf(bio_err, + "MySQL server handshake packet is broken.\n"); + goto shut; + } + + pos += 12; /* skip over conn id[4] + SALT[8] */ + if (packet[pos++] != '\0') { /* verify filler */ + BIO_printf(bio_err, + "MySQL packet is broken.\n"); + goto shut; + } + + /* capability flags[2] */ + if (!((packet[pos] + (packet[pos + 1] << 8)) & ssl_flg)) { + BIO_printf(bio_err, "MySQL server does not support SSL.\n"); + goto shut; + } + + /* Sending SSL Handshake packet. */ + BIO_write(sbio, ssl_req, sizeof(ssl_req)); + (void)BIO_flush(sbio); + } + break; + case PROTO_POSTGRES: + { + static const unsigned char ssl_request[] = { + /* Length SSLRequest */ + 0, 0, 0, 8, 4, 210, 22, 47 + }; + int bytes; + + /* Send SSLRequest packet */ + BIO_write(sbio, ssl_request, 8); + (void)BIO_flush(sbio); + + /* Reply will be a single S if SSL is enabled */ + bytes = BIO_read(sbio, sbuf, BUFSIZZ); + if (bytes != 1 || sbuf[0] != 'S') + goto shut; + } + break; + case PROTO_NNTP: + { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + BIO_gets(fbio, mbuf, BUFSIZZ); + /* STARTTLS command requires CAPABILITIES... */ + BIO_printf(fbio, "CAPABILITIES\r\n"); + (void)BIO_flush(fbio); + /* wait for multi-line CAPABILITIES response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } while (mbuf_len > 1 && mbuf[0] != '.'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, "STARTTLS\r\n"); + mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + mbuf[mbuf_len] = '\0'; + if (strstr(mbuf, "382") == NULL) { + BIO_printf(bio_err, "STARTTLS failed: %s", mbuf); + goto shut; + } + } + break; + case PROTO_SIEVE: + { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + /* wait for multi-line response to end from Sieve */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + /* + * According to RFC 5804 § 1.7, capability + * is case-insensitive, make it uppercase + */ + if (mbuf_len > 1 && mbuf[0] == '"') { + make_uppercase(mbuf); + if (strncmp(mbuf, "\"STARTTLS\"", 10) == 0) + foundit = 1; + } + } while (mbuf_len > 1 && mbuf[0] == '"'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, "STARTTLS\r\n"); + mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + mbuf[mbuf_len] = '\0'; + if (mbuf_len < 2) { + BIO_printf(bio_err, "STARTTLS failed: %s", mbuf); + goto shut; + } + /* + * According to RFC 5804 § 2.2, response codes are case- + * insensitive, make it uppercase but preserve the response. + */ + strncpy(sbuf, mbuf, 2); + make_uppercase(sbuf); + if (strncmp(sbuf, "OK", 2) != 0) { + BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf); goto shut; - mbuf[seen] = 0; + } + } + break; + case PROTO_LDAP: + { + /* StartTLS Operation according to RFC 4511 */ + static char ldap_tls_genconf[] = "asn1=SEQUENCE:LDAPMessage\n" + "[LDAPMessage]\n" + "messageID=INTEGER:1\n" + "extendedReq=EXPLICIT:23A,IMPLICIT:0C," + "FORMAT:ASCII,OCT:1.3.6.1.4.1.1466.20037\n"; + long errline = -1; + char *genstr = NULL; + int result = -1; + ASN1_TYPE *atyp = NULL; + BIO *ldapbio = BIO_new(BIO_s_mem()); + CONF *cnf = NCONF_new(NULL); + + if (cnf == NULL) { + BIO_free(ldapbio); + goto end; + } + BIO_puts(ldapbio, ldap_tls_genconf); + if (NCONF_load_bio(cnf, ldapbio, &errline) <= 0) { + BIO_free(ldapbio); + NCONF_free(cnf); + if (errline <= 0) { + BIO_printf(bio_err, "NCONF_load_bio failed\n"); + goto end; + } else { + BIO_printf(bio_err, "Error on line %ld\n", errline); + goto end; + } + } + BIO_free(ldapbio); + genstr = NCONF_get_string(cnf, "default", "asn1"); + if (genstr == NULL) { + NCONF_free(cnf); + BIO_printf(bio_err, "NCONF_get_string failed\n"); + goto end; + } + atyp = ASN1_generate_nconf(genstr, cnf); + if (atyp == NULL) { + NCONF_free(cnf); + BIO_printf(bio_err, "ASN1_generate_nconf failed\n"); + goto end; + } + NCONF_free(cnf); + + /* Send SSLRequest packet */ + BIO_write(sbio, atyp->value.sequence->data, + atyp->value.sequence->length); + (void)BIO_flush(sbio); + ASN1_TYPE_free(atyp); + + mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + result = ldap_ExtendedResponse_parse(mbuf, mbuf_len); + if (result < 0) { + BIO_printf(bio_err, "ldap_ExtendedResponse_parse failed\n"); + goto shut; + } else if (result > 0) { + BIO_printf(bio_err, "STARTTLS failed, LDAP Result Code: %i\n", + result); + goto shut; + } + mbuf_len = 0; } - BIO_printf(sbio, - "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); - seen = BIO_read(sbio, sbuf, BUFSIZZ); - sbuf[seen] = 0; - if (!strstr(sbuf, "<proceed")) + break; + } + + if (early_data_file != NULL + && ((SSL_get0_session(con) != NULL + && SSL_SESSION_get_max_early_data(SSL_get0_session(con)) > 0) + || (psksess != NULL + && SSL_SESSION_get_max_early_data(psksess) > 0))) { + BIO *edfile = BIO_new_file(early_data_file, "r"); + size_t readbytes, writtenbytes; + int finish = 0; + + if (edfile == NULL) { + BIO_printf(bio_err, "Cannot open early data file\n"); goto shut; - mbuf[0] = 0; + } + + while (!finish) { + if (!BIO_read_ex(edfile, cbuf, BUFSIZZ, &readbytes)) + finish = 1; + + while (!SSL_write_early_data(con, cbuf, readbytes, &writtenbytes)) { + switch (SSL_get_error(con, 0)) { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_READ: + /* Just keep trying - busy waiting */ + continue; + default: + BIO_printf(bio_err, "Error writing early data\n"); + BIO_free(edfile); + ERR_print_errors(bio_err); + goto shut; + } + } + } + + BIO_free(edfile); } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); - if ((SSL_version(con) == DTLS1_VERSION) && - DTLSv1_get_timeout(con, &timeout)) + if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)) timeoutp = &timeout; else timeoutp = NULL; - if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { + if (!SSL_is_init_finished(con) && SSL_total_renegotiations(con) == 0 + && SSL_get_key_update_type(con) == SSL_KEY_UPDATE_NONE) { in_init = 1; tty_on = 0; } else { tty_on = 1; if (in_init) { in_init = 0; -#if 0 /* This test doesn't really work as intended - * (needs to be fixed) */ -# ifndef OPENSSL_NO_TLSEXT - if (servername != NULL && !SSL_session_reused(con)) { - BIO_printf(bio_c_out, - "Server did %sacknowledge servername extension.\n", - tlsextcbp.ack ? "" : "not "); - } -# endif -#endif - if (sess_out) { - BIO *stmp = BIO_new_file(sess_out, "w"); - if (stmp) { - PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); - BIO_free(stmp); - } else - BIO_printf(bio_err, "Error writing session file %s\n", - sess_out); - } + if (c_brief) { BIO_puts(bio_err, "CONNECTION ESTABLISHED\n"); - print_ssl_summary(bio_err, con); + print_ssl_summary(con); } print_stuff(bio_c_out, con, full_log); @@ -1727,29 +2746,35 @@ int MAIN(int argc, char **argv) full_log--; if (starttls_proto) { - BIO_printf(bio_err, "%s", mbuf); + BIO_write(bio_err, mbuf, mbuf_len); /* We don't need to know any more */ - starttls_proto = PROTO_OFF; + if (!reconnect) + starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out, "drop connection and then reconnect\n"); - SSL_shutdown(con); + do_ssl_shutdown(con); SSL_set_connect_state(con); - SHUTDOWN(SSL_get_fd(con)); + BIO_closesocket(SSL_get_fd(con)); goto re_start; } } } - ssl_pending = read_ssl && SSL_pending(con); + ssl_pending = read_ssl && SSL_has_pending(con); if (!ssl_pending) { -#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) && !defined (OPENSSL_SYS_BEOS_R5) +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) if (tty_on) { - if (read_tty) + /* + * Note that select() returns when read _would not block_, + * and EOF satisfies that. To avoid a CPU-hogging loop, + * set the flag so we exit. + */ + if (read_tty && !at_eof) openssl_fdset(fileno_stdin(), &readfds); #if !defined(OPENSSL_SYS_VMS) if (write_tty) @@ -1768,8 +2793,6 @@ int MAIN(int argc, char **argv) openssl_fdset(SSL_get_fd(con), &writefds); } #endif -/*- printf("mode tty(%d %d%d) ssl(%d%d)\n", - tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ /* * Note: under VMS with SOCKETSHR the second parameter is @@ -1793,53 +2816,12 @@ int MAIN(int argc, char **argv) tv.tv_usec = 0; i = select(width, (void *)&readfds, (void *)&writefds, NULL, &tv); -# if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) - if (!i && (!_kbhit() || !read_tty)) - continue; -# else - if (!i && (!((_kbhit()) - || (WAIT_OBJECT_0 == - WaitForSingleObject(GetStdHandle - (STD_INPUT_HANDLE), - 0))) - || !read_tty)) + if (!i && (!has_stdin_waiting() || !read_tty)) continue; -# endif - } else - i = select(width, (void *)&readfds, (void *)&writefds, - NULL, timeoutp); - } -#elif defined(OPENSSL_SYS_NETWARE) - if (!write_tty) { - if (read_tty) { - tv.tv_sec = 1; - tv.tv_usec = 0; - i = select(width, (void *)&readfds, (void *)&writefds, - NULL, &tv); } else i = select(width, (void *)&readfds, (void *)&writefds, NULL, timeoutp); } -#elif defined(OPENSSL_SYS_BEOS_R5) - /* Under BeOS-R5 the situation is similar to DOS */ - i = 0; - stdin_set = 0; - (void)fcntl(fileno_stdin(), F_SETFL, O_NONBLOCK); - if (!write_tty) { - if (read_tty) { - tv.tv_sec = 1; - tv.tv_usec = 0; - i = select(width, (void *)&readfds, (void *)&writefds, - NULL, &tv); - if (read(fileno_stdin(), sbuf, 0) >= 0) - stdin_set = 1; - if (!i && (stdin_set != 1 || !read_tty)) - continue; - } else - i = select(width, (void *)&readfds, (void *)&writefds, - NULL, timeoutp); - } - (void)fcntl(fileno_stdin(), F_SETFL, 0); #else i = select(width, (void *)&readfds, (void *)&writefds, NULL, timeoutp); @@ -1848,14 +2830,11 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "bad select %d\n", get_last_socket_error()); goto shut; - /* goto end; */ } } - if ((SSL_version(con) == DTLS1_VERSION) - && DTLSv1_handle_timeout(con) > 0) { - BIO_printf(bio_err, "TIMEOUT occured\n"); - } + if (SSL_is_dtls(con) && DTLSv1_handle_timeout(con) > 0) + BIO_printf(bio_err, "TIMEOUT occurred\n"); if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) { k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int)cbuf_len); @@ -1880,6 +2859,12 @@ int MAIN(int argc, char **argv) write_ssl = 1; read_tty = 0; break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_c_out, "write A BLOCK\n"); + wait_for_async(con); + write_ssl = 1; + read_tty = 0; + break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out, "write R BLOCK\n"); write_tty = 0; @@ -1910,12 +2895,14 @@ int MAIN(int argc, char **argv) write_ssl = 0; } break; + case SSL_ERROR_WANT_ASYNC_JOB: + /* This shouldn't ever happen in s_client - treat as an error */ case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) || defined(OPENSSL_SYS_VMS) +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VMS) /* Assume Windows/DOS/BeOS can always write */ else if (!ssl_pending && write_tty) #else @@ -1931,10 +2918,9 @@ int MAIN(int argc, char **argv) BIO_printf(bio_c_out, "DONE\n"); ret = 0; goto shut; - /* goto end; */ } - sbuf_len -= i;; + sbuf_len -= i; sbuf_off += i; if (sbuf_len <= 0) { read_ssl = 1; @@ -1950,17 +2936,7 @@ int MAIN(int argc, char **argv) } } #endif -#if 1 k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); -#else -/* Demo for pending and peek :-) */ - k = SSL_read(con, sbuf, 16); - { - char zbuf[10240]; - printf("read=%d pending=%d peek=%d\n", k, SSL_pending(con), - SSL_peek(con, zbuf, 10240)); - } -#endif switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: @@ -1972,6 +2948,14 @@ int MAIN(int argc, char **argv) read_ssl = 0; write_tty = 1; break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_c_out, "read A BLOCK\n"); + wait_for_async(con); + write_tty = 0; + read_ssl = 1; + if ((read_tty == 0) && (write_ssl == 0)) + write_ssl = 1; + break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out, "read W BLOCK\n"); write_ssl = 1; @@ -1998,24 +2982,16 @@ int MAIN(int argc, char **argv) BIO_printf(bio_c_out, "closed\n"); ret = 0; goto shut; + case SSL_ERROR_WANT_ASYNC_JOB: + /* This shouldn't ever happen in s_client. Treat as an error */ case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; - /* break; */ } } -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) -# if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) - else if (_kbhit()) -# else - else if ((_kbhit()) - || (WAIT_OBJECT_0 == - WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) -# endif -#elif defined (OPENSSL_SYS_NETWARE) - else if (_kbhit()) -#elif defined(OPENSSL_SYS_BEOS_R5) - else if (stdin_set) +/* OPENSSL_SYS_MSDOS includes OPENSSL_SYS_WINDOWS */ +#if defined(OPENSSL_SYS_MSDOS) + else if (has_stdin_waiting()) #else else if (FD_ISSET(fileno_stdin(), &readfds)) #endif @@ -2040,20 +3016,33 @@ int MAIN(int argc, char **argv) assert(lf_num == 0); } else i = raw_read_stdin(cbuf, BUFSIZZ); +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) + if (i == 0) + at_eof = 1; +#endif - if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { + if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q' && cmdletters))) { BIO_printf(bio_err, "DONE\n"); ret = 0; goto shut; } - if ((!c_ign_eof) && (cbuf[0] == 'R')) { + if ((!c_ign_eof) && (cbuf[0] == 'R' && cmdletters)) { BIO_printf(bio_err, "RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len = 0; } + + if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' ) + && cmdletters) { + BIO_printf(bio_err, "KEYUPDATE\n"); + SSL_key_update(con, + cbuf[0] == 'K' ? SSL_KEY_UPDATE_REQUESTED + : SSL_KEY_UPDATE_NOT_REQUESTED); + cbuf_len = 0; + } #ifndef OPENSSL_NO_HEARTBEATS - else if ((!c_ign_eof) && (cbuf[0] == 'B')) { + else if ((!c_ign_eof) && (cbuf[0] == 'B' && cmdletters)) { BIO_printf(bio_err, "HEARTBEATING\n"); SSL_heartbeat(con); cbuf_len = 0; @@ -2076,101 +3065,103 @@ int MAIN(int argc, char **argv) shut: if (in_init) print_stuff(bio_c_out, con, full_log); - SSL_shutdown(con); - SHUTDOWN(SSL_get_fd(con)); + do_ssl_shutdown(con); + + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(SSL_get_fd(con), 1); /* SHUT_WR */ + /* + * We just said we have nothing else to say, but it doesn't mean that + * the other side has nothing. It's even recommended to consume incoming + * data. [In testing context this ensures that alerts are passed on...] + */ + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* some extreme round-trip */ + do { + FD_ZERO(&readfds); + openssl_fdset(s, &readfds); + } while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0 + && BIO_read(sbio, sbuf, BUFSIZZ) > 0); + + BIO_closesocket(SSL_get_fd(con)); end: if (con != NULL) { if (prexit != 0) print_stuff(bio_c_out, con, 1); SSL_free(con); } -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) - if (next_proto.data) - OPENSSL_free(next_proto.data); + SSL_SESSION_free(psksess); +#if !defined(OPENSSL_NO_NEXTPROTONEG) + OPENSSL_free(next_proto.data); #endif - if (ctx != NULL) - SSL_CTX_free(ctx); - if (cert) - X509_free(cert); - if (crls) - sk_X509_CRL_pop_free(crls, X509_CRL_free); - if (key) - EVP_PKEY_free(key); - if (chain) - sk_X509_pop_free(chain, X509_free); - if (pass) - OPENSSL_free(pass); + SSL_CTX_free(ctx); + set_keylog_file(NULL, NULL); + X509_free(cert); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + EVP_PKEY_free(key); + sk_X509_pop_free(chain, X509_free); + OPENSSL_free(pass); #ifndef OPENSSL_NO_SRP OPENSSL_free(srp_arg.srppassin); #endif - if (vpm) - X509_VERIFY_PARAM_free(vpm); + OPENSSL_free(connectstr); + OPENSSL_free(bindstr); + OPENSSL_free(host); + OPENSSL_free(port); + X509_VERIFY_PARAM_free(vpm); ssl_excert_free(exc); - if (ssl_args) - sk_OPENSSL_STRING_free(ssl_args); - if (cctx) - SSL_CONF_CTX_free(cctx); -#ifndef OPENSSL_NO_JPAKE - if (jpake_secret && psk_key) - OPENSSL_free(psk_key); -#endif - if (cbuf != NULL) { - OPENSSL_cleanse(cbuf, BUFSIZZ); - OPENSSL_free(cbuf); - } - if (sbuf != NULL) { - OPENSSL_cleanse(sbuf, BUFSIZZ); - OPENSSL_free(sbuf); - } - if (mbuf != NULL) { - OPENSSL_cleanse(mbuf, BUFSIZZ); - OPENSSL_free(mbuf); - } + sk_OPENSSL_STRING_free(ssl_args); + sk_OPENSSL_STRING_free(dane_tlsa_rrset); + SSL_CONF_CTX_free(cctx); + OPENSSL_clear_free(cbuf, BUFSIZZ); + OPENSSL_clear_free(sbuf, BUFSIZZ); + OPENSSL_clear_free(mbuf, BUFSIZZ); release_engine(e); - if (bio_c_out != NULL) { - BIO_free(bio_c_out); - bio_c_out = NULL; - } - if (bio_c_msg != NULL) { - BIO_free(bio_c_msg); - bio_c_msg = NULL; - } - SSL_COMP_free_compression_methods(); - apps_shutdown(); - OPENSSL_EXIT(ret); + BIO_free(bio_c_out); + bio_c_out = NULL; + BIO_free(bio_c_msg); + bio_c_msg = NULL; + return ret; } static void print_stuff(BIO *bio, SSL *s, int full) { X509 *peer = NULL; - char *p; - static const char *space = " "; - char buf[BUFSIZ]; STACK_OF(X509) *sk; - STACK_OF(X509_NAME) *sk2; const SSL_CIPHER *c; - X509_NAME *xn; - int j, i; + int i, istls13 = (SSL_version(s) == TLS1_3_VERSION); + long verify_result; #ifndef OPENSSL_NO_COMP const COMP_METHOD *comp, *expansion; #endif unsigned char *exportedkeymat; +#ifndef OPENSSL_NO_CT + const SSL_CTX *ctx = SSL_get_SSL_CTX(s); +#endif if (full) { int got_a_chain = 0; sk = SSL_get_peer_cert_chain(s); if (sk != NULL) { - got_a_chain = 1; /* we don't have it for SSL2 (yet) */ + got_a_chain = 1; BIO_printf(bio, "---\nCertificate chain\n"); for (i = 0; i < sk_X509_num(sk); i++) { - X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk, i)), - buf, sizeof(buf)); - BIO_printf(bio, "%2d s:%s\n", i, buf); - X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk, i)), - buf, sizeof(buf)); - BIO_printf(bio, " i:%s\n", buf); + BIO_printf(bio, "%2d s:", i); + X509_NAME_print_ex(bio, X509_get_subject_name(sk_X509_value(sk, i)), 0, get_nameopt()); + BIO_puts(bio, "\n"); + BIO_printf(bio, " i:"); + X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt()); + BIO_puts(bio, "\n"); if (c_showcerts) PEM_write_bio_X509(bio, sk_X509_value(sk, i)); } @@ -2184,69 +3175,65 @@ static void print_stuff(BIO *bio, SSL *s, int full) /* Redundant if we showed the whole chain */ if (!(c_showcerts && got_a_chain)) PEM_write_bio_X509(bio, peer); - X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof(buf)); - BIO_printf(bio, "subject=%s\n", buf); - X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf)); - BIO_printf(bio, "issuer=%s\n", buf); - } else - BIO_printf(bio, "no peer certificate available\n"); - - sk2 = SSL_get_client_CA_list(s); - if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) { - BIO_printf(bio, "---\nAcceptable client certificate CA names\n"); - for (i = 0; i < sk_X509_NAME_num(sk2); i++) { - xn = sk_X509_NAME_value(sk2, i); - X509_NAME_oneline(xn, buf, sizeof(buf)); - BIO_write(bio, buf, strlen(buf)); - BIO_write(bio, "\n", 1); - } + dump_cert_text(bio, peer); } else { - BIO_printf(bio, "---\nNo client certificate CA names sent\n"); + BIO_printf(bio, "no peer certificate available\n"); } - p = SSL_get_shared_ciphers(s, buf, sizeof(buf)); - if (p != NULL) { - /* - * This works only for SSL 2. In later protocol versions, the - * client does not know what other ciphers (in addition to the - * one to be used in the current connection) the server supports. - */ + print_ca_names(bio, s); - BIO_printf(bio, - "---\nCiphers common between both SSL endpoints:\n"); - j = i = 0; - while (*p) { - if (*p == ':') { - BIO_write(bio, space, 15 - j % 25); - i++; - j = 0; - BIO_write(bio, ((i % 3) ? " " : "\n"), 1); - } else { - BIO_write(bio, p, 1); - j++; + ssl_print_sigalgs(bio, s); + ssl_print_tmp_key(bio, s); + +#ifndef OPENSSL_NO_CT + /* + * When the SSL session is anonymous, or resumed via an abbreviated + * handshake, no SCTs are provided as part of the handshake. While in + * a resumed session SCTs may be present in the session's certificate, + * no callbacks are invoked to revalidate these, and in any case that + * set of SCTs may be incomplete. Thus it makes little sense to + * attempt to display SCTs from a resumed session's certificate, and of + * course none are associated with an anonymous peer. + */ + if (peer != NULL && !SSL_session_reused(s) && SSL_ct_is_enabled(s)) { + const STACK_OF(SCT) *scts = SSL_get0_peer_scts(s); + int sct_count = scts != NULL ? sk_SCT_num(scts) : 0; + + BIO_printf(bio, "---\nSCTs present (%i)\n", sct_count); + if (sct_count > 0) { + const CTLOG_STORE *log_store = SSL_CTX_get0_ctlog_store(ctx); + + BIO_printf(bio, "---\n"); + for (i = 0; i < sct_count; ++i) { + SCT *sct = sk_SCT_value(scts, i); + + BIO_printf(bio, "SCT validation status: %s\n", + SCT_validation_status_string(sct)); + SCT_print(sct, bio, 0, log_store); + if (i < sct_count - 1) + BIO_printf(bio, "\n---\n"); } - p++; + BIO_printf(bio, "\n"); } - BIO_write(bio, "\n", 1); } - - ssl_print_sigalgs(bio, s); - ssl_print_tmp_key(bio, s); +#endif BIO_printf(bio, - "---\nSSL handshake has read %ld bytes and written %ld bytes\n", + "---\nSSL handshake has read %ju bytes " + "and written %ju bytes\n", BIO_number_read(SSL_get_rbio(s)), BIO_number_written(SSL_get_wbio(s))); } - BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, ")); + print_verify_detail(s, bio); + BIO_printf(bio, (SSL_session_reused(s) ? "---\nReused, " : "---\nNew, ")); c = SSL_get_current_cipher(s); BIO_printf(bio, "%s, Cipher is %s\n", SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); if (peer != NULL) { EVP_PKEY *pktmp; - pktmp = X509_get_pubkey(peer); + + pktmp = X509_get0_pubkey(peer); BIO_printf(bio, "Server public key is %d bit\n", EVP_PKEY_bits(pktmp)); - EVP_PKEY_free(pktmp); } BIO_printf(bio, "Secure Renegotiation IS%s supported\n", SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); @@ -2263,16 +3250,19 @@ static void print_stuff(BIO *bio, SSL *s, int full) { /* Print out local port of connection: useful for debugging */ int sock; - struct sockaddr_in ladd; - socklen_t ladd_size = sizeof(ladd); + union BIO_sock_info_u info; + sock = SSL_get_fd(s); - getsockname(sock, (struct sockaddr *)&ladd, &ladd_size); - BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port)); + if ((info.addr = BIO_ADDR_new()) != NULL + && BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &info)) { + BIO_printf(bio_c_out, "LOCAL PORT is %u\n", + ntohs(BIO_ADDR_rawport(info.addr))); + } + BIO_ADDR_free(info.addr); } #endif -#if !defined(OPENSSL_NO_TLSEXT) -# if !defined(OPENSSL_NO_NEXTPROTONEG) +#if !defined(OPENSSL_NO_NEXTPROTONEG) if (next_proto.status != -1) { const unsigned char *proto; unsigned int proto_len; @@ -2281,7 +3271,7 @@ static void print_stuff(BIO *bio, SSL *s, int full) BIO_write(bio, proto, proto_len); BIO_write(bio, "\n", 1); } -# endif +#endif { const unsigned char *proto; unsigned int proto_len; @@ -2293,7 +3283,6 @@ static void print_stuff(BIO *bio, SSL *s, int full) } else BIO_printf(bio, "No ALPN negotiated\n"); } -#endif #ifndef OPENSSL_NO_SRTP { @@ -2306,37 +3295,61 @@ static void print_stuff(BIO *bio, SSL *s, int full) } #endif - SSL_SESSION_print(bio, SSL_get_session(s)); - if (keymatexportlabel != NULL) { + if (istls13) { + switch (SSL_get_early_data_status(s)) { + case SSL_EARLY_DATA_NOT_SENT: + BIO_printf(bio, "Early data was not sent\n"); + break; + + case SSL_EARLY_DATA_REJECTED: + BIO_printf(bio, "Early data was rejected\n"); + break; + + case SSL_EARLY_DATA_ACCEPTED: + BIO_printf(bio, "Early data was accepted\n"); + break; + + } + + /* + * We also print the verify results when we dump session information, + * but in TLSv1.3 we may not get that right away (or at all) depending + * on when we get a NewSessionTicket. Therefore we print it now as well. + */ + verify_result = SSL_get_verify_result(s); + BIO_printf(bio, "Verify return code: %ld (%s)\n", verify_result, + X509_verify_cert_error_string(verify_result)); + } else { + /* In TLSv1.3 we do this on arrival of a NewSessionTicket */ + SSL_SESSION_print(bio, SSL_get_session(s)); + } + + if (SSL_get_session(s) != NULL && keymatexportlabel != NULL) { BIO_printf(bio, "Keying material exporter:\n"); BIO_printf(bio, " Label: '%s'\n", keymatexportlabel); BIO_printf(bio, " Length: %i bytes\n", keymatexportlen); - exportedkeymat = OPENSSL_malloc(keymatexportlen); - if (exportedkeymat != NULL) { - if (!SSL_export_keying_material(s, exportedkeymat, - keymatexportlen, - keymatexportlabel, - strlen(keymatexportlabel), - NULL, 0, 0)) { - BIO_printf(bio, " Error\n"); - } else { - BIO_printf(bio, " Keying material: "); - for (i = 0; i < keymatexportlen; i++) - BIO_printf(bio, "%02X", exportedkeymat[i]); - BIO_printf(bio, "\n"); - } - OPENSSL_free(exportedkeymat); + exportedkeymat = app_malloc(keymatexportlen, "export key"); + if (!SSL_export_keying_material(s, exportedkeymat, + keymatexportlen, + keymatexportlabel, + strlen(keymatexportlabel), + NULL, 0, 0)) { + BIO_printf(bio, " Error\n"); + } else { + BIO_printf(bio, " Keying material: "); + for (i = 0; i < keymatexportlen; i++) + BIO_printf(bio, "%02X", exportedkeymat[i]); + BIO_printf(bio, "\n"); } + OPENSSL_free(exportedkeymat); } BIO_printf(bio, "---\n"); - if (peer != NULL) - X509_free(peer); + X509_free(peer); /* flush, or debugging output gets mixed with http response */ (void)BIO_flush(bio); } -#ifndef OPENSSL_NO_TLSEXT - +# ifndef OPENSSL_NO_OCSP static int ocsp_resp_cb(SSL *s, void *arg) { const unsigned char *p; @@ -2344,12 +3357,12 @@ static int ocsp_resp_cb(SSL *s, void *arg) OCSP_RESPONSE *rsp; len = SSL_get_tlsext_status_ocsp_resp(s, &p); BIO_puts(arg, "OCSP response: "); - if (!p) { + if (p == NULL) { BIO_puts(arg, "no response sent\n"); return 1; } rsp = d2i_OCSP_RESPONSE(NULL, &p, len); - if (!rsp) { + if (rsp == NULL) { BIO_puts(arg, "response parse error\n"); BIO_dump_indent(arg, (char *)p, len, 4); return 0; @@ -2360,5 +3373,90 @@ static int ocsp_resp_cb(SSL *s, void *arg) OCSP_RESPONSE_free(rsp); return 1; } +# endif -#endif +static int ldap_ExtendedResponse_parse(const char *buf, long rem) +{ + const unsigned char *cur, *end; + long len; + int tag, xclass, inf, ret = -1; + + cur = (const unsigned char *)buf; + end = cur + rem; + + /* + * From RFC 4511: + * + * LDAPMessage ::= SEQUENCE { + * messageID MessageID, + * protocolOp CHOICE { + * ... + * extendedResp ExtendedResponse, + * ... }, + * controls [0] Controls OPTIONAL } + * + * ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + * COMPONENTS OF LDAPResult, + * responseName [10] LDAPOID OPTIONAL, + * responseValue [11] OCTET STRING OPTIONAL } + * + * LDAPResult ::= SEQUENCE { + * resultCode ENUMERATED { + * success (0), + * ... + * other (80), + * ... }, + * matchedDN LDAPDN, + * diagnosticMessage LDAPString, + * referral [3] Referral OPTIONAL } + */ + + /* pull SEQUENCE */ + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE || + (rem = end - cur, len > rem)) { + BIO_printf(bio_err, "Unexpected LDAP response\n"); + goto end; + } + + rem = len; /* ensure that we don't overstep the SEQUENCE */ + + /* pull MessageID */ + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_INTEGER || + (rem = end - cur, len > rem)) { + BIO_printf(bio_err, "No MessageID\n"); + goto end; + } + + cur += len; /* shall we check for MessageId match or just skip? */ + + /* pull [APPLICATION 24] */ + rem = end - cur; + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_CONSTRUCTED || xclass != V_ASN1_APPLICATION || + tag != 24) { + BIO_printf(bio_err, "Not ExtendedResponse\n"); + goto end; + } + + /* pull resultCode */ + rem = end - cur; + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_ENUMERATED || len == 0 || + (rem = end - cur, len > rem)) { + BIO_printf(bio_err, "Not LDAPResult\n"); + goto end; + } + + /* len should always be one, but just in case... */ + for (ret = 0, inf = 0; inf < len; inf++) { + ret <<= 8; + ret |= cur[inf]; + } + /* There is more data, but we don't care... */ + end: + return ret; +} + +#endif /* OPENSSL_NO_SOCK */ diff --git a/apps/s_server.c b/apps/s_server.c index 83918fb6d39a..e3bb1a672d01 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -1,168 +1,28 @@ -/* apps/s_server.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * ECC cipher suite support in OpenSSL originally developed by - * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. - */ -/* ==================================================================== +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * - * The portions of the attached software ("Contribution") is developed by - * Nokia Corporation and is licensed pursuant to the OpenSSL open source - * license. - * - * The Contribution, originally written by Mika Kousa and Pasi Eronen of - * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites - * support (see RFC 4279) to OpenSSL. - * - * No patent licenses or other rights except those expressly stated in - * the OpenSSL open source license shall be deemed granted or received - * expressly, by implication, estoppel, or otherwise. - * - * No assurances are provided by Nokia that the Contribution does not - * infringe the patent or other intellectual property rights of any third - * party or that the license provides you with all the necessary rights - * to make use of the Contribution. - * - * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN - * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA - * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY - * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR - * OTHERWISE. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -/* - * Until the key-gen callbacks are modified to use newer prototypes, we allow - * deprecated functions for openssl-internal code - */ -#ifdef OPENSSL_NO_DEPRECATED -# undef OPENSSL_NO_DEPRECATED -#endif - -#include <assert.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#if defined(_WIN32) +/* Included before async.h to avoid some warnings */ +# include <windows.h> +#endif #include <openssl/e_os2.h> -#ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -#endif +#include <openssl/async.h> +#include <openssl/ssl.h> -/* conflicts with winsock2 stuff on netware */ -#if !defined(OPENSSL_SYS_NETWARE) -# include <sys/types.h> -#endif +#ifndef OPENSSL_NO_SOCK /* * With IPv6, it looks like Digital has mixed up the proper order of @@ -175,10 +35,9 @@ typedef unsigned int u_int; #endif -#include <openssl/lhash.h> #include <openssl/bn.h> -#define USE_SOCKETS #include "apps.h" +#include "progs.h" #include <openssl/err.h> #include <openssl/pem.h> #include <openssl/x509.h> @@ -196,129 +55,44 @@ typedef unsigned int u_int; #endif #include "s_apps.h" #include "timeouts.h" - -#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) -/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ -# undef FIONBIO -#endif - -#if defined(OPENSSL_SYS_BEOS_R5) -# include <fcntl.h> +#ifdef CHARSET_EBCDIC +#include <openssl/ebcdic.h> #endif +#include "internal/sockets.h" -#ifndef OPENSSL_NO_RSA -static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength); -#endif -static int sv_body(char *hostname, int s, int stype, unsigned char *context); -static int www_body(char *hostname, int s, int stype, unsigned char *context); -static int rev_body(char *hostname, int s, int stype, unsigned char *context); +static int not_resumable_sess_cb(SSL *s, int is_forward_secure); +static int sv_body(int s, int stype, int prot, unsigned char *context); +static int www_body(int s, int stype, int prot, unsigned char *context); +static int rev_body(int s, int stype, int prot, unsigned char *context); static void close_accept_socket(void); -static void sv_usage(void); static int init_ssl_connection(SSL *s); static void print_stats(BIO *bp, SSL_CTX *ctx); -static int generate_session_id(const SSL *ssl, unsigned char *id, +static int generate_session_id(SSL *ssl, unsigned char *id, unsigned int *id_len); static void init_session_cache_ctx(SSL_CTX *sctx); static void free_sessions(void); #ifndef OPENSSL_NO_DH static DH *load_dh_param(const char *dhfile); -static DH *get_dh2048(void); -#endif - -#ifdef MONOLITH -static void s_server_init(void); #endif +static void print_connection_info(SSL *con); -#ifndef OPENSSL_NO_DH -static unsigned char dh2048_p[] = { - 0xF6,0x42,0x57,0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6, - 0xA9,0x42,0xF3,0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1, - 0x6E,0xB9,0x4B,0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9, - 0x8F,0x40,0x55,0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD, - 0xF7,0x4C,0x64,0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17, - 0xD4,0xA1,0xD3,0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F, - 0x3D,0x3D,0x8D,0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD, - 0xB8,0xAE,0x74,0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30, - 0x61,0xCE,0x7C,0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E, - 0xC7,0x01,0xAA,0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4, - 0x1A,0xF0,0xBF,0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58, - 0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B, - 0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C, - 0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B, - 0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD, - 0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C, - 0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C, - 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29, - 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B, - 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C, - 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55, - 0xE9,0x32,0x0B,0x3B, -}; - -static unsigned char dh2048_g[] = { - 0x02, -}; - -DH *get_dh2048() -{ - DH *dh; - - if ((dh = DH_new()) == NULL) - return NULL; - dh->p=BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL); - dh->g=BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL); - if (dh->p == NULL || dh->g == NULL) { - DH_free(dh); - return NULL; - } - return dh; -} -#endif - -/* static int load_CA(SSL_CTX *ctx, char *file);*/ - -#undef BUFSIZZ -#define BUFSIZZ 16*1024 -static int bufsize = BUFSIZZ; +static const int bufsize = 16 * 1024; static int accept_socket = -1; #define TEST_CERT "server.pem" -#ifndef OPENSSL_NO_TLSEXT -# define TEST_CERT2 "server2.pem" -#endif -#undef PROG -#define PROG s_server_main +#define TEST_CERT2 "server2.pem" -extern int verify_depth, verify_return_error, verify_quiet; - -static int s_server_verify = SSL_VERIFY_NONE; -static int s_server_session_id_context = 1; /* anything will do */ -static const char *s_cert_file = TEST_CERT, *s_key_file = - NULL, *s_chain_file = NULL; -#ifndef OPENSSL_NO_TLSEXT -static const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL; -#endif -static char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL; -#ifdef FIONBIO static int s_nbio = 0; -#endif static int s_nbio_test = 0; -int s_crlf = 0; +static int s_crlf = 0; static SSL_CTX *ctx = NULL; -#ifndef OPENSSL_NO_TLSEXT static SSL_CTX *ctx2 = NULL; -#endif static int www = 0; static BIO *bio_s_out = NULL; static BIO *bio_s_msg = NULL; static int s_debug = 0; -#ifndef OPENSSL_NO_TLSEXT static int s_tlsextdebug = 0; -static int s_tlsextstatus = 0; -static int cert_status_cb(SSL *s, void *arg); -#endif -static int no_resume_ephemeral = 0; static int s_msg = 0; static int s_quiet = 0; static int s_ign_eof = 0; @@ -327,26 +101,29 @@ static int s_brief = 0; static char *keymatexportlabel = NULL; static int keymatexportlen = 20; -static int hack = 0; -static char *engine_id = NULL; +static int async = 0; + static const char *session_id_prefix = NULL; +#ifndef OPENSSL_NO_DTLS static int enable_timeouts = 0; static long socket_mtu; -#ifndef OPENSSL_NO_DTLS1 -static int cert_chain = 0; #endif -#ifndef OPENSSL_NO_TLSEXT -static BIO *serverinfo_in = NULL; -static const char *s_serverinfo_file = NULL; +/* + * We define this but make it always be 0 in no-dtls builds to simplify the + * code. + */ +static int dtlslisten = 0; +static int stateless = 0; -#endif +static int early_data = 0; +static SSL_SESSION *psksess = NULL; -#ifndef OPENSSL_NO_PSK static char *psk_identity = "Client_identity"; char *psk_key = NULL; /* by default PSK is not used */ +#ifndef OPENSSL_NO_PSK static unsigned int psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len) @@ -356,7 +133,7 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, if (s_debug) BIO_printf(bio_s_out, "psk_server_cb\n"); - if (!identity) { + if (identity == NULL) { BIO_printf(bio_err, "Error: client did not send PSK identity\n"); goto out_err; } @@ -366,15 +143,15 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, /* here we could lookup the given identity e.g. from a database */ if (strcmp(identity, psk_identity) != 0) { - BIO_printf(bio_s_out, "PSK error: client identity not found" + BIO_printf(bio_s_out, "PSK warning: client identity not what we expected" " (got '%s' expected '%s')\n", identity, psk_identity); - goto out_err; - } - if (s_debug) + } else { + if (s_debug) BIO_printf(bio_s_out, "PSK client identity found\n"); + } /* convert the PSK key to binary */ - key = string_to_hex(psk_key, &key_len); + key = OPENSSL_hexstr2buf(psk_key, &key_len); if (key == NULL) { BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", psk_key); @@ -397,10 +174,65 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, out_err: if (s_debug) BIO_printf(bio_err, "Error in PSK server callback\n"); + (void)BIO_flush(bio_err); + (void)BIO_flush(bio_s_out); return 0; } #endif +#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") +#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02") + +static int psk_find_session_cb(SSL *ssl, const unsigned char *identity, + size_t identity_len, SSL_SESSION **sess) +{ + SSL_SESSION *tmpsess = NULL; + unsigned char *key; + long key_len; + const SSL_CIPHER *cipher = NULL; + + if (strlen(psk_identity) != identity_len + || memcmp(psk_identity, identity, identity_len) != 0) { + BIO_printf(bio_s_out, + "PSK warning: client identity not what we expected" + " (got '%s' expected '%s')\n", identity, psk_identity); + } + + if (psksess != NULL) { + SSL_SESSION_up_ref(psksess); + *sess = psksess; + return 1; + } + + key = OPENSSL_hexstr2buf(psk_key, &key_len); + if (key == NULL) { + BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", + psk_key); + return 0; + } + + /* We default to SHA256 */ + cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); + OPENSSL_free(key); + return 0; + } + + tmpsess = SSL_SESSION_new(); + if (tmpsess == NULL + || !SSL_SESSION_set1_master_key(tmpsess, key, key_len) + || !SSL_SESSION_set_cipher(tmpsess, cipher) + || !SSL_SESSION_set_protocol_version(tmpsess, SSL_version(ssl))) { + OPENSSL_free(key); + return 0; + } + OPENSSL_free(key); + *sess = tmpsess; + + return 1; +} + #ifndef OPENSSL_NO_SRP /* This is a context that we pass to callbacks */ typedef struct srpsrvparm_st { @@ -408,6 +240,7 @@ typedef struct srpsrvparm_st { SRP_VBASE *vb; SRP_user_pwd *user; } srpsrvparm; +static srpsrvparm srp_callback_parm; /* * This callback pretends to require some asynchronous logic in order to @@ -417,7 +250,7 @@ typedef struct srpsrvparm_st { * (which would normally occur after a worker has finished) and we set the * user parameters. */ -static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) +static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) { srpsrvparm *p = (srpsrvparm *) arg; int ret = SSL3_AL_FATAL; @@ -425,7 +258,7 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) if (p->login == NULL && p->user == NULL) { p->login = SSL_get_srp_username(s); BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); - return (-1); + return -1; } if (p->user == NULL) { @@ -444,7 +277,7 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) p->login, p->user->info); ret = SSL_ERROR_NONE; -err: + err: SRP_user_pwd_free(p->user); p->user = NULL; p->login = NULL; @@ -453,230 +286,6 @@ err: #endif -#ifdef MONOLITH -static void s_server_init(void) -{ - accept_socket = -1; - s_server_verify = SSL_VERIFY_NONE; - s_dcert_file = NULL; - s_dkey_file = NULL; - s_dchain_file = NULL; - s_cert_file = TEST_CERT; - s_key_file = NULL; - s_chain_file = NULL; -# ifndef OPENSSL_NO_TLSEXT - s_cert_file2 = TEST_CERT2; - s_key_file2 = NULL; - ctx2 = NULL; -# endif -# ifdef FIONBIO - s_nbio = 0; -# endif - s_nbio_test = 0; - ctx = NULL; - www = 0; - - bio_s_out = NULL; - s_debug = 0; - s_msg = 0; - s_quiet = 0; - s_brief = 0; - hack = 0; - engine_id = NULL; -} -#endif - -static void sv_usage(void) -{ - BIO_printf(bio_err, "usage: s_server [args ...]\n"); - BIO_printf(bio_err, "\n"); - BIO_printf(bio_err, - " -accept arg - port to accept on (default is %d)\n", PORT); - BIO_printf(bio_err, - " -verify_hostname host - check peer certificate matches \"host\"\n"); - BIO_printf(bio_err, - " -verify_email email - check peer certificate matches \"email\"\n"); - BIO_printf(bio_err, - " -verify_ip ipaddr - check peer certificate matches \"ipaddr\"\n"); - BIO_printf(bio_err, " -context arg - set session ID context\n"); - BIO_printf(bio_err, - " -verify arg - turn on peer certificate verification\n"); - BIO_printf(bio_err, - " -Verify arg - turn on peer certificate verification, must have a cert.\n"); - BIO_printf(bio_err, - " -verify_return_error - return verification errors\n"); - BIO_printf(bio_err, " -cert arg - certificate file to use\n"); - BIO_printf(bio_err, " (default is %s)\n", TEST_CERT); -#ifndef OPENSSL_NO_TLSEXT - BIO_printf(bio_err, - " -serverinfo arg - PEM serverinfo file for certificate\n"); - BIO_printf(bio_err, - " -auth - send and receive RFC 5878 TLS auth extensions and supplemental data\n"); - BIO_printf(bio_err, - " -auth_require_reneg - Do not send TLS auth extensions until renegotiation\n"); -#endif - BIO_printf(bio_err, - " -no_resumption_on_reneg - set SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION flag\n"); - BIO_printf(bio_err, - " -crl_check - check the peer certificate has not been revoked by its CA.\n" - " The CRL(s) are appended to the certificate file\n"); - BIO_printf(bio_err, - " -crl_check_all - check the peer certificate has not been revoked by its CA\n" - " or any other CRL in the CA chain. CRL(s) are appened to the\n" - " the certificate file.\n"); - BIO_printf(bio_err, - " -certform arg - certificate format (PEM or DER) PEM default\n"); - BIO_printf(bio_err, - " -key arg - Private Key file to use, in cert file if\n"); - BIO_printf(bio_err, " not specified (default is %s)\n", - TEST_CERT); - BIO_printf(bio_err, - " -keyform arg - key format (PEM, DER or ENGINE) PEM default\n"); - BIO_printf(bio_err, - " -pass arg - private key file pass phrase source\n"); - BIO_printf(bio_err, - " -dcert arg - second certificate file to use (usually for DSA)\n"); - BIO_printf(bio_err, - " -dcertform x - second certificate format (PEM or DER) PEM default\n"); - BIO_printf(bio_err, - " -dkey arg - second private key file to use (usually for DSA)\n"); - BIO_printf(bio_err, - " -dkeyform arg - second key format (PEM, DER or ENGINE) PEM default\n"); - BIO_printf(bio_err, - " -dpass arg - second private key file pass phrase source\n"); - BIO_printf(bio_err, - " -dhparam arg - DH parameter file to use, in cert file if not specified\n"); - BIO_printf(bio_err, - " or a default set of parameters is used\n"); -#ifndef OPENSSL_NO_ECDH - BIO_printf(bio_err, - " -named_curve arg - Elliptic curve name to use for ephemeral ECDH keys.\n" - " Use \"openssl ecparam -list_curves\" for all names\n" - " (default is nistp256).\n"); -#endif -#ifdef FIONBIO - BIO_printf(bio_err, " -nbio - Run with non-blocking IO\n"); -#endif - BIO_printf(bio_err, - " -nbio_test - test with the non-blocking test bio\n"); - BIO_printf(bio_err, - " -crlf - convert LF from terminal into CRLF\n"); - BIO_printf(bio_err, " -debug - Print more output\n"); - BIO_printf(bio_err, " -msg - Show protocol messages\n"); - BIO_printf(bio_err, " -state - Print the SSL states\n"); - BIO_printf(bio_err, " -CApath arg - PEM format directory of CA's\n"); - BIO_printf(bio_err, " -CAfile arg - PEM format file of CA's\n"); - BIO_printf(bio_err, - " -no_alt_chains - only ever use the first certificate chain found\n"); - BIO_printf(bio_err, - " -nocert - Don't use any certificates (Anon-DH)\n"); - BIO_printf(bio_err, - " -cipher arg - play with 'openssl ciphers' to see what goes here\n"); - BIO_printf(bio_err, " -serverpref - Use server's cipher preferences\n"); - BIO_printf(bio_err, " -quiet - No server output\n"); - BIO_printf(bio_err, " -no_tmp_rsa - Do not generate a tmp RSA key\n"); -#ifndef OPENSSL_NO_PSK - BIO_printf(bio_err, " -psk_hint arg - PSK identity hint to use\n"); - BIO_printf(bio_err, " -psk arg - PSK in hex (without 0x)\n"); -# ifndef OPENSSL_NO_JPAKE - BIO_printf(bio_err, " -jpake arg - JPAKE secret to use\n"); -# endif -#endif -#ifndef OPENSSL_NO_SRP - BIO_printf(bio_err, " -srpvfile file - The verifier file for SRP\n"); - BIO_printf(bio_err, - " -srpuserseed string - A seed string for a default user salt.\n"); -#endif - BIO_printf(bio_err, " -ssl2 - Just talk SSLv2\n"); -#ifndef OPENSSL_NO_SSL3_METHOD - BIO_printf(bio_err, " -ssl3 - Just talk SSLv3\n"); -#endif - BIO_printf(bio_err, " -tls1_2 - Just talk TLSv1.2\n"); - BIO_printf(bio_err, " -tls1_1 - Just talk TLSv1.1\n"); - BIO_printf(bio_err, " -tls1 - Just talk TLSv1\n"); - BIO_printf(bio_err, " -dtls1 - Just talk DTLSv1\n"); - BIO_printf(bio_err, " -dtls1_2 - Just talk DTLSv1.2\n"); - BIO_printf(bio_err, " -timeout - Enable timeouts\n"); - BIO_printf(bio_err, " -mtu - Set link layer MTU\n"); - BIO_printf(bio_err, " -chain - Read a certificate chain\n"); - BIO_printf(bio_err, " -no_ssl2 - Just disable SSLv2\n"); - BIO_printf(bio_err, " -no_ssl3 - Just disable SSLv3\n"); - BIO_printf(bio_err, " -no_tls1 - Just disable TLSv1\n"); - BIO_printf(bio_err, " -no_tls1_1 - Just disable TLSv1.1\n"); - BIO_printf(bio_err, " -no_tls1_2 - Just disable TLSv1.2\n"); -#ifndef OPENSSL_NO_DH - BIO_printf(bio_err, " -no_dhe - Disable ephemeral DH\n"); -#endif -#ifndef OPENSSL_NO_ECDH - BIO_printf(bio_err, " -no_ecdhe - Disable ephemeral ECDH\n"); -#endif - BIO_printf(bio_err, " -bugs - Turn on SSL bug compatibility\n"); - BIO_printf(bio_err, - " -hack - workaround for early Netscape code\n"); - BIO_printf(bio_err, - " -www - Respond to a 'GET /' with a status page\n"); - BIO_printf(bio_err, - " -WWW - Respond to a 'GET /<path> HTTP/1.0' with file ./<path>\n"); - BIO_printf(bio_err, - " -HTTP - Respond to a 'GET /<path> HTTP/1.0' with file ./<path>\n"); - BIO_printf(bio_err, - " with the assumption it contains a complete HTTP response.\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine id - Initialise and use the specified engine\n"); -#endif - BIO_printf(bio_err, - " -id_prefix arg - Generate SSL/TLS session IDs prefixed by 'arg'\n"); - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); -#ifndef OPENSSL_NO_TLSEXT - BIO_printf(bio_err, - " -servername host - servername for HostName TLS extension\n"); - BIO_printf(bio_err, - " -servername_fatal - on mismatch send fatal alert (default warning alert)\n"); - BIO_printf(bio_err, - " -cert2 arg - certificate file to use for servername\n"); - BIO_printf(bio_err, " (default is %s)\n", TEST_CERT2); - BIO_printf(bio_err, - " -key2 arg - Private Key file to use for servername, in cert file if\n"); - BIO_printf(bio_err, " not specified (default is %s)\n", - TEST_CERT2); - BIO_printf(bio_err, - " -tlsextdebug - hex dump of all TLS extensions received\n"); - BIO_printf(bio_err, - " -no_ticket - disable use of RFC4507bis session tickets\n"); - BIO_printf(bio_err, - " -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); - BIO_printf(bio_err, - " -sigalgs arg - Signature algorithms to support (colon-separated list)\n"); - BIO_printf(bio_err, - " -client_sigalgs arg - Signature algorithms to support for client \n"); - BIO_printf(bio_err, - " certificate authentication (colon-separated list)\n"); -# ifndef OPENSSL_NO_NEXTPROTONEG - BIO_printf(bio_err, - " -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n"); -# endif -# ifndef OPENSSL_NO_SRTP - BIO_printf(bio_err, - " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); -# endif - BIO_printf(bio_err, - " -alpn arg - set the advertised protocols for the ALPN extension (comma-separated list)\n"); -#endif - BIO_printf(bio_err, - " -keymatexport label - Export keying material using label\n"); - BIO_printf(bio_err, - " -keymatexportlen len - Export len bytes of keying material (default 20)\n"); - BIO_printf(bio_err, - " -status - respond to certificate status requests\n"); - BIO_printf(bio_err, - " -status_verbose - enable status request verbose printout\n"); - BIO_printf(bio_err, - " -status_timeout n - status request responder timeout\n"); - BIO_printf(bio_err, " -status_url URL - status request fallback URL\n"); -} - static int local_argc = 0; static char **local_argv; @@ -690,130 +299,134 @@ static int ebcdic_gets(BIO *bp, char *buf, int size); static int ebcdic_puts(BIO *bp, const char *str); # define BIO_TYPE_EBCDIC_FILTER (18|0x0200) -static BIO_METHOD methods_ebcdic = { - BIO_TYPE_EBCDIC_FILTER, - "EBCDIC/ASCII filter", - ebcdic_write, - ebcdic_read, - ebcdic_puts, - ebcdic_gets, - ebcdic_ctrl, - ebcdic_new, - ebcdic_free, -}; +static BIO_METHOD *methods_ebcdic = NULL; +/* This struct is "unwarranted chumminess with the compiler." */ typedef struct { size_t alloced; char buff[1]; } EBCDIC_OUTBUFF; -BIO_METHOD *BIO_f_ebcdic_filter() +static const BIO_METHOD *BIO_f_ebcdic_filter() { - return (&methods_ebcdic); + if (methods_ebcdic == NULL) { + methods_ebcdic = BIO_meth_new(BIO_TYPE_EBCDIC_FILTER, + "EBCDIC/ASCII filter"); + if (methods_ebcdic == NULL + || !BIO_meth_set_write(methods_ebcdic, ebcdic_write) + || !BIO_meth_set_read(methods_ebcdic, ebcdic_read) + || !BIO_meth_set_puts(methods_ebcdic, ebcdic_puts) + || !BIO_meth_set_gets(methods_ebcdic, ebcdic_gets) + || !BIO_meth_set_ctrl(methods_ebcdic, ebcdic_ctrl) + || !BIO_meth_set_create(methods_ebcdic, ebcdic_new) + || !BIO_meth_set_destroy(methods_ebcdic, ebcdic_free)) + return NULL; + } + return methods_ebcdic; } static int ebcdic_new(BIO *bi) { EBCDIC_OUTBUFF *wbuf; - wbuf = (EBCDIC_OUTBUFF *) OPENSSL_malloc(sizeof(EBCDIC_OUTBUFF) + 1024); - if (!wbuf) - return 0; + wbuf = app_malloc(sizeof(*wbuf) + 1024, "ebcdic wbuf"); wbuf->alloced = 1024; wbuf->buff[0] = '\0'; - bi->ptr = (char *)wbuf; - bi->init = 1; - bi->flags = 0; - return (1); + BIO_set_data(bi, wbuf); + BIO_set_init(bi, 1); + return 1; } static int ebcdic_free(BIO *a) { + EBCDIC_OUTBUFF *wbuf; + if (a == NULL) - return (0); - if (a->ptr != NULL) - OPENSSL_free(a->ptr); - a->ptr = NULL; - a->init = 0; - a->flags = 0; - return (1); + return 0; + wbuf = BIO_get_data(a); + OPENSSL_free(wbuf); + BIO_set_data(a, NULL); + BIO_set_init(a, 0); + + return 1; } static int ebcdic_read(BIO *b, char *out, int outl) { int ret = 0; + BIO *next = BIO_next(b); if (out == NULL || outl == 0) - return (0); - if (b->next_bio == NULL) - return (0); + return 0; + if (next == NULL) + return 0; - ret = BIO_read(b->next_bio, out, outl); + ret = BIO_read(next, out, outl); if (ret > 0) ascii2ebcdic(out, out, ret); - return (ret); + return ret; } static int ebcdic_write(BIO *b, const char *in, int inl) { EBCDIC_OUTBUFF *wbuf; + BIO *next = BIO_next(b); int ret = 0; int num; - unsigned char n; if ((in == NULL) || (inl <= 0)) - return (0); - if (b->next_bio == NULL) - return (0); + return 0; + if (next == NULL) + return 0; - wbuf = (EBCDIC_OUTBUFF *) b->ptr; + wbuf = (EBCDIC_OUTBUFF *) BIO_get_data(b); if (inl > (num = wbuf->alloced)) { num = num + num; /* double the size */ if (num < inl) num = inl; - wbuf = - (EBCDIC_OUTBUFF *) OPENSSL_malloc(sizeof(EBCDIC_OUTBUFF) + num); - if (!wbuf) - return 0; - OPENSSL_free(b->ptr); + OPENSSL_free(wbuf); + wbuf = app_malloc(sizeof(*wbuf) + num, "grow ebcdic wbuf"); wbuf->alloced = num; wbuf->buff[0] = '\0'; - b->ptr = (char *)wbuf; + BIO_set_data(b, wbuf); } ebcdic2ascii(wbuf->buff, in, inl); - ret = BIO_write(b->next_bio, wbuf->buff, inl); + ret = BIO_write(next, wbuf->buff, inl); - return (ret); + return ret; } static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret; + BIO *next = BIO_next(b); - if (b->next_bio == NULL) - return (0); + if (next == NULL) + return 0; switch (cmd) { case BIO_CTRL_DUP: ret = 0L; break; default: - ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + ret = BIO_ctrl(next, cmd, num, ptr); break; } - return (ret); + return ret; } static int ebcdic_gets(BIO *bp, char *buf, int size) { int i, ret = 0; - if (bp->next_bio == NULL) - return (0); + BIO *next = BIO_next(bp); + + if (next == NULL) + return 0; /* return(BIO_gets(bp->next_bio,buf,size));*/ for (i = 0; i < size - 1; ++i) { ret = ebcdic_read(bp, &buf[i], 1); @@ -831,14 +444,12 @@ static int ebcdic_gets(BIO *bp, char *buf, int size) static int ebcdic_puts(BIO *bp, const char *str) { - if (bp->next_bio == NULL) - return (0); + if (BIO_next(bp) == NULL) + return 0; return ebcdic_write(bp, str, strlen(str)); } #endif -#ifndef OPENSSL_NO_TLSEXT - /* This is a context that we pass to callbacks */ typedef struct tlsextctx_st { char *servername; @@ -846,21 +457,29 @@ typedef struct tlsextctx_st { int extension_error; } tlsextctx; -static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) +static int ssl_servername_cb(SSL *s, int *ad, void *arg) { tlsextctx *p = (tlsextctx *) arg; const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); - if (servername && p->biodebug) - BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n", - servername); - if (!p->servername) + if (servername != NULL && p->biodebug != NULL) { + const char *cp = servername; + unsigned char uc; + + BIO_printf(p->biodebug, "Hostname in TLS extension: \""); + while ((uc = *cp++) != 0) + BIO_printf(p->biodebug, + isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc); + BIO_printf(p->biodebug, "\"\n"); + } + + if (p->servername == NULL) return SSL_TLSEXT_ERR_NOACK; - if (servername) { + if (servername != NULL) { if (strcasecmp(servername, p->servername)) return p->extension_error; - if (ctx2) { + if (ctx2 != NULL) { BIO_printf(p->biodebug, "Switching server context.\n"); SSL_set_SSL_CTX(s, ctx2); } @@ -869,68 +488,57 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) } /* Structure passed to cert status callback */ - typedef struct tlsextstatusctx_st { + int timeout; + /* File to load OCSP Response from (or NULL if no file) */ + char *respin; /* Default responder to use */ char *host, *path, *port; int use_ssl; - int timeout; - BIO *err; int verbose; } tlsextstatusctx; -static tlsextstatusctx tlscstatp = { NULL, NULL, NULL, 0, -1, NULL, 0 }; +static tlsextstatusctx tlscstatp = { -1 }; + +#ifndef OPENSSL_NO_OCSP /* - * Certificate Status callback. This is called when a client includes a - * certificate status request extension. This is a simplified version. It - * examines certificates each time and makes one OCSP responder query for - * each request. A full version would store details such as the OCSP - * certificate IDs and minimise the number of OCSP responses by caching them - * until they were considered "expired". + * Helper function to get an OCSP_RESPONSE from a responder. This is a + * simplified version. It examines certificates each time and makes one OCSP + * responder query for each request. A full version would store details such as + * the OCSP certificate IDs and minimise the number of OCSP responses by caching + * them until they were considered "expired". */ - -static int cert_status_cb(SSL *s, void *arg) +static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, + OCSP_RESPONSE **resp) { - tlsextstatusctx *srctx = arg; - BIO *err = srctx->err; - char *host, *port, *path; + char *host = NULL, *port = NULL, *path = NULL; int use_ssl; - unsigned char *rspder = NULL; - int rspderlen; STACK_OF(OPENSSL_STRING) *aia = NULL; X509 *x = NULL; - X509_STORE_CTX inctx; - X509_OBJECT obj; + X509_STORE_CTX *inctx = NULL; + X509_OBJECT *obj; OCSP_REQUEST *req = NULL; - OCSP_RESPONSE *resp = NULL; OCSP_CERTID *id = NULL; STACK_OF(X509_EXTENSION) *exts; int ret = SSL_TLSEXT_ERR_NOACK; int i; -# if 0 - STACK_OF(OCSP_RESPID) *ids; - SSL_get_tlsext_status_ids(s, &ids); - BIO_printf(err, "cert_status: received %d ids\n", - sk_OCSP_RESPID_num(ids)); -# endif - if (srctx->verbose) - BIO_puts(err, "cert_status: callback called\n"); + /* Build up OCSP query from server certificate */ x = SSL_get_certificate(s); aia = X509_get1_ocsp(x); - if (aia) { + if (aia != NULL) { if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &host, &port, &path, &use_ssl)) { - BIO_puts(err, "cert_status: can't parse AIA URL\n"); + BIO_puts(bio_err, "cert_status: can't parse AIA URL\n"); goto err; } if (srctx->verbose) - BIO_printf(err, "cert_status: AIA URL: %s\n", + BIO_printf(bio_err, "cert_status: AIA URL: %s\n", sk_OPENSSL_STRING_value(aia, 0)); } else { - if (!srctx->host) { - BIO_puts(srctx->err, + if (srctx->host == NULL) { + BIO_puts(bio_err, "cert_status: no AIA and no default responder URL\n"); goto done; } @@ -940,23 +548,25 @@ static int cert_status_cb(SSL *s, void *arg) use_ssl = srctx->use_ssl; } - if (!X509_STORE_CTX_init(&inctx, + inctx = X509_STORE_CTX_new(); + if (inctx == NULL) + goto err; + if (!X509_STORE_CTX_init(inctx, SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)), NULL, NULL)) goto err; - if (X509_STORE_get_by_subject(&inctx, X509_LU_X509, - X509_get_issuer_name(x), &obj) <= 0) { - BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n"); - X509_STORE_CTX_cleanup(&inctx); + obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509, + X509_get_issuer_name(x)); + if (obj == NULL) { + BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n"); goto done; } - req = OCSP_REQUEST_new(); - if (!req) + id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj)); + X509_OBJECT_free(obj); + if (id == NULL) goto err; - id = OCSP_cert_to_id(NULL, x, obj.data.x509); - X509_free(obj.data.x509); - X509_STORE_CTX_cleanup(&inctx); - if (!id) + req = OCSP_REQUEST_new(); + if (req == NULL) goto err; if (!OCSP_request_add0_id(req, id)) goto err; @@ -968,47 +578,96 @@ static int cert_status_cb(SSL *s, void *arg) if (!OCSP_REQUEST_add_ext(req, ext, -1)) goto err; } - resp = process_responder(err, req, host, path, port, use_ssl, NULL, + *resp = process_responder(req, host, path, port, use_ssl, NULL, srctx->timeout); - if (!resp) { - BIO_puts(err, "cert_status: error querying responder\n"); + if (*resp == NULL) { + BIO_puts(bio_err, "cert_status: error querying responder\n"); goto done; } - rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); - if (rspderlen <= 0) - goto err; - SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); - if (srctx->verbose) { - BIO_puts(err, "cert_status: ocsp response sent:\n"); - OCSP_RESPONSE_print(err, resp, 2); - } + ret = SSL_TLSEXT_ERR_OK; + goto done; + + err: + ret = SSL_TLSEXT_ERR_ALERT_FATAL; done: - if (ret != SSL_TLSEXT_ERR_OK) - ERR_print_errors(err); - if (aia) { + /* + * If we parsed aia we need to free; otherwise they were copied and we + * don't + */ + if (aia != NULL) { OPENSSL_free(host); OPENSSL_free(path); OPENSSL_free(port); X509_email_free(aia); } - if (id) - OCSP_CERTID_free(id); - if (req) - OCSP_REQUEST_free(req); - if (resp) - OCSP_RESPONSE_free(resp); + OCSP_CERTID_free(id); + OCSP_REQUEST_free(req); + X509_STORE_CTX_free(inctx); return ret; +} + +/* + * Certificate Status callback. This is called when a client includes a + * certificate status request extension. The response is either obtained from a + * file, or from an OCSP responder. + */ +static int cert_status_cb(SSL *s, void *arg) +{ + tlsextstatusctx *srctx = arg; + OCSP_RESPONSE *resp = NULL; + unsigned char *rspder = NULL; + int rspderlen; + int ret = SSL_TLSEXT_ERR_ALERT_FATAL; + + if (srctx->verbose) + BIO_puts(bio_err, "cert_status: callback called\n"); + + if (srctx->respin != NULL) { + BIO *derbio = bio_open_default(srctx->respin, 'r', FORMAT_ASN1); + if (derbio == NULL) { + BIO_puts(bio_err, "cert_status: Cannot open OCSP response file\n"); + goto err; + } + resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); + BIO_free(derbio); + if (resp == NULL) { + BIO_puts(bio_err, "cert_status: Error reading OCSP response\n"); + goto err; + } + } else { + ret = get_ocsp_resp_from_responder(s, srctx, &resp); + if (ret != SSL_TLSEXT_ERR_OK) + goto err; + } + + rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); + if (rspderlen <= 0) + goto err; + + SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); + if (srctx->verbose) { + BIO_puts(bio_err, "cert_status: ocsp response sent:\n"); + OCSP_RESPONSE_print(bio_err, resp, 2); + } + + ret = SSL_TLSEXT_ERR_OK; + err: - ret = SSL_TLSEXT_ERR_ALERT_FATAL; - goto done; + if (ret != SSL_TLSEXT_ERR_OK) + ERR_print_errors(bio_err); + + OCSP_RESPONSE_free(resp); + + return ret; } +#endif -# ifndef OPENSSL_NO_NEXTPROTONEG +#ifndef OPENSSL_NO_NEXTPROTONEG /* This is the context that we pass to next_proto_cb */ typedef struct tlsextnextprotoctx_st { unsigned char *data; - unsigned int len; + size_t len; } tlsextnextprotoctx; static int next_proto_cb(SSL *s, const unsigned char **data, @@ -1021,12 +680,12 @@ static int next_proto_cb(SSL *s, const unsigned char **data, return SSL_TLSEXT_ERR_OK; } -# endif /* ndef OPENSSL_NO_NEXTPROTONEG */ +#endif /* ndef OPENSSL_NO_NEXTPROTONEG */ /* This the context that we pass to alpn_cb */ typedef struct tlsextalpnctx_st { unsigned char *data; - unsigned short len; + size_t len; } tlsextalpnctx; static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, @@ -1036,7 +695,7 @@ static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, if (!s_quiet) { /* We can assume that |in| is syntactically valid. */ - unsigned i; + unsigned int i; BIO_printf(bio_s_out, "ALPN protocols advertised by the client: "); for (i = 0; i < inlen;) { if (i) @@ -1061,633 +720,996 @@ static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, return SSL_TLSEXT_ERR_OK; } -#endif /* ndef OPENSSL_NO_TLSEXT */ -int MAIN(int, char **); +static int not_resumable_sess_cb(SSL *s, int is_forward_secure) +{ + /* disable resumption for sessions with forward secure ciphers */ + return is_forward_secure; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, + OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT, + OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL, + OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM, + OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT, + OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT, + OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE, + OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, + OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, + OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF, + OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE, + OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE, + OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE, + OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE, + OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK, + OPT_PSK_SESS, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW, + OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, OPT_SSL_CONFIG, + OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, + OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, + OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS, + OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, + OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, + OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, + OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA, + OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, + OPT_R_ENUM, + OPT_S_ENUM, + OPT_V_ENUM, + OPT_X_ENUM +} OPTION_CHOICE; -#ifndef OPENSSL_NO_JPAKE -static char *jpake_secret = NULL; -# define no_jpake !jpake_secret -#else -# define no_jpake 1 +const OPTIONS s_server_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"port", OPT_PORT, 'p', + "TCP/IP port to listen on for connections (default is " PORT ")"}, + {"accept", OPT_ACCEPT, 's', + "TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"}, +#ifdef AF_UNIX + {"unix", OPT_UNIX, 's', "Unix domain socket to accept on"}, +#endif + {"4", OPT_4, '-', "Use IPv4 only"}, + {"6", OPT_6, '-', "Use IPv6 only"}, +#ifdef AF_UNIX + {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"}, +#endif + {"context", OPT_CONTEXT, 's', "Set session ID context"}, + {"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"}, + {"Verify", OPT_UPPER_V_VERIFY, 'n', + "Turn on peer certificate verification, must have a cert"}, + {"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"}, + {"serverinfo", OPT_SERVERINFO, 's', + "PEM serverinfo file for certificate"}, + {"certform", OPT_CERTFORM, 'F', + "Certificate format (PEM or DER) PEM default"}, + {"key", OPT_KEY, 's', + "Private Key if not in -cert; default is " TEST_CERT}, + {"keyform", OPT_KEYFORM, 'f', + "Key format (PEM, DER or ENGINE) PEM default"}, + {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, + {"dcert", OPT_DCERT, '<', + "Second certificate file to use (usually for DSA)"}, + {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"}, + {"dcertform", OPT_DCERTFORM, 'F', + "Second certificate format (PEM or DER) PEM default"}, + {"dkey", OPT_DKEY, '<', + "Second private key file to use (usually for DSA)"}, + {"dkeyform", OPT_DKEYFORM, 'F', + "Second key format (PEM, DER or ENGINE) PEM default"}, + {"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"}, + {"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"}, + {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"}, + {"debug", OPT_DEBUG, '-', "Print more output"}, + {"msg", OPT_MSG, '-', "Show protocol messages"}, + {"msgfile", OPT_MSGFILE, '>', + "File to send output of -msg or -trace, instead of stdout"}, + {"state", OPT_STATE, '-', "Print the SSL states"}, + {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"}, + {"quiet", OPT_QUIET, '-', "No server output"}, + {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-', + "Disable caching and tickets if ephemeral (EC)DH is used"}, + {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"}, + {"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"}, + {"servername", OPT_SERVERNAME, 's', + "Servername for HostName TLS extension"}, + {"servername_fatal", OPT_SERVERNAME_FATAL, '-', + "mismatch send fatal alert (default warning alert)"}, + {"cert2", OPT_CERT2, '<', + "Certificate file to use for servername; default is" TEST_CERT2}, + {"key2", OPT_KEY2, '<', + "-Private Key file to use for servername if not in -cert2"}, + {"tlsextdebug", OPT_TLSEXTDEBUG, '-', + "Hex dump of all TLS extensions received"}, + {"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"}, + {"id_prefix", OPT_ID_PREFIX, 's', + "Generate SSL/TLS session IDs prefixed by arg"}, + OPT_R_OPTIONS, + {"keymatexport", OPT_KEYMATEXPORT, 's', + "Export keying material using label"}, + {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', + "Export len bytes of keying material (default 20)"}, + {"CRL", OPT_CRL, '<', "CRL file to use"}, + {"crl_download", OPT_CRL_DOWNLOAD, '-', + "Download CRL from distribution points"}, + {"cert_chain", OPT_CERT_CHAIN, '<', + "certificate chain file in PEM format"}, + {"dcert_chain", OPT_DCERT_CHAIN, '<', + "second certificate chain file in PEM format"}, + {"chainCApath", OPT_CHAINCAPATH, '/', + "use dir as certificate store path to build CA certificate chain"}, + {"verifyCApath", OPT_VERIFYCAPATH, '/', + "use dir as certificate store path to verify CA certificate"}, + {"no_cache", OPT_NO_CACHE, '-', "Disable session cache"}, + {"ext_cache", OPT_EXT_CACHE, '-', + "Disable internal cache, setup and use external cache"}, + {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"}, + {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', + "Close connection on verification error"}, + {"verify_quiet", OPT_VERIFY_QUIET, '-', + "No verify output except verify errors"}, + {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"}, + {"chainCAfile", OPT_CHAINCAFILE, '<', + "CA file for certificate chain (PEM format)"}, + {"verifyCAfile", OPT_VERIFYCAFILE, '<', + "CA file for certificate verification (PEM format)"}, + {"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"}, + {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"}, +#ifndef OPENSSL_NO_OCSP + {"status", OPT_STATUS, '-', "Request certificate status from server"}, + {"status_verbose", OPT_STATUS_VERBOSE, '-', + "Print more output in certificate status callback"}, + {"status_timeout", OPT_STATUS_TIMEOUT, 'n', + "Status request responder timeout"}, + {"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"}, + {"status_file", OPT_STATUS_FILE, '<', + "File containing DER encoded OCSP Response"}, +#endif +#ifndef OPENSSL_NO_SSL_TRACE + {"trace", OPT_TRACE, '-', "trace protocol messages"}, +#endif + {"security_debug", OPT_SECURITY_DEBUG, '-', + "Print output from SSL/TLS security framework"}, + {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-', + "Print more output from SSL/TLS security framework"}, + {"brief", OPT_BRIEF, '-', + "Restrict output to brief summary of connection parameters"}, + {"rev", OPT_REV, '-', + "act as a simple test server which just sends back with the received text reversed"}, + {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"}, + {"ssl_config", OPT_SSL_CONFIG, 's', + "Configure SSL_CTX using the configuration 'val'"}, + {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, + {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', + "Size used to split data for encrypt pipelines"}, + {"max_pipelines", OPT_MAX_PIPELINES, 'p', + "Maximum number of encrypt/decrypt pipelines to be used"}, + {"read_buf", OPT_READ_BUF, 'p', + "Default read buffer size to be used for connections"}, + OPT_S_OPTIONS, + OPT_V_OPTIONS, + OPT_X_OPTIONS, + {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, + {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"}, +#ifndef OPENSSL_NO_PSK + {"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"}, #endif + {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, + {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, #ifndef OPENSSL_NO_SRP -static srpsrvparm srp_callback_parm; + {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"}, + {"srpuserseed", OPT_SRPUSERSEED, 's', + "A seed string for a default user salt"}, +#endif +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"}, +#endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "Just talk TLSv1"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"}, +#endif +#ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "just talk TLSv1.3"}, +#endif +#ifndef OPENSSL_NO_DTLS + {"dtls", OPT_DTLS, '-', "Use any DTLS version"}, + {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"}, + {"mtu", OPT_MTU, 'p', "Set link layer MTU"}, + {"listen", OPT_LISTEN, '-', + "Listen for a DTLS ClientHello with a cookie and then connect"}, +#endif + {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"}, +#ifndef OPENSSL_NO_DTLS1 + {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"}, +#endif +#ifndef OPENSSL_NO_DTLS1_2 + {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"}, +#endif +#ifndef OPENSSL_NO_SCTP + {"sctp", OPT_SCTP, '-', "Use SCTP"}, +#endif +#ifndef OPENSSL_NO_DH + {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"}, +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + {"nextprotoneg", OPT_NEXTPROTONEG, 's', + "Set the advertised protocols for the NPN extension (comma-separated list)"}, #endif #ifndef OPENSSL_NO_SRTP -static char *srtp_profiles = NULL; + {"use_srtp", OPT_SRTP_PROFILES, 's', + "Offer SRTP key management with a colon-separated profile list"}, #endif + {"alpn", OPT_ALPN, 's', + "Set the advertised protocols for the ALPN extension (comma-separated list)"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, + {"max_early_data", OPT_MAX_EARLY, 'n', + "The maximum number of bytes of early data as advertised in tickets"}, + {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n', + "The maximum number of bytes of early data (hard limit)"}, + {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"}, + {"num_tickets", OPT_S_NUM_TICKETS, 'n', + "The number of TLSv1.3 session tickets that a server will automatically issue" }, + {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"}, + {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"}, + {NULL, OPT_EOF, 0, NULL} +}; + +#define IS_PROT_FLAG(o) \ + (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \ + || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2) -int MAIN(int argc, char *argv[]) +int s_server_main(int argc, char *argv[]) { + ENGINE *engine = NULL; + EVP_PKEY *s_key = NULL, *s_dkey = NULL; + SSL_CONF_CTX *cctx = NULL; + const SSL_METHOD *meth = TLS_server_method(); + SSL_EXCERT *exc = NULL; + STACK_OF(OPENSSL_STRING) *ssl_args = NULL; + STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL; + STACK_OF(X509_CRL) *crls = NULL; + X509 *s_cert = NULL, *s_dcert = NULL; X509_VERIFY_PARAM *vpm = NULL; - int badarg = 0; - short port = PORT; - char *CApath = NULL, *CAfile = NULL; - char *chCApath = NULL, *chCAfile = NULL; - char *vfyCApath = NULL, *vfyCAfile = NULL; - unsigned char *context = NULL; + const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL; + char *dpassarg = NULL, *dpass = NULL; + char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; + char *crl_file = NULL, *prog; +#ifdef AF_UNIX + int unlink_unix_path = 0; +#endif + do_server_cb server_cb; + int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0; +#ifndef OPENSSL_NO_DH char *dhfile = NULL; - int badop = 0; - int ret = 1; - int build_chain = 0; - int no_tmp_rsa = 0, no_dhe = 0, no_ecdhe = 0, nocert = 0; - int state = 0; - const SSL_METHOD *meth = NULL; - int socket_type = SOCK_STREAM; - ENGINE *e = NULL; - char *inrand = NULL; + int no_dhe = 0; +#endif + int nocert = 0, ret = 1; + int noCApath = 0, noCAfile = 0; int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM; - char *passarg = NULL, *pass = NULL; - char *dpassarg = NULL, *dpass = NULL; int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM; - X509 *s_cert = NULL, *s_dcert = NULL; - STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL; - EVP_PKEY *s_key = NULL, *s_dkey = NULL; - int no_cache = 0, ext_cache = 0; - int rev = 0, naccept = -1; -#ifndef OPENSSL_NO_TLSEXT + int rev = 0, naccept = -1, sdebug = 0; + int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; + int state = 0, crl_format = FORMAT_PEM, crl_download = 0; + char *host = NULL; + char *port = BUF_strdup(PORT); + unsigned char *context = NULL; + OPTION_CHOICE o; EVP_PKEY *s_key2 = NULL; X509 *s_cert2 = NULL; tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING }; -# ifndef OPENSSL_NO_NEXTPROTONEG + const char *ssl_config = NULL; + int read_buf_len = 0; +#ifndef OPENSSL_NO_NEXTPROTONEG const char *next_proto_neg_in = NULL; tlsextnextprotoctx next_proto = { NULL, 0 }; -# endif +#endif const char *alpn_in = NULL; tlsextalpnctx alpn_ctx = { NULL, 0 }; -#endif #ifndef OPENSSL_NO_PSK /* by default do not send a PSK identity hint */ - static char *psk_identity_hint = NULL; + char *psk_identity_hint = NULL; #endif + char *p; #ifndef OPENSSL_NO_SRP char *srpuserseed = NULL; char *srp_verifier_file = NULL; #endif - SSL_EXCERT *exc = NULL; - SSL_CONF_CTX *cctx = NULL; - STACK_OF(OPENSSL_STRING) *ssl_args = NULL; - - char *crl_file = NULL; - int crl_format = FORMAT_PEM; - int crl_download = 0; - STACK_OF(X509_CRL) *crls = NULL; - int prot_opt = 0, no_prot_opt = 0; - - meth = SSLv23_server_method(); +#ifndef OPENSSL_NO_SRTP + char *srtp_profiles = NULL; +#endif + int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0; + int s_server_verify = SSL_VERIFY_NONE; + int s_server_session_id_context = 1; /* anything will do */ + const char *s_cert_file = TEST_CERT, *s_key_file = NULL, *s_chain_file = NULL; + const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL; + char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL; +#ifndef OPENSSL_NO_OCSP + int s_tlsextstatus = 0; +#endif + int no_resume_ephemeral = 0; + unsigned int max_send_fragment = 0; + unsigned int split_send_fragment = 0, max_pipelines = 0; + const char *s_serverinfo_file = NULL; + const char *keylog_file = NULL; + int max_early_data = -1, recv_max_early_data = -1; + char *psksessf = NULL; + /* Init of few remaining global variables */ local_argc = argc; local_argv = argv; - apps_startup(); -#ifdef MONOLITH - s_server_init(); -#endif - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; + ctx = ctx2 = NULL; + s_nbio = s_nbio_test = 0; + www = 0; + bio_s_out = NULL; + s_debug = 0; + s_msg = 0; + s_quiet = 0; + s_brief = 0; + async = 0; cctx = SSL_CONF_CTX_new(); - if (!cctx) + vpm = X509_VERIFY_PARAM_new(); + if (cctx == NULL || vpm == NULL) goto end; - SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); - SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CMDLINE); - - verify_depth = 0; -#ifdef FIONBIO - s_nbio = 0; -#endif - s_nbio_test = 0; + SSL_CONF_CTX_set_flags(cctx, + SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE); - argc--; - argv++; + prog = opt_init(argc, argv, s_server_options); + while ((o = opt_next()) != OPT_EOF) { + if (IS_PROT_FLAG(o) && ++prot_opt > 1) { + BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); + goto end; + } + if (IS_NO_PROT_FLAG(o)) + no_prot_opt++; + if (prot_opt == 1 && no_prot_opt) { + BIO_printf(bio_err, + "Cannot supply both a protocol flag and '-no_<prot>'\n"); + goto end; + } + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(s_server_options); + ret = 0; + goto end; - while (argc >= 1) { - if ((strcmp(*argv, "-port") == 0) || (strcmp(*argv, "-accept") == 0)) { - if (--argc < 1) - goto bad; - if (!extract_port(*(++argv), &port)) - goto bad; - } else if (strcmp(*argv, "-naccept") == 0) { - if (--argc < 1) - goto bad; - naccept = atol(*(++argv)); - if (naccept <= 0) { - BIO_printf(bio_err, "bad accept value %s\n", *argv); - goto bad; + case OPT_4: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + OPENSSL_free(host); host = NULL; + OPENSSL_free(port); port = NULL; } - } else if (strcmp(*argv, "-verify") == 0) { +#endif + socket_family = AF_INET; + break; + case OPT_6: + if (1) { +#ifdef AF_INET6 +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + OPENSSL_free(host); host = NULL; + OPENSSL_free(port); port = NULL; + } +#endif + socket_family = AF_INET6; + } else { +#endif + BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog); + goto end; + } + break; + case OPT_PORT: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + socket_family = AF_UNSPEC; + } +#endif + OPENSSL_free(port); port = NULL; + OPENSSL_free(host); host = NULL; + if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) { + BIO_printf(bio_err, + "%s: -port argument malformed or ambiguous\n", + port); + goto end; + } + break; + case OPT_ACCEPT: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + socket_family = AF_UNSPEC; + } +#endif + OPENSSL_free(port); port = NULL; + OPENSSL_free(host); host = NULL; + if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) { + BIO_printf(bio_err, + "%s: -accept argument malformed or ambiguous\n", + port); + goto end; + } + break; +#ifdef AF_UNIX + case OPT_UNIX: + socket_family = AF_UNIX; + OPENSSL_free(host); host = BUF_strdup(opt_arg()); + OPENSSL_free(port); port = NULL; + break; + case OPT_UNLINK: + unlink_unix_path = 1; + break; +#endif + case OPT_NACCEPT: + naccept = atol(opt_arg()); + break; + case OPT_VERIFY: s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; - if (--argc < 1) - goto bad; - verify_depth = atoi(*(++argv)); + verify_args.depth = atoi(opt_arg()); if (!s_quiet) - BIO_printf(bio_err, "verify depth is %d\n", verify_depth); - } else if (strcmp(*argv, "-Verify") == 0) { + BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth); + break; + case OPT_UPPER_V_VERIFY: s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE; - if (--argc < 1) - goto bad; - verify_depth = atoi(*(++argv)); + verify_args.depth = atoi(opt_arg()); if (!s_quiet) BIO_printf(bio_err, "verify depth is %d, must return a certificate\n", - verify_depth); - } else if (strcmp(*argv, "-context") == 0) { - if (--argc < 1) - goto bad; - context = (unsigned char *)*(++argv); - } else if (strcmp(*argv, "-cert") == 0) { - if (--argc < 1) - goto bad; - s_cert_file = *(++argv); - } else if (strcmp(*argv, "-CRL") == 0) { - if (--argc < 1) - goto bad; - crl_file = *(++argv); - } else if (strcmp(*argv, "-crl_download") == 0) + verify_args.depth); + break; + case OPT_CONTEXT: + context = (unsigned char *)opt_arg(); + break; + case OPT_CERT: + s_cert_file = opt_arg(); + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_CRL: + crl_file = opt_arg(); + break; + case OPT_CRL_DOWNLOAD: crl_download = 1; -#ifndef OPENSSL_NO_TLSEXT - else if (strcmp(*argv, "-serverinfo") == 0) { - if (--argc < 1) - goto bad; - s_serverinfo_file = *(++argv); - } + break; + case OPT_SERVERINFO: + s_serverinfo_file = opt_arg(); + break; + case OPT_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format)) + goto opthelp; + break; + case OPT_KEY: + s_key_file = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_key_format)) + goto opthelp; + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_CERT_CHAIN: + s_chain_file = opt_arg(); + break; + case OPT_DHPARAM: +#ifndef OPENSSL_NO_DH + dhfile = opt_arg(); #endif - else if (strcmp(*argv, "-certform") == 0) { - if (--argc < 1) - goto bad; - s_cert_format = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-key") == 0) { - if (--argc < 1) - goto bad; - s_key_file = *(++argv); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - goto bad; - s_key_format = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-pass") == 0) { - if (--argc < 1) - goto bad; - passarg = *(++argv); - } else if (strcmp(*argv, "-cert_chain") == 0) { - if (--argc < 1) - goto bad; - s_chain_file = *(++argv); - } else if (strcmp(*argv, "-dhparam") == 0) { - if (--argc < 1) - goto bad; - dhfile = *(++argv); - } else if (strcmp(*argv, "-dcertform") == 0) { - if (--argc < 1) - goto bad; - s_dcert_format = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-dcert") == 0) { - if (--argc < 1) - goto bad; - s_dcert_file = *(++argv); - } else if (strcmp(*argv, "-dkeyform") == 0) { - if (--argc < 1) - goto bad; - s_dkey_format = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-dpass") == 0) { - if (--argc < 1) - goto bad; - dpassarg = *(++argv); - } else if (strcmp(*argv, "-dkey") == 0) { - if (--argc < 1) - goto bad; - s_dkey_file = *(++argv); - } else if (strcmp(*argv, "-dcert_chain") == 0) { - if (--argc < 1) - goto bad; - s_dchain_file = *(++argv); - } else if (strcmp(*argv, "-nocert") == 0) { + break; + case OPT_DCERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format)) + goto opthelp; + break; + case OPT_DCERT: + s_dcert_file = opt_arg(); + break; + case OPT_DKEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dkey_format)) + goto opthelp; + break; + case OPT_DPASS: + dpassarg = opt_arg(); + break; + case OPT_DKEY: + s_dkey_file = opt_arg(); + break; + case OPT_DCERT_CHAIN: + s_dchain_file = opt_arg(); + break; + case OPT_NOCERT: nocert = 1; - } else if (strcmp(*argv, "-CApath") == 0) { - if (--argc < 1) - goto bad; - CApath = *(++argv); - } else if (strcmp(*argv, "-chainCApath") == 0) { - if (--argc < 1) - goto bad; - chCApath = *(++argv); - } else if (strcmp(*argv, "-verifyCApath") == 0) { - if (--argc < 1) - goto bad; - vfyCApath = *(++argv); - } else if (strcmp(*argv, "-no_cache") == 0) + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_CHAINCAPATH: + chCApath = opt_arg(); + break; + case OPT_VERIFYCAPATH: + vfyCApath = opt_arg(); + break; + case OPT_NO_CACHE: no_cache = 1; - else if (strcmp(*argv, "-ext_cache") == 0) + break; + case OPT_EXT_CACHE: ext_cache = 1; - else if (strcmp(*argv, "-CRLform") == 0) { - if (--argc < 1) - goto bad; - crl_format = str2fmt(*(++argv)); - } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { - if (badarg) - goto bad; - continue; - } else if (args_excert(&argv, &argc, &badarg, bio_err, &exc)) { - if (badarg) - goto bad; - continue; - } else if (args_ssl(&argv, &argc, cctx, &badarg, bio_err, &ssl_args, - &no_prot_opt)) { - if (badarg) - goto bad; - continue; - } else if (strcmp(*argv, "-verify_return_error") == 0) - verify_return_error = 1; - else if (strcmp(*argv, "-verify_quiet") == 0) - verify_quiet = 1; - else if (strcmp(*argv, "-build_chain") == 0) + break; + case OPT_CRLFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format)) + goto opthelp; + break; + case OPT_S_CASES: + case OPT_S_NUM_TICKETS: + case OPT_ANTI_REPLAY: + case OPT_NO_ANTI_REPLAY: + if (ssl_args == NULL) + ssl_args = sk_OPENSSL_STRING_new_null(); + if (ssl_args == NULL + || !sk_OPENSSL_STRING_push(ssl_args, opt_flag()) + || !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_X_CASES: + if (!args_excert(o, &exc)) + goto end; + break; + case OPT_VERIFY_RET_ERROR: + verify_args.return_error = 1; + break; + case OPT_VERIFY_QUIET: + verify_args.quiet = 1; + break; + case OPT_BUILD_CHAIN: build_chain = 1; - else if (strcmp(*argv, "-CAfile") == 0) { - if (--argc < 1) - goto bad; - CAfile = *(++argv); - } else if (strcmp(*argv, "-chainCAfile") == 0) { - if (--argc < 1) - goto bad; - chCAfile = *(++argv); - } else if (strcmp(*argv, "-verifyCAfile") == 0) { - if (--argc < 1) - goto bad; - vfyCAfile = *(++argv); - } -#ifdef FIONBIO - else if (strcmp(*argv, "-nbio") == 0) { - s_nbio = 1; - } -#endif - else if (strcmp(*argv, "-nbio_test") == 0) { -#ifdef FIONBIO + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_CHAINCAFILE: + chCAfile = opt_arg(); + break; + case OPT_VERIFYCAFILE: + vfyCAfile = opt_arg(); + break; + case OPT_NBIO: s_nbio = 1; -#endif - s_nbio_test = 1; - } else if (strcmp(*argv, "-ign_eof") == 0) + break; + case OPT_NBIO_TEST: + s_nbio = s_nbio_test = 1; + break; + case OPT_IGN_EOF: s_ign_eof = 1; - else if (strcmp(*argv, "-no_ign_eof") == 0) + break; + case OPT_NO_IGN_EOF: s_ign_eof = 0; - else if (strcmp(*argv, "-debug") == 0) { + break; + case OPT_DEBUG: s_debug = 1; - } -#ifndef OPENSSL_NO_TLSEXT - else if (strcmp(*argv, "-tlsextdebug") == 0) + break; + case OPT_TLSEXTDEBUG: s_tlsextdebug = 1; - else if (strcmp(*argv, "-status") == 0) - s_tlsextstatus = 1; - else if (strcmp(*argv, "-status_verbose") == 0) { + break; + case OPT_STATUS: +#ifndef OPENSSL_NO_OCSP s_tlsextstatus = 1; - tlscstatp.verbose = 1; - } else if (!strcmp(*argv, "-status_timeout")) { +#endif + break; + case OPT_STATUS_VERBOSE: +#ifndef OPENSSL_NO_OCSP + s_tlsextstatus = tlscstatp.verbose = 1; +#endif + break; + case OPT_STATUS_TIMEOUT: +#ifndef OPENSSL_NO_OCSP s_tlsextstatus = 1; - if (--argc < 1) - goto bad; - tlscstatp.timeout = atoi(*(++argv)); - } else if (!strcmp(*argv, "-status_url")) { + tlscstatp.timeout = atoi(opt_arg()); +#endif + break; + case OPT_STATUS_URL: +#ifndef OPENSSL_NO_OCSP s_tlsextstatus = 1; - if (--argc < 1) - goto bad; - if (!OCSP_parse_url(*(++argv), + if (!OCSP_parse_url(opt_arg(), &tlscstatp.host, &tlscstatp.port, &tlscstatp.path, &tlscstatp.use_ssl)) { BIO_printf(bio_err, "Error parsing URL\n"); - goto bad; + goto end; } - } #endif - else if (strcmp(*argv, "-msg") == 0) { + break; + case OPT_STATUS_FILE: +#ifndef OPENSSL_NO_OCSP + s_tlsextstatus = 1; + tlscstatp.respin = opt_arg(); +#endif + break; + case OPT_MSG: s_msg = 1; - } else if (strcmp(*argv, "-msgfile") == 0) { - if (--argc < 1) - goto bad; - bio_s_msg = BIO_new_file(*(++argv), "w"); - } + break; + case OPT_MSGFILE: + bio_s_msg = BIO_new_file(opt_arg(), "w"); + break; + case OPT_TRACE: #ifndef OPENSSL_NO_SSL_TRACE - else if (strcmp(*argv, "-trace") == 0) { s_msg = 2; - } #endif - else if (strcmp(*argv, "-hack") == 0) { - hack = 1; - } else if (strcmp(*argv, "-state") == 0) { + break; + case OPT_SECURITY_DEBUG: + sdebug = 1; + break; + case OPT_SECURITY_DEBUG_VERBOSE: + sdebug = 2; + break; + case OPT_STATE: state = 1; - } else if (strcmp(*argv, "-crlf") == 0) { + break; + case OPT_CRLF: s_crlf = 1; - } else if (strcmp(*argv, "-quiet") == 0) { - s_quiet = 1; - } else if (strcmp(*argv, "-brief") == 0) { + break; + case OPT_QUIET: s_quiet = 1; - s_brief = 1; - verify_quiet = 1; - } else if (strcmp(*argv, "-no_tmp_rsa") == 0) { - no_tmp_rsa = 1; - } else if (strcmp(*argv, "-no_dhe") == 0) { + break; + case OPT_BRIEF: + s_quiet = s_brief = verify_args.quiet = 1; + break; + case OPT_NO_DHE: +#ifndef OPENSSL_NO_DH no_dhe = 1; - } else if (strcmp(*argv, "-no_ecdhe") == 0) { - no_ecdhe = 1; - } else if (strcmp(*argv, "-no_resume_ephemeral") == 0) { +#endif + break; + case OPT_NO_RESUME_EPHEMERAL: no_resume_ephemeral = 1; - } + break; + case OPT_PSK_IDENTITY: + psk_identity = opt_arg(); + break; + case OPT_PSK_HINT: #ifndef OPENSSL_NO_PSK - else if (strcmp(*argv, "-psk_hint") == 0) { - if (--argc < 1) - goto bad; - psk_identity_hint = *(++argv); - } else if (strcmp(*argv, "-psk") == 0) { - size_t i; - - if (--argc < 1) - goto bad; - psk_key = *(++argv); - for (i = 0; i < strlen(psk_key); i++) { - if (isxdigit((unsigned char)psk_key[i])) + psk_identity_hint = opt_arg(); +#endif + break; + case OPT_PSK: + for (p = psk_key = opt_arg(); *p; p++) { + if (isxdigit(_UC(*p))) continue; BIO_printf(bio_err, "Not a hex number '%s'\n", *argv); - goto bad; + goto end; } - } + break; + case OPT_PSK_SESS: + psksessf = opt_arg(); + break; + case OPT_SRPVFILE: +#ifndef OPENSSL_NO_SRP + srp_verifier_file = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; #endif + break; + case OPT_SRPUSERSEED: #ifndef OPENSSL_NO_SRP - else if (strcmp(*argv, "-srpvfile") == 0) { - if (--argc < 1) - goto bad; - srp_verifier_file = *(++argv); - meth = TLSv1_server_method(); - } else if (strcmp(*argv, "-srpuserseed") == 0) { - if (--argc < 1) - goto bad; - srpuserseed = *(++argv); - meth = TLSv1_server_method(); - } + srpuserseed = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; #endif - else if (strcmp(*argv, "-rev") == 0) { + break; + case OPT_REV: rev = 1; - } else if (strcmp(*argv, "-www") == 0) { + break; + case OPT_WWW: www = 1; - } else if (strcmp(*argv, "-WWW") == 0) { + break; + case OPT_UPPER_WWW: www = 2; - } else if (strcmp(*argv, "-HTTP") == 0) { + break; + case OPT_HTTP: www = 3; - } -#ifndef OPENSSL_NO_SSL2 - else if (strcmp(*argv, "-ssl2") == 0) { - no_ecdhe = 1; - meth = SSLv2_server_method(); - prot_opt++; - } -#endif -#ifndef OPENSSL_NO_SSL3_METHOD - else if (strcmp(*argv, "-ssl3") == 0) { - meth = SSLv3_server_method(); - prot_opt++; - } -#endif -#ifndef OPENSSL_NO_TLS1 - else if (strcmp(*argv, "-tls1") == 0) { - meth = TLSv1_server_method(); - prot_opt++; - } else if (strcmp(*argv, "-tls1_1") == 0) { - meth = TLSv1_1_server_method(); - prot_opt++; - } else if (strcmp(*argv, "-tls1_2") == 0) { - meth = TLSv1_2_server_method(); - prot_opt++; - } -#endif -#ifndef OPENSSL_NO_DTLS1 - else if (strcmp(*argv, "-dtls") == 0) { + break; + case OPT_SSL_CONFIG: + ssl_config = opt_arg(); + break; + case OPT_SSL3: + min_version = SSL3_VERSION; + max_version = SSL3_VERSION; + break; + case OPT_TLS1_3: + min_version = TLS1_3_VERSION; + max_version = TLS1_3_VERSION; + break; + case OPT_TLS1_2: + min_version = TLS1_2_VERSION; + max_version = TLS1_2_VERSION; + break; + case OPT_TLS1_1: + min_version = TLS1_1_VERSION; + max_version = TLS1_1_VERSION; + break; + case OPT_TLS1: + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + break; + case OPT_DTLS: +#ifndef OPENSSL_NO_DTLS meth = DTLS_server_method(); socket_type = SOCK_DGRAM; - prot_opt++; - } else if (strcmp(*argv, "-dtls1") == 0) { - meth = DTLSv1_server_method(); +#endif + break; + case OPT_DTLS1: +#ifndef OPENSSL_NO_DTLS + meth = DTLS_server_method(); + min_version = DTLS1_VERSION; + max_version = DTLS1_VERSION; socket_type = SOCK_DGRAM; - prot_opt++; - } else if (strcmp(*argv, "-dtls1_2") == 0) { - meth = DTLSv1_2_server_method(); +#endif + break; + case OPT_DTLS1_2: +#ifndef OPENSSL_NO_DTLS + meth = DTLS_server_method(); + min_version = DTLS1_2_VERSION; + max_version = DTLS1_2_VERSION; socket_type = SOCK_DGRAM; - prot_opt++; - } else if (strcmp(*argv, "-timeout") == 0) +#endif + break; + case OPT_SCTP: +#ifndef OPENSSL_NO_SCTP + protocol = IPPROTO_SCTP; +#endif + break; + case OPT_TIMEOUT: +#ifndef OPENSSL_NO_DTLS enable_timeouts = 1; - else if (strcmp(*argv, "-mtu") == 0) { - if (--argc < 1) - goto bad; - socket_mtu = atol(*(++argv)); - } else if (strcmp(*argv, "-chain") == 0) - cert_chain = 1; #endif - else if (strcmp(*argv, "-id_prefix") == 0) { - if (--argc < 1) - goto bad; - session_id_prefix = *(++argv); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine_id = *(++argv); - } + break; + case OPT_MTU: +#ifndef OPENSSL_NO_DTLS + socket_mtu = atol(opt_arg()); #endif - else if (strcmp(*argv, "-rand") == 0) { - if (--argc < 1) - goto bad; - inrand = *(++argv); - } -#ifndef OPENSSL_NO_TLSEXT - else if (strcmp(*argv, "-servername") == 0) { - if (--argc < 1) - goto bad; - tlsextcbp.servername = *(++argv); - } else if (strcmp(*argv, "-servername_fatal") == 0) { + break; + case OPT_LISTEN: +#ifndef OPENSSL_NO_DTLS + dtlslisten = 1; +#endif + break; + case OPT_STATELESS: + stateless = 1; + break; + case OPT_ID_PREFIX: + session_id_prefix = opt_arg(); + break; + case OPT_ENGINE: + engine = setup_engine(opt_arg(), 1); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_SERVERNAME: + tlsextcbp.servername = opt_arg(); + break; + case OPT_SERVERNAME_FATAL: tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL; - } else if (strcmp(*argv, "-cert2") == 0) { - if (--argc < 1) - goto bad; - s_cert_file2 = *(++argv); - } else if (strcmp(*argv, "-key2") == 0) { - if (--argc < 1) - goto bad; - s_key_file2 = *(++argv); - } + break; + case OPT_CERT2: + s_cert_file2 = opt_arg(); + break; + case OPT_KEY2: + s_key_file2 = opt_arg(); + break; + case OPT_NEXTPROTONEG: # ifndef OPENSSL_NO_NEXTPROTONEG - else if (strcmp(*argv, "-nextprotoneg") == 0) { - if (--argc < 1) - goto bad; - next_proto_neg_in = *(++argv); - } -# endif - else if (strcmp(*argv, "-alpn") == 0) { - if (--argc < 1) - goto bad; - alpn_in = *(++argv); - } -#endif -#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) - else if (strcmp(*argv, "-jpake") == 0) { - if (--argc < 1) - goto bad; - jpake_secret = *(++argv); - } + next_proto_neg_in = opt_arg(); #endif + break; + case OPT_ALPN: + alpn_in = opt_arg(); + break; + case OPT_SRTP_PROFILES: #ifndef OPENSSL_NO_SRTP - else if (strcmp(*argv, "-use_srtp") == 0) { - if (--argc < 1) - goto bad; - srtp_profiles = *(++argv); - } + srtp_profiles = opt_arg(); #endif - else if (strcmp(*argv, "-keymatexport") == 0) { - if (--argc < 1) - goto bad; - keymatexportlabel = *(++argv); - } else if (strcmp(*argv, "-keymatexportlen") == 0) { - if (--argc < 1) - goto bad; - keymatexportlen = atoi(*(++argv)); - if (keymatexportlen == 0) - goto bad; - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badop = 1; + break; + case OPT_KEYMATEXPORT: + keymatexportlabel = opt_arg(); + break; + case OPT_KEYMATEXPORTLEN: + keymatexportlen = atoi(opt_arg()); + break; + case OPT_ASYNC: + async = 1; + break; + case OPT_MAX_SEND_FRAG: + max_send_fragment = atoi(opt_arg()); + break; + case OPT_SPLIT_SEND_FRAG: + split_send_fragment = atoi(opt_arg()); + break; + case OPT_MAX_PIPELINES: + max_pipelines = atoi(opt_arg()); + break; + case OPT_READ_BUF: + read_buf_len = atoi(opt_arg()); + break; + case OPT_KEYLOG_FILE: + keylog_file = opt_arg(); + break; + case OPT_MAX_EARLY: + max_early_data = atoi(opt_arg()); + if (max_early_data < 0) { + BIO_printf(bio_err, "Invalid value for max_early_data\n"); + goto end; + } + break; + case OPT_RECV_MAX_EARLY: + recv_max_early_data = atoi(opt_arg()); + if (recv_max_early_data < 0) { + BIO_printf(bio_err, "Invalid value for recv_max_early_data\n"); + goto end; + } + break; + case OPT_EARLY_DATA: + early_data = 1; + if (max_early_data == -1) + max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; break; } - argc--; - argv++; } - if (badop) { - bad: - sv_usage(); - goto end; + argc = opt_num_rest(); + argv = opt_rest(); + +#ifndef OPENSSL_NO_NEXTPROTONEG + if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { + BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n"); + goto opthelp; } -#ifndef OPENSSL_NO_DTLS1 +#endif +#ifndef OPENSSL_NO_DTLS if (www && socket_type == SOCK_DGRAM) { BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n"); goto end; } -#endif -#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) - if (jpake_secret) { - if (psk_key) { - BIO_printf(bio_err, "Can't use JPAKE and PSK together\n"); - goto end; - } - psk_identity = "JPAKE"; + if (dtlslisten && socket_type != SOCK_DGRAM) { + BIO_printf(bio_err, "Can only use -listen with DTLS\n"); + goto end; } #endif - if (prot_opt > 1) { - BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); + if (stateless && socket_type != SOCK_STREAM) { + BIO_printf(bio_err, "Can only use --stateless with TLS\n"); goto end; } - if (prot_opt == 1 && no_prot_opt) { - BIO_printf(bio_err, "Cannot supply both a protocol flag and " - "\"-no_<prot>\"\n"); +#ifdef AF_UNIX + if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) { + BIO_printf(bio_err, + "Can't use unix sockets and datagrams together\n"); goto end; } +#endif - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); - - e = setup_engine(bio_err, engine_id, 1); +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + if (socket_type != SOCK_DGRAM) { + BIO_printf(bio_err, "Can't use -sctp without DTLS\n"); + goto end; + } + /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */ + socket_type = SOCK_STREAM; + } +#endif - if (!app_passwd(bio_err, passarg, dpassarg, &pass, &dpass)) { + if (!app_passwd(passarg, dpassarg, &pass, &dpass)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (s_key_file == NULL) s_key_file = s_cert_file; -#ifndef OPENSSL_NO_TLSEXT + if (s_key_file2 == NULL) s_key_file2 = s_cert_file2; -#endif - if (!load_excert(&exc, bio_err)) + if (!load_excert(&exc)) goto end; if (nocert == 0) { - s_key = load_key(bio_err, s_key_file, s_key_format, 0, pass, e, + s_key = load_key(s_key_file, s_key_format, 0, pass, engine, "server certificate private key file"); - if (!s_key) { + if (s_key == NULL) { ERR_print_errors(bio_err); goto end; } - s_cert = load_cert(bio_err, s_cert_file, s_cert_format, - NULL, e, "server certificate file"); + s_cert = load_cert(s_cert_file, s_cert_format, + "server certificate file"); - if (!s_cert) { + if (s_cert == NULL) { ERR_print_errors(bio_err); goto end; } - if (s_chain_file) { - s_chain = load_certs(bio_err, s_chain_file, FORMAT_PEM, - NULL, e, "server certificate chain"); - if (!s_chain) + if (s_chain_file != NULL) { + if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL, + "server certificate chain")) goto end; } -#ifndef OPENSSL_NO_TLSEXT - if (tlsextcbp.servername) { - s_key2 = load_key(bio_err, s_key_file2, s_key_format, 0, pass, e, + + if (tlsextcbp.servername != NULL) { + s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine, "second server certificate private key file"); - if (!s_key2) { + if (s_key2 == NULL) { ERR_print_errors(bio_err); goto end; } - s_cert2 = load_cert(bio_err, s_cert_file2, s_cert_format, - NULL, e, "second server certificate file"); + s_cert2 = load_cert(s_cert_file2, s_cert_format, + "second server certificate file"); - if (!s_cert2) { + if (s_cert2 == NULL) { ERR_print_errors(bio_err); goto end; } } -#endif /* OPENSSL_NO_TLSEXT */ } -#if !defined(OPENSSL_NO_TLSEXT) -# if !defined(OPENSSL_NO_NEXTPROTONEG) +#if !defined(OPENSSL_NO_NEXTPROTONEG) if (next_proto_neg_in) { - unsigned short len; - next_proto.data = next_protos_parse(&len, next_proto_neg_in); + next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in); if (next_proto.data == NULL) goto end; - next_proto.len = len; - } else { - next_proto.data = NULL; } -# endif +#endif alpn_ctx.data = NULL; if (alpn_in) { - unsigned short len; - alpn_ctx.data = next_protos_parse(&len, alpn_in); + alpn_ctx.data = next_protos_parse(&alpn_ctx.len, alpn_in); if (alpn_ctx.data == NULL) goto end; - alpn_ctx.len = len; } -#endif - if (crl_file) { + if (crl_file != NULL) { X509_CRL *crl; crl = load_crl(crl_file, crl_format); - if (!crl) { + if (crl == NULL) { BIO_puts(bio_err, "Error loading CRL\n"); ERR_print_errors(bio_err); goto end; } crls = sk_X509_CRL_new_null(); - if (!crls || !sk_X509_CRL_push(crls, crl)) { + if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { BIO_puts(bio_err, "Error adding CRL\n"); ERR_print_errors(bio_err); X509_CRL_free(crl); @@ -1695,54 +1717,44 @@ int MAIN(int argc, char *argv[]) } } - if (s_dcert_file) { + if (s_dcert_file != NULL) { if (s_dkey_file == NULL) s_dkey_file = s_dcert_file; - s_dkey = load_key(bio_err, s_dkey_file, s_dkey_format, - 0, dpass, e, "second certificate private key file"); - if (!s_dkey) { + s_dkey = load_key(s_dkey_file, s_dkey_format, + 0, dpass, engine, "second certificate private key file"); + if (s_dkey == NULL) { ERR_print_errors(bio_err); goto end; } - s_dcert = load_cert(bio_err, s_dcert_file, s_dcert_format, - NULL, e, "second server certificate file"); + s_dcert = load_cert(s_dcert_file, s_dcert_format, + "second server certificate file"); - if (!s_dcert) { + if (s_dcert == NULL) { ERR_print_errors(bio_err); goto end; } - if (s_dchain_file) { - s_dchain = load_certs(bio_err, s_dchain_file, FORMAT_PEM, - NULL, e, "second server certificate chain"); - if (!s_dchain) + if (s_dchain_file != NULL) { + if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL, + "second server certificate chain")) goto end; } } - if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL - && !RAND_status()) { - BIO_printf(bio_err, - "warning, not much extra random data, consider using the -rand option\n"); - } - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - if (bio_s_out == NULL) { if (s_quiet && !s_debug) { bio_s_out = BIO_new(BIO_s_null()); - if (s_msg && !bio_s_msg) - bio_s_msg = BIO_new_fp(stdout, BIO_NOCLOSE); + if (s_msg && bio_s_msg == NULL) + bio_s_msg = dup_bio_out(FORMAT_TEXT); } else { if (bio_s_out == NULL) - bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE); + bio_s_out = dup_bio_out(FORMAT_TEXT); } } -#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) +#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) if (nocert) #endif { @@ -1750,10 +1762,8 @@ int MAIN(int argc, char *argv[]) s_key_file = NULL; s_dcert_file = NULL; s_dkey_file = NULL; -#ifndef OPENSSL_NO_TLSEXT s_cert_file2 = NULL; s_key_file2 = NULL; -#endif } ctx = SSL_CTX_new(meth); @@ -1761,13 +1771,34 @@ int MAIN(int argc, char *argv[]) ERR_print_errors(bio_err); goto end; } + + SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); + + if (sdebug) + ssl_ctx_security_debug(ctx, sdebug); + + if (!config_ctx(cctx, ssl_args, ctx)) + goto end; + + if (ssl_config) { + if (SSL_CTX_config(ctx, ssl_config) == 0) { + BIO_printf(bio_err, "Error using configuration \"%s\"\n", + ssl_config); + ERR_print_errors(bio_err); + goto end; + } + } + if (min_version != 0 + && SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + goto end; + if (max_version != 0 + && SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto end; + if (session_id_prefix) { if (strlen(session_id_prefix) >= 32) BIO_printf(bio_err, "warning: id_prefix is too long, only one new session will be possible\n"); - else if (strlen(session_id_prefix) >= 16) - BIO_printf(bio_err, - "warning: id_prefix is too long if you use SSLv2\n"); if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) { BIO_printf(bio_err, "error setting 'id_prefix'\n"); ERR_print_errors(bio_err); @@ -1776,9 +1807,7 @@ int MAIN(int argc, char *argv[]) BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); } SSL_CTX_set_quiet_shutdown(ctx, 1); - if (hack) - SSL_CTX_set_options(ctx, SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); - if (exc) + if (exc != NULL) ssl_ctx_set_excert(ctx, exc); if (state) @@ -1790,45 +1819,63 @@ int MAIN(int argc, char *argv[]) else SSL_CTX_sess_set_cache_size(ctx, 128); -#ifndef OPENSSL_NO_SRTP - if (srtp_profiles != NULL) - SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); -#endif + if (async) { + SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); + } -#if 0 - if (cipher == NULL) - cipher = getenv("SSL_CIPHER"); -#endif + if (max_send_fragment > 0 + && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { + BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n", + prog, max_send_fragment); + goto end; + } -#if 0 - if (s_cert_file == NULL) { - BIO_printf(bio_err, - "You must specify a certificate file for the server to use\n"); + if (split_send_fragment > 0 + && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) { + BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n", + prog, split_send_fragment); goto end; } + if (max_pipelines > 0 + && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) { + BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n", + prog, max_pipelines); + goto end; + } + + if (read_buf_len > 0) { + SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len); + } +#ifndef OPENSSL_NO_SRTP + if (srtp_profiles != NULL) { + /* Returns 0 on success! */ + if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) { + BIO_printf(bio_err, "Error setting SRTP profile\n"); + ERR_print_errors(bio_err); + goto end; + } + } #endif - if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) || - (!SSL_CTX_set_default_verify_paths(ctx))) { - /* BIO_printf(bio_err,"X509_load_verify_locations\n"); */ + if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { ERR_print_errors(bio_err); - /* goto end; */ + goto end; + } + if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { + BIO_printf(bio_err, "Error setting verify params\n"); + ERR_print_errors(bio_err); + goto end; } - if (vpm) - SSL_CTX_set1_param(ctx, vpm); ssl_ctx_add_crls(ctx, crls, 0); - if (!args_ssl_call(ctx, bio_err, cctx, ssl_args, no_ecdhe, no_jpake)) - goto end; - if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, crls, crl_download)) { BIO_printf(bio_err, "Error loading store locations\n"); ERR_print_errors(bio_err); goto end; } -#ifndef OPENSSL_NO_TLSEXT + if (s_cert2) { ctx2 = SSL_CTX_new(meth); if (ctx2 == NULL) { @@ -1837,16 +1884,16 @@ int MAIN(int argc, char *argv[]) } } - if (ctx2) { + if (ctx2 != NULL) { BIO_printf(bio_s_out, "Setting secondary ctx parameters\n"); + if (sdebug) + ssl_ctx_security_debug(ctx, sdebug); + if (session_id_prefix) { if (strlen(session_id_prefix) >= 32) BIO_printf(bio_err, "warning: id_prefix is too long, only one new session will be possible\n"); - else if (strlen(session_id_prefix) >= 16) - BIO_printf(bio_err, - "warning: id_prefix is too long if you use SSLv2\n"); if (!SSL_CTX_set_generate_session_id(ctx2, generate_session_id)) { BIO_printf(bio_err, "error setting 'id_prefix'\n"); ERR_print_errors(bio_err); @@ -1855,9 +1902,7 @@ int MAIN(int argc, char *argv[]) BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); } SSL_CTX_set_quiet_shutdown(ctx2, 1); - if (hack) - SSL_CTX_set_options(ctx2, SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); - if (exc) + if (exc != NULL) ssl_ctx_set_excert(ctx2, exc); if (state) @@ -1870,52 +1915,58 @@ int MAIN(int argc, char *argv[]) else SSL_CTX_sess_set_cache_size(ctx2, 128); - if ((!SSL_CTX_load_verify_locations(ctx2, CAfile, CApath)) || - (!SSL_CTX_set_default_verify_paths(ctx2))) { + if (async) + SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC); + + if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile, + noCApath)) { + ERR_print_errors(bio_err); + goto end; + } + if (vpmtouched && !SSL_CTX_set1_param(ctx2, vpm)) { + BIO_printf(bio_err, "Error setting verify params\n"); ERR_print_errors(bio_err); + goto end; } - if (vpm) - SSL_CTX_set1_param(ctx2, vpm); ssl_ctx_add_crls(ctx2, crls, 0); - - if (!args_ssl_call(ctx2, bio_err, cctx, ssl_args, no_ecdhe, no_jpake)) + if (!config_ctx(cctx, ssl_args, ctx2)) goto end; - } -# ifndef OPENSSL_NO_NEXTPROTONEG +#ifndef OPENSSL_NO_NEXTPROTONEG if (next_proto.data) SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto); -# endif +#endif if (alpn_ctx.data) SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); -#endif #ifndef OPENSSL_NO_DH if (!no_dhe) { DH *dh = NULL; - if (dhfile) + if (dhfile != NULL) dh = load_dh_param(dhfile); - else if (s_cert_file) + else if (s_cert_file != NULL) dh = load_dh_param(s_cert_file); if (dh != NULL) { BIO_printf(bio_s_out, "Setting temp DH parameters\n"); } else { BIO_printf(bio_s_out, "Using default temp DH parameters\n"); - dh = get_dh2048(); - if (dh == NULL) { - ERR_print_errors(bio_err); - goto end; - } } (void)BIO_flush(bio_s_out); - SSL_CTX_set_tmp_dh(ctx, dh); -# ifndef OPENSSL_NO_TLSEXT - if (ctx2) { + if (dh == NULL) { + SSL_CTX_set_dh_auto(ctx, 1); + } else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { + BIO_puts(bio_err, "Error setting temp DH parameters\n"); + ERR_print_errors(bio_err); + DH_free(dh); + goto end; + } + + if (ctx2 != NULL) { if (!dhfile) { DH *dh2 = load_dh_param(s_cert_file2); if (dh2 != NULL) { @@ -1926,76 +1977,49 @@ int MAIN(int argc, char *argv[]) dh = dh2; } } - SSL_CTX_set_tmp_dh(ctx2, dh); + if (dh == NULL) { + SSL_CTX_set_dh_auto(ctx2, 1); + } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { + BIO_puts(bio_err, "Error setting temp DH parameters\n"); + ERR_print_errors(bio_err); + DH_free(dh); + goto end; + } } -# endif DH_free(dh); } #endif if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain)) goto end; -#ifndef OPENSSL_NO_TLSEXT + if (s_serverinfo_file != NULL && !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) { ERR_print_errors(bio_err); goto end; } -#endif -#ifndef OPENSSL_NO_TLSEXT - if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain)) + + if (ctx2 != NULL + && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain)) goto end; -#endif + if (s_dcert != NULL) { if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain)) goto end; } -#ifndef OPENSSL_NO_RSA -# if 1 - if (!no_tmp_rsa) { - SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb); -# ifndef OPENSSL_NO_TLSEXT - if (ctx2) - SSL_CTX_set_tmp_rsa_callback(ctx2, tmp_rsa_cb); -# endif - } -# else - if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx)) { - RSA *rsa; - BIO_printf(bio_s_out, "Generating temp (512 bit) RSA key..."); - BIO_flush(bio_s_out); + if (no_resume_ephemeral) { + SSL_CTX_set_not_resumable_session_callback(ctx, + not_resumable_sess_cb); - rsa = RSA_generate_key(512, RSA_F4, NULL); - - if (!SSL_CTX_set_tmp_rsa(ctx, rsa)) { - ERR_print_errors(bio_err); - goto end; - } -# ifndef OPENSSL_NO_TLSEXT - if (ctx2) { - if (!SSL_CTX_set_tmp_rsa(ctx2, rsa)) { - ERR_print_errors(bio_err); - goto end; - } - } -# endif - RSA_free(rsa); - BIO_printf(bio_s_out, "\n"); + if (ctx2 != NULL) + SSL_CTX_set_not_resumable_session_callback(ctx2, + not_resumable_sess_cb); } -# endif -#endif - #ifndef OPENSSL_NO_PSK -# ifdef OPENSSL_NO_JPAKE - if (psk_key != NULL) -# else - if (psk_key != NULL || jpake_secret) -# endif - { + if (psk_key != NULL) { if (s_debug) - BIO_printf(bio_s_out, - "PSK key given or JPAKE in use, setting server callback\n"); + BIO_printf(bio_s_out, "PSK key given, setting server callback\n"); SSL_CTX_set_psk_server_callback(ctx, psk_server_cb); } @@ -2005,29 +2029,59 @@ int MAIN(int argc, char *argv[]) goto end; } #endif + if (psksessf != NULL) { + BIO *stmp = BIO_new_file(psksessf, "r"); + + if (stmp == NULL) { + BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); + BIO_free(stmp); + if (psksess == NULL) { + BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + + } + + if (psk_key != NULL || psksess != NULL) + SSL_CTX_set_psk_find_session_callback(ctx, psk_find_session_cb); SSL_CTX_set_verify(ctx, s_server_verify, verify_callback); - SSL_CTX_set_session_id_context(ctx, (void *)&s_server_session_id_context, - sizeof(s_server_session_id_context)); + if (!SSL_CTX_set_session_id_context(ctx, + (void *)&s_server_session_id_context, + sizeof(s_server_session_id_context))) { + BIO_printf(bio_err, "error setting session id context\n"); + ERR_print_errors(bio_err); + goto end; + } /* Set DTLS cookie generation and verification callbacks */ SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback); SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback); -#ifndef OPENSSL_NO_TLSEXT - if (ctx2) { - SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback); - SSL_CTX_set_session_id_context(ctx2, - (void *)&s_server_session_id_context, - sizeof(s_server_session_id_context)); + /* Set TLS1.3 cookie generation and verification callbacks */ + SSL_CTX_set_stateless_cookie_generate_cb(ctx, generate_stateless_cookie_callback); + SSL_CTX_set_stateless_cookie_verify_cb(ctx, verify_stateless_cookie_callback); + if (ctx2 != NULL) { + SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback); + if (!SSL_CTX_set_session_id_context(ctx2, + (void *)&s_server_session_id_context, + sizeof(s_server_session_id_context))) { + BIO_printf(bio_err, "error setting session id context\n"); + ERR_print_errors(bio_err); + goto end; + } tlsextcbp.biodebug = bio_s_out; SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); } -#endif #ifndef OPENSSL_NO_SRP if (srp_verifier_file != NULL) { @@ -2049,92 +2103,82 @@ int MAIN(int argc, char *argv[]) #endif if (CAfile != NULL) { SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile)); -#ifndef OPENSSL_NO_TLSEXT + if (ctx2) SSL_CTX_set_client_CA_list(ctx2, SSL_load_client_CA_file(CAfile)); -#endif } +#ifndef OPENSSL_NO_OCSP + if (s_tlsextstatus) { + SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb); + SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp); + if (ctx2) { + SSL_CTX_set_tlsext_status_cb(ctx2, cert_status_cb); + SSL_CTX_set_tlsext_status_arg(ctx2, &tlscstatp); + } + } +#endif + if (set_keylog_file(ctx, keylog_file)) + goto end; + + if (max_early_data >= 0) + SSL_CTX_set_max_early_data(ctx, max_early_data); + if (recv_max_early_data >= 0) + SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data); - BIO_printf(bio_s_out, "ACCEPT\n"); - (void)BIO_flush(bio_s_out); if (rev) - do_server(port, socket_type, &accept_socket, rev_body, context, - naccept); + server_cb = rev_body; else if (www) - do_server(port, socket_type, &accept_socket, www_body, context, - naccept); + server_cb = www_body; else - do_server(port, socket_type, &accept_socket, sv_body, context, - naccept); + server_cb = sv_body; +#ifdef AF_UNIX + if (socket_family == AF_UNIX + && unlink_unix_path) + unlink(host); +#endif + do_server(&accept_socket, host, port, socket_family, socket_type, protocol, + server_cb, context, naccept, bio_s_out); print_stats(bio_s_out, ctx); ret = 0; end: - if (ctx != NULL) - SSL_CTX_free(ctx); - if (s_cert) - X509_free(s_cert); - if (crls) - sk_X509_CRL_pop_free(crls, X509_CRL_free); - if (s_dcert) - X509_free(s_dcert); - if (s_key) - EVP_PKEY_free(s_key); - if (s_dkey) - EVP_PKEY_free(s_dkey); - if (s_chain) - sk_X509_pop_free(s_chain, X509_free); - if (s_dchain) - sk_X509_pop_free(s_dchain, X509_free); - if (pass) - OPENSSL_free(pass); - if (dpass) - OPENSSL_free(dpass); - if (vpm) - X509_VERIFY_PARAM_free(vpm); + SSL_CTX_free(ctx); + SSL_SESSION_free(psksess); + set_keylog_file(NULL, NULL); + X509_free(s_cert); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + X509_free(s_dcert); + EVP_PKEY_free(s_key); + EVP_PKEY_free(s_dkey); + sk_X509_pop_free(s_chain, X509_free); + sk_X509_pop_free(s_dchain, X509_free); + OPENSSL_free(pass); + OPENSSL_free(dpass); + OPENSSL_free(host); + OPENSSL_free(port); + X509_VERIFY_PARAM_free(vpm); free_sessions(); -#ifndef OPENSSL_NO_TLSEXT - if (tlscstatp.host) - OPENSSL_free(tlscstatp.host); - if (tlscstatp.port) - OPENSSL_free(tlscstatp.port); - if (tlscstatp.path) - OPENSSL_free(tlscstatp.path); - if (ctx2 != NULL) - SSL_CTX_free(ctx2); - if (s_cert2) - X509_free(s_cert2); - if (s_key2) - EVP_PKEY_free(s_key2); - if (serverinfo_in != NULL) - BIO_free(serverinfo_in); -# ifndef OPENSSL_NO_NEXTPROTONEG - if (next_proto.data) - OPENSSL_free(next_proto.data); -# endif - if (alpn_ctx.data) - OPENSSL_free(alpn_ctx.data); + OPENSSL_free(tlscstatp.host); + OPENSSL_free(tlscstatp.port); + OPENSSL_free(tlscstatp.path); + SSL_CTX_free(ctx2); + X509_free(s_cert2); + EVP_PKEY_free(s_key2); +#ifndef OPENSSL_NO_NEXTPROTONEG + OPENSSL_free(next_proto.data); #endif + OPENSSL_free(alpn_ctx.data); ssl_excert_free(exc); - if (ssl_args) - sk_OPENSSL_STRING_free(ssl_args); - if (cctx) - SSL_CONF_CTX_free(cctx); -#ifndef OPENSSL_NO_JPAKE - if (jpake_secret && psk_key) - OPENSSL_free(psk_key); + sk_OPENSSL_STRING_free(ssl_args); + SSL_CONF_CTX_free(cctx); + release_engine(engine); + BIO_free(bio_s_out); + bio_s_out = NULL; + BIO_free(bio_s_msg); + bio_s_msg = NULL; +#ifdef CHARSET_EBCDIC + BIO_meth_free(methods_ebcdic); #endif - release_engine(e); - if (bio_s_out != NULL) { - BIO_free(bio_s_out); - bio_s_out = NULL; - } - if (bio_s_msg != NULL) { - BIO_free(bio_s_msg); - bio_s_msg = NULL; - } - SSL_COMP_free_compression_methods(); - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) @@ -2165,7 +2209,7 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) SSL_CTX_sess_get_cache_size(ssl_ctx)); } -static int sv_body(char *hostname, int s, int stype, unsigned char *context) +static int sv_body(int s, int stype, int prot, unsigned char *context) { char *buf = NULL; fd_set readfds; @@ -2174,64 +2218,58 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) unsigned long l; SSL *con = NULL; BIO *sbio; -#ifndef OPENSSL_NO_KRB5 - KSSL_CTX *kctx; -#endif struct timeval timeout; -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) - struct timeval tv; -#else +#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)) struct timeval *timeoutp; #endif +#ifndef OPENSSL_NO_DTLS +# ifndef OPENSSL_NO_SCTP + int isdtls = (stype == SOCK_DGRAM || prot == IPPROTO_SCTP); +# else + int isdtls = (stype == SOCK_DGRAM); +# endif +#endif - if ((buf = OPENSSL_malloc(bufsize)) == NULL) { - BIO_printf(bio_err, "out of memory\n"); - goto err; - } -#ifdef FIONBIO + buf = app_malloc(bufsize, "server buffer"); if (s_nbio) { - unsigned long sl = 1; - - if (!s_quiet) - BIO_printf(bio_err, "turning on non blocking io\n"); - if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0) + if (!BIO_socket_nbio(s, 1)) ERR_print_errors(bio_err); + else if (!s_quiet) + BIO_printf(bio_err, "Turned on non blocking io\n"); } -#endif + con = SSL_new(ctx); if (con == NULL) { - con = SSL_new(ctx); -#ifndef OPENSSL_NO_TLSEXT - if (s_tlsextdebug) { - SSL_set_tlsext_debug_callback(con, tlsext_cb); - SSL_set_tlsext_debug_arg(con, bio_s_out); - } - if (s_tlsextstatus) { - SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb); - tlscstatp.err = bio_err; - SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp); - } -#endif -#ifndef OPENSSL_NO_KRB5 - if ((kctx = kssl_ctx_new()) != NULL) { - SSL_set0_kssl_ctx(con, kctx); - kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC); - kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB); - } -#endif /* OPENSSL_NO_KRB5 */ - if (context) - SSL_set_session_id_context(con, context, strlen((char *)context)); + ret = -1; + goto err; } - SSL_clear(con); -#if 0 -# ifdef TLSEXT_TYPE_opaque_prf_input - SSL_set_tlsext_opaque_prf_input(con, "Test server", 11); -# endif -#endif - if (stype == SOCK_DGRAM) { + if (s_tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } - sbio = BIO_new_dgram(s, BIO_NOCLOSE); + if (context != NULL + && !SSL_set_session_id_context(con, context, + strlen((char *)context))) { + BIO_printf(bio_err, "Error setting session id context\n"); + ret = -1; + goto err; + } + + if (!SSL_clear(con)) { + BIO_printf(bio_err, "Error clearing SSL connection\n"); + ret = -1; + goto err; + } +#ifndef OPENSSL_NO_DTLS + if (isdtls) { +# ifndef OPENSSL_NO_SCTP + if (prot == IPPROTO_SCTP) + sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE); + else +# endif + sbio = BIO_new_dgram(s, BIO_NOCLOSE); if (enable_timeouts) { timeout.tv_sec = 0; @@ -2262,28 +2300,33 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); - /* turn on cookie exchange */ - SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); +# ifndef OPENSSL_NO_SCTP + if (prot != IPPROTO_SCTP) +# endif + /* Turn on cookie exchange. Not necessary for SCTP */ + SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); } else +#endif sbio = BIO_new_socket(s, BIO_NOCLOSE); + if (sbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + ERR_print_errors(bio_err); + goto err; + } + if (s_nbio_test) { BIO *test; test = BIO_new(BIO_f_nbio_test()); sbio = BIO_push(test, sbio); } -#ifndef OPENSSL_NO_JPAKE - if (jpake_secret) - jpake_server_auth(bio_s_out, sbio, jpake_secret); -#endif SSL_set_bio(con, sbio, sbio); SSL_set_accept_state(con); /* SSL_set_fd(con,s); */ if (s_debug) { - SSL_set_debug(con, 1); BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); } @@ -2296,12 +2339,54 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); } -#ifndef OPENSSL_NO_TLSEXT + if (s_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_s_out); } -#endif + + if (early_data) { + int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR; + size_t readbytes; + + while (edret != SSL_READ_EARLY_DATA_FINISH) { + for (;;) { + edret = SSL_read_early_data(con, buf, bufsize, &readbytes); + if (edret != SSL_READ_EARLY_DATA_ERROR) + break; + + switch (SSL_get_error(con, 0)) { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_READ: + /* Just keep trying - busy waiting */ + continue; + default: + BIO_printf(bio_err, "Error reading early data\n"); + ERR_print_errors(bio_err); + goto err; + } + } + if (readbytes > 0) { + if (write_header) { + BIO_printf(bio_s_out, "Early data received:\n"); + write_header = 0; + } + raw_write_stdout(buf, (unsigned int)readbytes); + (void)BIO_flush(bio_s_out); + } + } + if (write_header) { + if (SSL_get_early_data_status(con) == SSL_EARLY_DATA_NOT_SENT) + BIO_printf(bio_s_out, "No early data received\n"); + else + BIO_printf(bio_s_out, "Early data was rejected\n"); + } else { + BIO_printf(bio_s_out, "\nEnd of early data\n"); + } + if (SSL_is_init_finished(con)) + print_connection_info(con); + } if (fileno_stdin() > s) width = fileno_stdin() + 1; @@ -2312,11 +2397,12 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) int read_from_sslcon; read_from_terminal = 0; - read_from_sslcon = SSL_pending(con); + read_from_sslcon = SSL_has_pending(con) + || (async && SSL_waiting_for_async(con)); if (!read_from_sslcon) { FD_ZERO(&readfds); -#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) && !defined(OPENSSL_SYS_BEOS_R5) +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) openssl_fdset(fileno_stdin(), &readfds); #endif openssl_fdset(s, &readfds); @@ -2327,44 +2413,30 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) * if you do have a cast then you can either go for (int *) or * (void *). */ -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) /* * Under DOS (non-djgpp) and Windows we can't select on stdin: * only on sockets. As a workaround we timeout the select every * second and check for any keypress. In a proper Windows * application we wouldn't do this because it is inefficient. */ - tv.tv_sec = 1; - tv.tv_usec = 0; - i = select(width, (void *)&readfds, NULL, NULL, &tv); - if ((i < 0) || (!i && !_kbhit())) - continue; - if (_kbhit()) + timeout.tv_sec = 1; + timeout.tv_usec = 0; + i = select(width, (void *)&readfds, NULL, NULL, &timeout); + if (has_stdin_waiting()) read_from_terminal = 1; -#elif defined(OPENSSL_SYS_BEOS_R5) - /* Under BeOS-R5 the situation is similar to DOS */ - tv.tv_sec = 1; - tv.tv_usec = 0; - (void)fcntl(fileno_stdin(), F_SETFL, O_NONBLOCK); - i = select(width, (void *)&readfds, NULL, NULL, &tv); - if ((i < 0) || (!i && read(fileno_stdin(), buf, 0) < 0)) + if ((i < 0) || (!i && !read_from_terminal)) continue; - if (read(fileno_stdin(), buf, 0) >= 0) - read_from_terminal = 1; - (void)fcntl(fileno_stdin(), F_SETFL, 0); #else - if ((SSL_version(con) == DTLS1_VERSION) && - DTLSv1_get_timeout(con, &timeout)) + if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)) timeoutp = &timeout; else timeoutp = NULL; i = select(width, (void *)&readfds, NULL, NULL, timeoutp); - if ((SSL_version(con) == DTLS1_VERSION) - && DTLSv1_handle_timeout(con) > 0) { - BIO_printf(bio_err, "TIMEOUT occured\n"); - } + if ((SSL_is_dtls(con)) && DTLSv1_handle_timeout(con) > 0) + BIO_printf(bio_err, "TIMEOUT occurred\n"); if (i <= 0) continue; @@ -2393,21 +2465,24 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) } } assert(lf_num == 0); - } else + } else { i = raw_read_stdin(buf, bufsize); + } if (!s_quiet && !s_brief) { if ((i <= 0) || (buf[0] == 'Q')) { BIO_printf(bio_s_out, "DONE\n"); - SHUTDOWN(s); + (void)BIO_flush(bio_s_out); + BIO_closesocket(s); close_accept_socket(); ret = -11; goto err; } if ((i <= 0) || (buf[0] == 'q')) { BIO_printf(bio_s_out, "DONE\n"); + (void)BIO_flush(bio_s_out); if (SSL_version(con) != DTLS1_VERSION) - SHUTDOWN(s); + BIO_closesocket(s); /* * close_accept_socket(); ret= -11; */ @@ -2427,9 +2502,6 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) printf("SSL_do_handshake -> %d\n", i); i = 0; /* 13; */ continue; - /* - * strcpy(buf,"server side RE-NEGOTIATE\n"); - */ } if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) { SSL_set_verify(con, @@ -2440,10 +2512,29 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) printf("SSL_do_handshake -> %d\n", i); i = 0; /* 13; */ continue; - /* - * strcpy(buf,"server side RE-NEGOTIATE asking for client - * cert\n"); - */ + } + if ((buf[0] == 'K' || buf[0] == 'k') + && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_key_update(con, buf[0] == 'K' ? + SSL_KEY_UPDATE_REQUESTED + : SSL_KEY_UPDATE_NOT_REQUESTED); + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; + continue; + } + if (buf[0] == 'c' && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_set_verify(con, SSL_VERIFY_PEER, NULL); + i = SSL_verify_client_post_handshake(con); + if (i == 0) { + printf("Failed to initiate request\n"); + ERR_print_errors(bio_err); + } else { + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; + } + continue; } if (buf[0] == 'P') { static const char *str = "Lets print some clear text\n"; @@ -2460,12 +2551,10 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) for (;;) { /* should do a select for the write */ #ifdef RENEG - { - static count = 0; - if (++count == 100) { - count = 0; - SSL_renegotiate(con); - } + static count = 0; + if (++count == 100) { + count = 0; + SSL_renegotiate(con); } #endif k = SSL_write(con, &(buf[l]), (unsigned int)i); @@ -2487,20 +2576,32 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_s_out, "Write BLOCK (Async)\n"); + (void)BIO_flush(bio_s_out); + wait_for_async(con); + break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_s_out, "Write BLOCK\n"); + (void)BIO_flush(bio_s_out); break; + case SSL_ERROR_WANT_ASYNC_JOB: + /* + * This shouldn't ever happen in s_server. Treat as an error + */ case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: BIO_printf(bio_s_out, "ERROR\n"); + (void)BIO_flush(bio_s_out); ERR_print_errors(bio_err); ret = 1; goto err; /* break; */ case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_s_out, "DONE\n"); + (void)BIO_flush(bio_s_out); ret = 1; goto err; } @@ -2513,7 +2614,13 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) } } if (read_from_sslcon) { - if (!SSL_is_init_finished(con)) { + /* + * init_ssl_connection handles all async events itself so if we're + * waiting for async then we shouldn't go back into + * init_ssl_connection + */ + if ((!async || !SSL_waiting_for_async(con)) + && !SSL_is_init_finished(con)) { i = init_ssl_connection(con); if (i < 0) { @@ -2547,21 +2654,34 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) ascii2ebcdic(buf, buf, i); #endif raw_write_stdout(buf, (unsigned int)i); - if (SSL_pending(con)) + (void)BIO_flush(bio_s_out); + if (SSL_has_pending(con)) goto again; break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_s_out, "Read BLOCK (Async)\n"); + (void)BIO_flush(bio_s_out); + wait_for_async(con); + break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: BIO_printf(bio_s_out, "Read BLOCK\n"); + (void)BIO_flush(bio_s_out); break; + case SSL_ERROR_WANT_ASYNC_JOB: + /* + * This shouldn't ever happen in s_server. Treat as an error + */ case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: BIO_printf(bio_s_out, "ERROR\n"); + (void)BIO_flush(bio_s_out); ERR_print_errors(bio_err); ret = 1; goto err; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_s_out, "DONE\n"); + (void)BIO_flush(bio_s_out); ret = 1; goto err; } @@ -2571,94 +2691,153 @@ static int sv_body(char *hostname, int s, int stype, unsigned char *context) err: if (con != NULL) { BIO_printf(bio_s_out, "shutting down SSL\n"); -#if 1 SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); -#else - SSL_shutdown(con); -#endif SSL_free(con); } BIO_printf(bio_s_out, "CONNECTION CLOSED\n"); - if (buf != NULL) { - OPENSSL_cleanse(buf, bufsize); - OPENSSL_free(buf); - } - if (ret >= 0) - BIO_printf(bio_s_out, "ACCEPT\n"); - return (ret); + OPENSSL_clear_free(buf, bufsize); + return ret; } static void close_accept_socket(void) { BIO_printf(bio_err, "shutdown accept socket\n"); if (accept_socket >= 0) { - SHUTDOWN2(accept_socket); + BIO_closesocket(accept_socket); } } +static int is_retryable(SSL *con, int i) +{ + int err = SSL_get_error(con, i); + + /* If it's not a fatal error, it must be retryable */ + return (err != SSL_ERROR_SSL) + && (err != SSL_ERROR_SYSCALL) + && (err != SSL_ERROR_ZERO_RETURN); +} + static int init_ssl_connection(SSL *con) { int i; - const char *str; - X509 *peer; - long verify_error; - MS_STATIC char buf[BUFSIZ]; -#ifndef OPENSSL_NO_KRB5 - char *client_princ; -#endif -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) - const unsigned char *next_proto_neg; - unsigned next_proto_neg_len; -#endif - unsigned char *exportedkeymat; + long verify_err; + int retry = 0; - i = SSL_accept(con); -#ifdef CERT_CB_TEST_RETRY - { - while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP - && SSL_state(con) == SSL3_ST_SR_CLNT_HELLO_C) { - fprintf(stderr, - "LOOKUP from certificate callback during accept\n"); + if (dtlslisten || stateless) { + BIO_ADDR *client = NULL; + + if (dtlslisten) { + if ((client = BIO_ADDR_new()) == NULL) { + BIO_printf(bio_err, "ERROR - memory\n"); + return 0; + } + i = DTLSv1_listen(con, client); + } else { + i = SSL_stateless(con); + } + if (i > 0) { + BIO *wbio; + int fd = -1; + + if (dtlslisten) { + wbio = SSL_get_wbio(con); + if (wbio) { + BIO_get_fd(wbio, &fd); + } + + if (!wbio || BIO_connect(fd, client, 0) == 0) { + BIO_printf(bio_err, "ERROR - unable to connect\n"); + BIO_ADDR_free(client); + return 0; + } + BIO_ADDR_free(client); + dtlslisten = 0; + } else { + stateless = 0; + } i = SSL_accept(con); + } else { + BIO_ADDR_free(client); } - } + } else { + do { + i = SSL_accept(con); + + if (i <= 0) + retry = is_retryable(con, i); +#ifdef CERT_CB_TEST_RETRY + { + while (i <= 0 + && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP + && SSL_get_state(con) == TLS_ST_SR_CLNT_HELLO) { + BIO_printf(bio_err, + "LOOKUP from certificate callback during accept\n"); + i = SSL_accept(con); + if (i <= 0) + retry = is_retryable(con, i); + } + } #endif + #ifndef OPENSSL_NO_SRP - while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { - BIO_printf(bio_s_out, "LOOKUP during accept %s\n", - srp_callback_parm.login); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); - i = SSL_accept(con); - } + while (i <= 0 + && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { + BIO_printf(bio_s_out, "LOOKUP during accept %s\n", + srp_callback_parm.login); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = + SRP_VBASE_get1_by_user(srp_callback_parm.vb, + srp_callback_parm.login); + if (srp_callback_parm.user) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm.user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); + i = SSL_accept(con); + if (i <= 0) + retry = is_retryable(con, i); + } #endif + } while (i < 0 && SSL_waiting_for_async(con)); + } if (i <= 0) { - if (BIO_sock_should_retry(i)) { + if (((dtlslisten || stateless) && i == 0) + || (!dtlslisten && !stateless && retry)) { BIO_printf(bio_s_out, "DELAY\n"); - return (1); + return 1; } BIO_printf(bio_err, "ERROR\n"); - verify_error = SSL_get_verify_result(con); - if (verify_error != X509_V_OK) { + + verify_err = SSL_get_verify_result(con); + if (verify_err != X509_V_OK) { BIO_printf(bio_err, "verify error:%s\n", - X509_verify_cert_error_string(verify_error)); + X509_verify_cert_error_string(verify_err)); } /* Always print any error messages */ ERR_print_errors(bio_err); - return (0); + return 0; } + print_connection_info(con); + return 1; +} + +static void print_connection_info(SSL *con) +{ + const char *str; + X509 *peer; + char buf[BUFSIZ]; +#if !defined(OPENSSL_NO_NEXTPROTONEG) + const unsigned char *next_proto_neg; + unsigned next_proto_neg_len; +#endif + unsigned char *exportedkeymat; + int i; + if (s_brief) - print_ssl_summary(bio_err, con); + print_ssl_summary(con); PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con)); @@ -2666,11 +2845,9 @@ static int init_ssl_connection(SSL *con) if (peer != NULL) { BIO_printf(bio_s_out, "Client certificate\n"); PEM_write_bio_X509(bio_s_out, peer); - X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof(buf)); - BIO_printf(bio_s_out, "subject=%s\n", buf); - X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf)); - BIO_printf(bio_s_out, "issuer=%s\n", buf); + dump_cert_text(bio_s_out, peer); X509_free(peer); + peer = NULL; } if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL) @@ -2679,11 +2856,12 @@ static int init_ssl_connection(SSL *con) ssl_print_sigalgs(bio_s_out, con); #ifndef OPENSSL_NO_EC ssl_print_point_formats(bio_s_out, con); - ssl_print_curves(bio_s_out, con, 0); + ssl_print_groups(bio_s_out, con, 0); #endif + print_ca_names(bio_s_out, con); BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +#if !defined(OPENSSL_NO_NEXTPROTONEG) SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len); if (next_proto_neg) { BIO_printf(bio_s_out, "NEXTPROTO is "); @@ -2701,43 +2879,34 @@ static int init_ssl_connection(SSL *con) srtp_profile->name); } #endif - if (SSL_cache_hit(con)) + if (SSL_session_reused(con)) BIO_printf(bio_s_out, "Reused session-id\n"); - if (SSL_ctrl(con, SSL_CTRL_GET_FLAGS, 0, NULL) & - TLS1_FLAGS_TLS_PADDING_BUG) - BIO_printf(bio_s_out, "Peer has incorrect TLSv1 block padding\n"); -#ifndef OPENSSL_NO_KRB5 - client_princ = kssl_ctx_get0_client_princ(SSL_get0_kssl_ctx(con)); - if (client_princ != NULL) { - BIO_printf(bio_s_out, "Kerberos peer principal is %s\n", - client_princ); - } -#endif /* OPENSSL_NO_KRB5 */ BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n", SSL_get_secure_renegotiation_support(con) ? "" : " NOT"); + if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION)) + BIO_printf(bio_s_out, "Renegotiation is DISABLED\n"); + if (keymatexportlabel != NULL) { BIO_printf(bio_s_out, "Keying material exporter:\n"); BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel); BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen); - exportedkeymat = OPENSSL_malloc(keymatexportlen); - if (exportedkeymat != NULL) { - if (!SSL_export_keying_material(con, exportedkeymat, - keymatexportlen, - keymatexportlabel, - strlen(keymatexportlabel), - NULL, 0, 0)) { - BIO_printf(bio_s_out, " Error\n"); - } else { - BIO_printf(bio_s_out, " Keying material: "); - for (i = 0; i < keymatexportlen; i++) - BIO_printf(bio_s_out, "%02X", exportedkeymat[i]); - BIO_printf(bio_s_out, "\n"); - } - OPENSSL_free(exportedkeymat); + exportedkeymat = app_malloc(keymatexportlen, "export key"); + if (!SSL_export_keying_material(con, exportedkeymat, + keymatexportlen, + keymatexportlabel, + strlen(keymatexportlabel), + NULL, 0, 0)) { + BIO_printf(bio_s_out, " Error\n"); + } else { + BIO_printf(bio_s_out, " Keying material: "); + for (i = 0; i < keymatexportlen; i++) + BIO_printf(bio_s_out, "%02X", exportedkeymat[i]); + BIO_printf(bio_s_out, "\n"); } + OPENSSL_free(exportedkeymat); } - return (1); + (void)BIO_flush(bio_s_out); } #ifndef OPENSSL_NO_DH @@ -2750,37 +2919,12 @@ static DH *load_dh_param(const char *dhfile) goto err; ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); err: - if (bio != NULL) - BIO_free(bio); - return (ret); -} -#endif -#ifndef OPENSSL_NO_KRB5 -char *client_princ; -#endif - -#if 0 -static int load_CA(SSL_CTX *ctx, char *file) -{ - FILE *in; - X509 *x = NULL; - - if ((in = fopen(file, "r")) == NULL) - return (0); - - for (;;) { - if (PEM_read_X509(in, &x, NULL) == NULL) - break; - SSL_CTX_add_client_CA(ctx, x); - } - if (x != NULL) - X509_free(x); - fclose(in); - return (1); + BIO_free(bio); + return ret; } #endif -static int www_body(char *hostname, int s, int stype, unsigned char *context) +static int www_body(int s, int stype, int prot, unsigned char *context) { char *buf = NULL; int ret = 1; @@ -2788,28 +2932,27 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) SSL *con; const SSL_CIPHER *c; BIO *io, *ssl_bio, *sbio; -#ifndef OPENSSL_NO_KRB5 - KSSL_CTX *kctx; +#ifdef RENEG + int total_bytes = 0; #endif + int width; + fd_set readfds; + + /* Set width for a select call if needed */ + width = s + 1; - buf = OPENSSL_malloc(bufsize); - if (buf == NULL) - return (0); + buf = app_malloc(bufsize, "server www buffer"); io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); if ((io == NULL) || (ssl_bio == NULL)) goto err; -#ifdef FIONBIO if (s_nbio) { - unsigned long sl = 1; - - if (!s_quiet) - BIO_printf(bio_err, "turning on non blocking io\n"); - if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0) + if (!BIO_socket_nbio(s, 1)) ERR_print_errors(bio_err); + else if (!s_quiet) + BIO_printf(bio_err, "Turned on non blocking io\n"); } -#endif /* lets make the output buffer a reasonable size */ if (!BIO_set_write_buffer_size(io, bufsize)) @@ -2817,20 +2960,18 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) if ((con = SSL_new(ctx)) == NULL) goto err; -#ifndef OPENSSL_NO_TLSEXT + if (s_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_s_out); } -#endif -#ifndef OPENSSL_NO_KRB5 - if ((kctx = kssl_ctx_new()) != NULL) { - kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC); - kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB); + + if (context != NULL + && !SSL_set_session_id_context(con, context, + strlen((char *)context))) { + SSL_free(con); + goto err; } -#endif /* OPENSSL_NO_KRB5 */ - if (context) - SSL_set_session_id_context(con, context, strlen((char *)context)); sbio = BIO_new_socket(s, BIO_NOCLOSE); if (s_nbio_test) { @@ -2842,7 +2983,7 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) SSL_set_bio(con, sbio, sbio); SSL_set_accept_state(con); - /* SSL_set_fd(con,s); */ + /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ BIO_set_ssl(ssl_bio, con, BIO_CLOSE); BIO_push(io, ssl_bio); #ifdef CHARSET_EBCDIC @@ -2850,7 +2991,6 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) #endif if (s_debug) { - SSL_set_debug(con, 1); BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); } @@ -2865,47 +3005,9 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) } for (;;) { - if (hack) { - i = SSL_accept(con); -#ifndef OPENSSL_NO_SRP - while (i <= 0 - && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { - BIO_printf(bio_s_out, "LOOKUP during accept %s\n", - srp_callback_parm.login); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); - i = SSL_accept(con); - } -#endif - switch (SSL_get_error(con, i)) { - case SSL_ERROR_NONE: - break; - case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_X509_LOOKUP: - continue; - case SSL_ERROR_SYSCALL: - case SSL_ERROR_SSL: - case SSL_ERROR_ZERO_RETURN: - ret = 1; - goto err; - /* break; */ - } - - SSL_renegotiate(con); - SSL_write(con, NULL, 0); - } - i = BIO_gets(io, buf, bufsize - 1); if (i < 0) { /* error */ - if (!BIO_should_retry(io)) { + if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) { if (!s_quiet) ERR_print_errors(bio_err); goto err; @@ -2927,9 +3029,7 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) continue; } #endif -#if defined(OPENSSL_SYS_NETWARE) - delay(1000); -#elif !defined(OPENSSL_SYS_MSDOS) && !defined(__DJGPP__) +#if !defined(OPENSSL_SYS_MSDOS) sleep(1); #endif continue; @@ -2943,18 +3043,67 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) if (((www == 1) && (strncmp("GET ", buf, 4) == 0)) || ((www == 2) && (strncmp("GET /stats ", buf, 11) == 0))) { char *p; - X509 *peer; + X509 *peer = NULL; STACK_OF(SSL_CIPHER) *sk; static const char *space = " "; + if (www == 1 && strncmp("GET /reneg", buf, 10) == 0) { + if (strncmp("GET /renegcert", buf, 14) == 0) + SSL_set_verify(con, + SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, + NULL); + i = SSL_renegotiate(con); + BIO_printf(bio_s_out, "SSL_renegotiate -> %d\n", i); + /* Send the HelloRequest */ + i = SSL_do_handshake(con); + if (i <= 0) { + BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n", + SSL_get_error(con, i)); + ERR_print_errors(bio_err); + goto err; + } + /* Wait for a ClientHello to come back */ + FD_ZERO(&readfds); + openssl_fdset(s, &readfds); + i = select(width, (void *)&readfds, NULL, NULL, NULL); + if (i <= 0 || !FD_ISSET(s, &readfds)) { + BIO_printf(bio_s_out, + "Error waiting for client response\n"); + ERR_print_errors(bio_err); + goto err; + } + /* + * We're not actually expecting any data here and we ignore + * any that is sent. This is just to force the handshake that + * we're expecting to come from the client. If they haven't + * sent one there's not much we can do. + */ + BIO_gets(io, buf, bufsize - 1); + } + BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n"); BIO_puts(io, "<pre>\n"); -/* BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/ + /* BIO_puts(io, OpenSSL_version(OPENSSL_VERSION)); */ BIO_puts(io, "\n"); for (i = 0; i < local_argc; i++) { - BIO_puts(io, local_argv[i]); + const char *myp; + for (myp = local_argv[i]; *myp; myp++) + switch (*myp) { + case '<': + BIO_puts(io, "<"); + break; + case '>': + BIO_puts(io, ">"); + break; + case '&': + BIO_puts(io, "&"); + break; + default: + BIO_write(io, myp, 1); + break; + } BIO_write(io, " ", 1); } BIO_puts(io, "\n"); @@ -2972,7 +3121,7 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) j = sk_SSL_CIPHER_num(sk); for (i = 0; i < j; i++) { c = sk_SSL_CIPHER_value(sk, i); - BIO_printf(io, "%-11s:%-25s", + BIO_printf(io, "%-11s:%-25s ", SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); if ((((i + 1) % 2) == 0) && (i + 1 != j)) BIO_puts(io, "\n"); @@ -2999,9 +3148,10 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) } ssl_print_sigalgs(io, con); #ifndef OPENSSL_NO_EC - ssl_print_curves(io, con, 0); + ssl_print_groups(io, con, 0); #endif - BIO_printf(io, (SSL_cache_hit(con) + print_ca_names(io, con); + BIO_printf(io, (SSL_session_reused(con) ? "---\nReused, " : "---\nNew, ")); c = SSL_get_current_cipher(con); BIO_printf(io, "%s, Cipher is %s\n", @@ -3015,8 +3165,11 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) BIO_printf(io, "Client certificate\n"); X509_print(io, peer); PEM_write_bio_X509(io, peer); - } else + X509_free(peer); + peer = NULL; + } else { BIO_puts(io, "no client certificate available\n"); + } BIO_puts(io, "</pre></BODY></HTML>\r\n\r\n"); break; } else if ((www == 2 || www == 3) @@ -3069,21 +3222,12 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) BIO_printf(io, "'%s' is an invalid path\r\n", p); break; } -#if 0 - /* append if a directory lookup */ - if (e[-1] == '/') - strcat(p, "index.html"); -#endif /* if a directory, do the index thang */ if (app_isdir(p) > 0) { -#if 0 /* must check buffer size */ - strcat(p, "/index.html"); -#else BIO_puts(io, text); BIO_printf(io, "'%s' is a directory\r\n", p); break; -#endif } if ((file = BIO_new_file(p, "r")) == NULL) { @@ -3115,26 +3259,25 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) #ifdef RENEG total_bytes += i; - fprintf(stderr, "%d\n", i); + BIO_printf(bio_err, "%d\n", i); if (total_bytes > 3 * 1024) { total_bytes = 0; - fprintf(stderr, "RENEGOTIATE\n"); + BIO_printf(bio_err, "RENEGOTIATE\n"); SSL_renegotiate(con); } #endif for (j = 0; j < i;) { #ifdef RENEG - { - static count = 0; - if (++count == 13) { - SSL_renegotiate(con); - } + static count = 0; + if (++count == 13) { + SSL_renegotiate(con); } #endif k = BIO_write(io, &(buf[j]), i - j); if (k <= 0) { - if (!BIO_should_retry(io)) + if (!BIO_should_retry(io) + && !SSL_waiting_for_async(con)) goto write_error; else { BIO_printf(bio_s_out, "rwrite W BLOCK\n"); @@ -3159,44 +3302,24 @@ static int www_body(char *hostname, int s, int stype, unsigned char *context) break; } end: -#if 1 /* make sure we re-use sessions */ SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); -#else - /* This kills performance */ - /* - * SSL_shutdown(con); A shutdown gets sent in the BIO_free_all(io) - * procession - */ -#endif err: - - if (ret >= 0) - BIO_printf(bio_s_out, "ACCEPT\n"); - - if (buf != NULL) - OPENSSL_free(buf); - if (io != NULL) - BIO_free_all(io); -/* if (ssl_bio != NULL) BIO_free(ssl_bio);*/ - return (ret); + OPENSSL_free(buf); + BIO_free_all(io); + return ret; } -static int rev_body(char *hostname, int s, int stype, unsigned char *context) +static int rev_body(int s, int stype, int prot, unsigned char *context) { char *buf = NULL; int i; int ret = 1; SSL *con; BIO *io, *ssl_bio, *sbio; -#ifndef OPENSSL_NO_KRB5 - KSSL_CTX *kctx; -#endif - buf = OPENSSL_malloc(bufsize); - if (buf == NULL) - return (0); + buf = app_malloc(bufsize, "server rev buffer"); io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); if ((io == NULL) || (ssl_bio == NULL)) @@ -3208,25 +3331,24 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context) if ((con = SSL_new(ctx)) == NULL) goto err; -#ifndef OPENSSL_NO_TLSEXT + if (s_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_s_out); } -#endif -#ifndef OPENSSL_NO_KRB5 - if ((kctx = kssl_ctx_new()) != NULL) { - kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC); - kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB); + if (context != NULL + && !SSL_set_session_id_context(con, context, + strlen((char *)context))) { + SSL_free(con); + ERR_print_errors(bio_err); + goto err; } -#endif /* OPENSSL_NO_KRB5 */ - if (context) - SSL_set_session_id_context(con, context, strlen((char *)context)); sbio = BIO_new_socket(s, BIO_NOCLOSE); SSL_set_bio(con, sbio, sbio); SSL_set_accept_state(con); + /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ BIO_set_ssl(ssl_bio, con, BIO_CLOSE); BIO_push(io, ssl_bio); #ifdef CHARSET_EBCDIC @@ -3234,7 +3356,6 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context) #endif if (s_debug) { - SSL_set_debug(con, 1); BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); } @@ -3275,7 +3396,7 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context) #endif } BIO_printf(bio_err, "CONNECTION ESTABLISHED\n"); - print_ssl_summary(bio_err, con); + print_ssl_summary(con); for (;;) { i = BIO_gets(io, buf, bufsize - 1); @@ -3302,9 +3423,7 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context) continue; } #endif -#if defined(OPENSSL_SYS_NETWARE) - delay(1000); -#elif !defined(OPENSSL_SYS_MSDOS) && !defined(__DJGPP__) +#if !defined(OPENSSL_SYS_MSDOS) sleep(1); #endif continue; @@ -3319,7 +3438,7 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context) p--; i--; } - if (!s_ign_eof && i == 5 && !strncmp(buf, "CLOSE", 5)) { + if (!s_ign_eof && (i == 5) && (strncmp(buf, "CLOSE", 5) == 0)) { ret = 1; BIO_printf(bio_err, "CONNECTION CLOSED\n"); goto end; @@ -3342,45 +3461,13 @@ static int rev_body(char *hostname, int s, int stype, unsigned char *context) err: - if (buf != NULL) - OPENSSL_free(buf); - if (io != NULL) - BIO_free_all(io); - return (ret); -} - -#ifndef OPENSSL_NO_RSA -static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) -{ - BIGNUM *bn = NULL; - static RSA *rsa_tmp = NULL; - - if (!rsa_tmp && ((bn = BN_new()) == NULL)) - BIO_printf(bio_err, "Allocation error in generating RSA key\n"); - if (!rsa_tmp && bn) { - if (!s_quiet) { - BIO_printf(bio_err, "Generating temp (%d bit) RSA key...", - keylength); - (void)BIO_flush(bio_err); - } - if (!BN_set_word(bn, RSA_F4) || ((rsa_tmp = RSA_new()) == NULL) || - !RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) { - if (rsa_tmp) - RSA_free(rsa_tmp); - rsa_tmp = NULL; - } - if (!s_quiet) { - BIO_printf(bio_err, "\n"); - (void)BIO_flush(bio_err); - } - BN_free(bn); - } - return (rsa_tmp); + OPENSSL_free(buf); + BIO_free_all(io); + return ret; } -#endif #define MAX_SESSION_ID_ATTEMPTS 10 -static int generate_session_id(const SSL *ssl, unsigned char *id, +static int generate_session_id(SSL *ssl, unsigned char *id, unsigned int *id_len) { unsigned int count = 0; @@ -3424,33 +3511,36 @@ static simple_ssl_session *first = NULL; static int add_session(SSL *ssl, SSL_SESSION *session) { - simple_ssl_session *sess; + simple_ssl_session *sess = app_malloc(sizeof(*sess), "get session"); unsigned char *p; - sess = OPENSSL_malloc(sizeof(simple_ssl_session)); - if (!sess) { - BIO_printf(bio_err, "Out of memory adding session to external cache\n"); - return 0; - } - SSL_SESSION_get_id(session, &sess->idlen); sess->derlen = i2d_SSL_SESSION(session, NULL); + if (sess->derlen < 0) { + BIO_printf(bio_err, "Error encoding session\n"); + OPENSSL_free(sess); + return 0; + } - sess->id = BUF_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen); - - sess->der = OPENSSL_malloc(sess->derlen); - if (!sess->id || !sess->der) { - BIO_printf(bio_err, "Out of memory adding session to external cache\n"); - - if (sess->id) - OPENSSL_free(sess->id); - if (sess->der) - OPENSSL_free(sess->der); + sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen); + sess->der = app_malloc(sess->derlen, "get session buffer"); + if (!sess->id) { + BIO_printf(bio_err, "Out of memory adding to external cache\n"); + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); OPENSSL_free(sess); return 0; } p = sess->der; - i2d_SSL_SESSION(session, &p); + + /* Assume it still works. */ + if (i2d_SSL_SESSION(session, &p) != sess->derlen) { + BIO_printf(bio_err, "Unexpected session encoding length\n"); + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); + OPENSSL_free(sess); + return 0; + } sess->next = first; first = sess; @@ -3458,7 +3548,7 @@ static int add_session(SSL *ssl, SSL_SESSION *session) return 0; } -static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen, +static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen, int *do_copy) { simple_ssl_session *sess; @@ -3517,3 +3607,5 @@ static void free_sessions(void) } first = NULL; } + +#endif /* OPENSSL_NO_SOCK */ diff --git a/apps/s_socket.c b/apps/s_socket.c index 83624ca84f15..76f928900207 100644 --- a/apps/s_socket.c +++ b/apps/s_socket.c @@ -1,74 +1,19 @@ /* - * apps/s_socket.c - socket-related functions used by s_client and s_server - */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ +/* socket-related functions used by s_client and s_server */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <signal.h> - -#ifdef FLAT_INC -# include "e_os2.h" -#else -# include "../e_os2.h" -#endif +#include <openssl/opensslconf.h> /* * With IPv6, it looks like Digital has mixed up the proper order of @@ -81,533 +26,370 @@ typedef unsigned int u_int; #endif -#define USE_SOCKETS -#define NON_MAIN -#include "apps.h" -#undef USE_SOCKETS -#undef NON_MAIN -#include "s_apps.h" -#include <openssl/ssl.h> - -#ifdef FLAT_INC -# include "e_os.h" -#else -# include "../e_os.h" -#endif - #ifndef OPENSSL_NO_SOCK -# if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) -# include "netdb.h" -# endif - -static struct hostent *GetHostByName(char *name); -# if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) -static void ssl_sock_cleanup(void); -# endif -static int ssl_sock_init(void); -static int init_client_ip(int *sock, unsigned char ip[4], int port, int type); -static int init_server(int *sock, int port, int type); -static int init_server_long(int *sock, int port, char *ip, int type); -static int do_accept(int acc_sock, int *sock, char **host); -static int host_ip(char *str, unsigned char ip[4]); - -# ifdef OPENSSL_SYS_WIN16 -# define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ -# else -# define SOCKET_PROTOCOL IPPROTO_TCP -# endif - -# if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) -static int wsa_init_done = 0; -# endif +# include "apps.h" +# include "s_apps.h" +# include "internal/sockets.h" -# ifdef OPENSSL_SYS_WINDOWS -static struct WSAData wsa_state; -static int wsa_init_done = 0; +# include <openssl/bio.h> +# include <openssl/err.h> -# ifdef OPENSSL_SYS_WIN16 -static HWND topWnd = 0; -static FARPROC lpTopWndProc = NULL; -static FARPROC lpTopHookProc = NULL; -extern HINSTANCE _hInstance; /* nice global CRT provides */ +/* Keep track of our peer's address for the cookie callback */ +BIO_ADDR *ourpeer = NULL; -static LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam, - LPARAM lParam) -{ - if (hwnd == topWnd) { - switch (message) { - case WM_DESTROY: - case WM_CLOSE: - SetWindowLong(topWnd, GWL_WNDPROC, (LONG) lpTopWndProc); - ssl_sock_cleanup(); - break; - } - } - return CallWindowProc(lpTopWndProc, hwnd, message, wParam, lParam); -} - -static BOOL CALLBACK enumproc(HWND hwnd, LPARAM lParam) +/* + * init_client - helper routine to set up socket communication + * @sock: pointer to storage of resulting socket. + * @host: the host name or path (for AF_UNIX) to connect to. + * @port: the port to connect to (ignored for AF_UNIX). + * @bindhost: source host or path (for AF_UNIX). + * @bindport: source port (ignored for AF_UNIX). + * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or + * AF_UNSPEC + * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM + * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any) + * + * This will create a socket and use it to connect to a host:port, or if + * family == AF_UNIX, to the path found in host. + * + * If the host has more than one address, it will try them one by one until + * a successful connection is established. The resulting socket will be + * found in *sock on success, it will be given INVALID_SOCKET otherwise. + * + * Returns 1 on success, 0 on failure. + */ +int init_client(int *sock, const char *host, const char *port, + const char *bindhost, const char *bindport, + int family, int type, int protocol) { - topWnd = hwnd; - return (FALSE); -} + BIO_ADDRINFO *res = NULL; + BIO_ADDRINFO *bindaddr = NULL; + const BIO_ADDRINFO *ai = NULL; + const BIO_ADDRINFO *bi = NULL; + int found = 0; + int ret; -# endif /* OPENSSL_SYS_WIN32 */ -# endif /* OPENSSL_SYS_WINDOWS */ + if (BIO_sock_init() != 1) + return 0; -# ifdef OPENSSL_SYS_WINDOWS -static void ssl_sock_cleanup(void) -{ - if (wsa_init_done) { - wsa_init_done = 0; -# ifndef OPENSSL_SYS_WINCE - WSACancelBlockingCall(); -# endif - WSACleanup(); - } -} -# elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) -static void sock_cleanup(void) -{ - if (wsa_init_done) { - wsa_init_done = 0; - WSACleanup(); + ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol, + &res); + if (ret == 0) { + ERR_print_errors(bio_err); + return 0; } -} -# endif -static int ssl_sock_init(void) -{ -# ifdef WATT32 - extern int _watt_do_exit; - _watt_do_exit = 0; - if (sock_init()) - return (0); -# elif defined(OPENSSL_SYS_WINDOWS) - if (!wsa_init_done) { - int err; - -# ifdef SIGINT - signal(SIGINT, (void (*)(int))ssl_sock_cleanup); -# endif - wsa_init_done = 1; - memset(&wsa_state, 0, sizeof(wsa_state)); - if (WSAStartup(0x0101, &wsa_state) != 0) { - err = WSAGetLastError(); - BIO_printf(bio_err, "unable to start WINSOCK, error code=%d\n", - err); - return (0); + if (bindhost != NULL || bindport != NULL) { + ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT, + family, type, protocol, &bindaddr); + if (ret == 0) { + ERR_print_errors (bio_err); + goto out; } -# ifdef OPENSSL_SYS_WIN16 - EnumTaskWindows(GetCurrentTask(), enumproc, 0L); - lpTopWndProc = (FARPROC) GetWindowLong(topWnd, GWL_WNDPROC); - lpTopHookProc = MakeProcInstance((FARPROC) topHookProc, _hInstance); - - SetWindowLong(topWnd, GWL_WNDPROC, (LONG) lpTopHookProc); -# endif /* OPENSSL_SYS_WIN16 */ } -# elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) - WORD wVerReq; - WSADATA wsaData; - int err; - if (!wsa_init_done) { + ret = 0; + for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) { + /* Admittedly, these checks are quite paranoid, we should not get + * anything in the BIO_ADDRINFO chain that we haven't + * asked for. */ + OPENSSL_assert((family == AF_UNSPEC + || family == BIO_ADDRINFO_family(ai)) + && (type == 0 || type == BIO_ADDRINFO_socktype(ai)) + && (protocol == 0 + || protocol == BIO_ADDRINFO_protocol(ai))); -# ifdef SIGINT - signal(SIGINT, (void (*)(int))sock_cleanup); -# endif - - wsa_init_done = 1; - wVerReq = MAKEWORD(2, 0); - err = WSAStartup(wVerReq, &wsaData); - if (err != 0) { - BIO_printf(bio_err, "unable to start WINSOCK2, error code=%d\n", - err); - return (0); + if (bindaddr != NULL) { + for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) { + if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai)) + break; + } + if (bi == NULL) + continue; + ++found; } - } -# endif /* OPENSSL_SYS_WINDOWS */ - return (1); -} -int init_client(int *sock, char *host, int port, int type) -{ - unsigned char ip[4]; - - memset(ip, '\0', sizeof(ip)); - if (!host_ip(host, &(ip[0]))) - return 0; - return init_client_ip(sock, ip, port, type); -} + *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai), + BIO_ADDRINFO_protocol(ai), 0); + if (*sock == INVALID_SOCKET) { + /* Maybe the kernel doesn't support the socket family, even if + * BIO_lookup() added it in the returned result... + */ + continue; + } -static int init_client_ip(int *sock, unsigned char ip[4], int port, int type) -{ - unsigned long addr; - struct sockaddr_in them; - int s, i; + if (bi != NULL) { + if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi), + BIO_SOCK_REUSEADDR)) { + BIO_closesocket(*sock); + *sock = INVALID_SOCKET; + break; + } + } - if (!ssl_sock_init()) - return (0); +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + /* + * For SCTP we have to set various options on the socket prior to + * connecting. This is done automatically by BIO_new_dgram_sctp(). + * We don't actually need the created BIO though so we free it again + * immediately. + */ + BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE); - memset((char *)&them, 0, sizeof(them)); - them.sin_family = AF_INET; - them.sin_port = htons((unsigned short)port); - addr = (unsigned long) - ((unsigned long)ip[0] << 24L) | - ((unsigned long)ip[1] << 16L) | - ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]); - them.sin_addr.s_addr = htonl(addr); + if (tmpbio == NULL) { + ERR_print_errors(bio_err); + return 0; + } + BIO_free(tmpbio); + } +#endif - if (type == SOCK_STREAM) - s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL); - else /* ( type == SOCK_DGRAM) */ - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), + protocol == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) { + BIO_closesocket(*sock); + *sock = INVALID_SOCKET; + continue; + } - if (s == INVALID_SOCKET) { - perror("socket"); - return (0); + /* Success, don't try any more addresses */ + break; } -# if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) - if (type == SOCK_STREAM) { - i = 0; - i = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof(i)); - if (i < 0) { - closesocket(s); - perror("keepalive"); - return (0); + + if (*sock == INVALID_SOCKET) { + if (bindaddr != NULL && !found) { + BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n", + BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " : + BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " : + BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "", + bindhost != NULL ? bindhost : "", + bindport != NULL ? ":" : "", + bindport != NULL ? bindport : ""); + ERR_clear_error(); + ret = 0; } + ERR_print_errors(bio_err); + } else { + /* Remove any stale errors from previous connection attempts */ + ERR_clear_error(); + ret = 1; } -# endif - - if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1) { - closesocket(s); - perror("connect"); - return (0); +out: + if (bindaddr != NULL) { + BIO_ADDRINFO_free (bindaddr); } - *sock = s; - return (1); + BIO_ADDRINFO_free(res); + return ret; } -int do_server(int port, int type, int *ret, - int (*cb) (char *hostname, int s, int stype, - unsigned char *context), unsigned char *context, - int naccept) +/* + * do_server - helper routine to perform a server operation + * @accept_sock: pointer to storage of resulting socket. + * @host: the host name or path (for AF_UNIX) to connect to. + * @port: the port to connect to (ignored for AF_UNIX). + * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or + * AF_UNSPEC + * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM + * @cb: pointer to a function that receives the accepted socket and + * should perform the communication with the connecting client. + * @context: pointer to memory that's passed verbatim to the cb function. + * @naccept: number of times an incoming connect should be accepted. If -1, + * unlimited number. + * + * This will create a socket and use it to listen to a host:port, or if + * family == AF_UNIX, to the path found in host, then start accepting + * incoming connections and run cb on the resulting socket. + * + * 0 on failure, something other on success. + */ +int do_server(int *accept_sock, const char *host, const char *port, + int family, int type, int protocol, do_server_cb cb, + unsigned char *context, int naccept, BIO *bio_s_out) { + int asock = 0; int sock; - char *name = NULL; - int accept_socket = 0; int i; - - if (!init_server(&accept_socket, port, type)) - return (0); - - if (ret != NULL) { - *ret = accept_socket; - /* return(1); */ - } - for (;;) { - if (type == SOCK_STREAM) { - if (do_accept(accept_socket, &sock, &name) == 0) { - SHUTDOWN(accept_socket); - return (0); - } - } else - sock = accept_socket; - i = (*cb) (name, sock, type, context); - if (name != NULL) - OPENSSL_free(name); - if (type == SOCK_STREAM) - SHUTDOWN2(sock); - if (naccept != -1) - naccept--; - if (i < 0 || naccept == 0) { - SHUTDOWN2(accept_socket); - return (i); - } - } -} - -static int init_server_long(int *sock, int port, char *ip, int type) -{ + BIO_ADDRINFO *res = NULL; + const BIO_ADDRINFO *next; + int sock_family, sock_type, sock_protocol, sock_port; + const BIO_ADDR *sock_address; + int sock_options = BIO_SOCK_REUSEADDR; int ret = 0; - struct sockaddr_in server; - int s = -1; - - if (!ssl_sock_init()) - return (0); - - memset((char *)&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons((unsigned short)port); - if (ip == NULL) - server.sin_addr.s_addr = INADDR_ANY; - else -/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */ -# ifndef BIT_FIELD_LIMITS - memcpy(&server.sin_addr.s_addr, ip, 4); -# else - memcpy(&server.sin_addr, ip, 4); -# endif - if (type == SOCK_STREAM) - s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL); - else /* type == SOCK_DGRAM */ - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (BIO_sock_init() != 1) + return 0; - if (s == INVALID_SOCKET) - goto err; -# if defined SOL_SOCKET && defined SO_REUSEADDR - { - int j = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&j, sizeof(j)); - } -# endif - if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) { -# ifndef OPENSSL_SYS_WINDOWS - perror("bind"); -# endif - goto err; - } - /* Make it 128 for linux */ - if (type == SOCK_STREAM && listen(s, 128) == -1) - goto err; - *sock = s; - ret = 1; - err: - if ((ret == 0) && (s != -1)) { - SHUTDOWN(s); + if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol, + &res)) { + ERR_print_errors(bio_err); + return 0; } - return (ret); -} -static int init_server(int *sock, int port, int type) -{ - return (init_server_long(sock, port, NULL, type)); -} + /* Admittedly, these checks are quite paranoid, we should not get + * anything in the BIO_ADDRINFO chain that we haven't asked for */ + OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res)) + && (type == 0 || type == BIO_ADDRINFO_socktype(res)) + && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res))); -static int do_accept(int acc_sock, int *sock, char **host) -{ - int ret; - struct hostent *h1, *h2; - static struct sockaddr_in from; - int len; -/* struct linger ling; */ - - if (!ssl_sock_init()) - return (0); - -# ifndef OPENSSL_SYS_WINDOWS - redoit: -# endif - - memset((char *)&from, 0, sizeof(from)); - len = sizeof(from); - /* - * Note: under VMS with SOCKETSHR the fourth parameter is currently of - * type (int *) whereas under other systems it is (void *) if you don't - * have a cast it will choke the compiler: if you do have a cast then you - * can either go for (int *) or (void *). - */ - ret = accept(acc_sock, (struct sockaddr *)&from, (void *)&len); - if (ret == INVALID_SOCKET) { -# if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) - int i; - i = WSAGetLastError(); - BIO_printf(bio_err, "accept error %d\n", i); -# else - if (errno == EINTR) { - /* - * check_timeout(); - */ - goto redoit; + sock_family = BIO_ADDRINFO_family(res); + sock_type = BIO_ADDRINFO_socktype(res); + sock_protocol = BIO_ADDRINFO_protocol(res); + sock_address = BIO_ADDRINFO_address(res); + next = BIO_ADDRINFO_next(res); + if (sock_family == AF_INET6) + sock_options |= BIO_SOCK_V6_ONLY; + if (next != NULL + && BIO_ADDRINFO_socktype(next) == sock_type + && BIO_ADDRINFO_protocol(next) == sock_protocol) { + if (sock_family == AF_INET + && BIO_ADDRINFO_family(next) == AF_INET6) { + sock_family = AF_INET6; + sock_address = BIO_ADDRINFO_address(next); + } else if (sock_family == AF_INET6 + && BIO_ADDRINFO_family(next) == AF_INET) { + sock_options &= ~BIO_SOCK_V6_ONLY; } - fprintf(stderr, "errno=%d ", errno); - perror("accept"); -# endif - return (0); } -/*- - ling.l_onoff=1; - ling.l_linger=0; - i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling)); - if (i < 0) { perror("linger"); return(0); } - i=0; - i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); - if (i < 0) { perror("keepalive"); return(0); } -*/ - - if (host == NULL) + asock = BIO_socket(sock_family, sock_type, sock_protocol, 0); + if (asock == INVALID_SOCKET + || !BIO_listen(asock, sock_address, sock_options)) { + BIO_ADDRINFO_free(res); + ERR_print_errors(bio_err); + if (asock != INVALID_SOCKET) + BIO_closesocket(asock); goto end; -# ifndef BIT_FIELD_LIMITS - /* I should use WSAAsyncGetHostByName() under windows */ - h1 = gethostbyaddr((char *)&from.sin_addr.s_addr, - sizeof(from.sin_addr.s_addr), AF_INET); -# else - h1 = gethostbyaddr((char *)&from.sin_addr, - sizeof(struct in_addr), AF_INET); -# endif - if (h1 == NULL) { - BIO_printf(bio_err, "bad gethostbyaddr\n"); - *host = NULL; - /* return(0); */ - } else { - if ((*host = (char *)OPENSSL_malloc(strlen(h1->h_name) + 1)) == NULL) { - perror("OPENSSL_malloc"); - closesocket(ret); - return (0); - } - BUF_strlcpy(*host, h1->h_name, strlen(h1->h_name) + 1); - - h2 = GetHostByName(*host); - if (h2 == NULL) { - BIO_printf(bio_err, "gethostbyname failure\n"); - closesocket(ret); - return (0); - } - if (h2->h_addrtype != AF_INET) { - BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n"); - closesocket(ret); - return (0); - } } - end: - *sock = ret; - return (1); -} -int extract_host_port(char *str, char **host_ptr, unsigned char *ip, - short *port_ptr) -{ - char *h, *p; +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + /* + * For SCTP we have to set various options on the socket prior to + * accepting. This is done automatically by BIO_new_dgram_sctp(). + * We don't actually need the created BIO though so we free it again + * immediately. + */ + BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE); - h = str; - p = strchr(str, ':'); - if (p == NULL) { - BIO_printf(bio_err, "no port defined\n"); - return (0); + if (tmpbio == NULL) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + BIO_free(tmpbio); } - *(p++) = '\0'; - - if ((ip != NULL) && !host_ip(str, ip)) - goto err; - if (host_ptr != NULL) - *host_ptr = h; +#endif - if (!extract_port(p, port_ptr)) - goto err; - return (1); - err: - return (0); -} + sock_port = BIO_ADDR_rawport(sock_address); -static int host_ip(char *str, unsigned char ip[4]) -{ - unsigned int in[4]; - int i; + BIO_ADDRINFO_free(res); + res = NULL; - if (sscanf(str, "%u.%u.%u.%u", &(in[0]), &(in[1]), &(in[2]), &(in[3])) == - 4) { - for (i = 0; i < 4; i++) - if (in[i] > 255) { - BIO_printf(bio_err, "invalid IP address\n"); - goto err; - } - ip[0] = in[0]; - ip[1] = in[1]; - ip[2] = in[2]; - ip[3] = in[3]; - } else { /* do a gethostbyname */ - struct hostent *he; + if (sock_port == 0) { + /* dynamically allocated port, report which one */ + union BIO_sock_info_u info; + char *hostname = NULL; + char *service = NULL; + int success = 0; - if (!ssl_sock_init()) - return (0); + if ((info.addr = BIO_ADDR_new()) != NULL + && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info) + && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL + && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL + && BIO_printf(bio_s_out, + strchr(hostname, ':') == NULL + ? /* IPv4 */ "ACCEPT %s:%s\n" + : /* IPv6 */ "ACCEPT [%s]:%s\n", + hostname, service) > 0) + success = 1; - he = GetHostByName(str); - if (he == NULL) { - BIO_printf(bio_err, "gethostbyname failure\n"); - goto err; - } - /* cast to short because of win16 winsock definition */ - if ((short)he->h_addrtype != AF_INET) { - BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n"); - return (0); + (void)BIO_flush(bio_s_out); + OPENSSL_free(hostname); + OPENSSL_free(service); + BIO_ADDR_free(info.addr); + if (!success) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; } - ip[0] = he->h_addr_list[0][0]; - ip[1] = he->h_addr_list[0][1]; - ip[2] = he->h_addr_list[0][2]; - ip[3] = he->h_addr_list[0][3]; - } - return (1); - err: - return (0); -} - -int extract_port(char *str, short *port_ptr) -{ - int i; - struct servent *s; - - i = atoi(str); - if (i != 0) - *port_ptr = (unsigned short)i; - else { - s = getservbyname(str, "tcp"); - if (s == NULL) { - BIO_printf(bio_err, "getservbyname failure for %s\n", str); - return (0); - } - *port_ptr = ntohs((unsigned short)s->s_port); + } else { + (void)BIO_printf(bio_s_out, "ACCEPT\n"); + (void)BIO_flush(bio_s_out); } - return (1); -} -# define GHBN_NUM 4 -static struct ghbn_cache_st { - char name[128]; - struct hostent ent; - unsigned long order; -} ghbn_cache[GHBN_NUM]; + if (accept_sock != NULL) + *accept_sock = asock; + for (;;) { + char sink[64]; + struct timeval timeout; + fd_set readfds; -static unsigned long ghbn_hits = 0L; -static unsigned long ghbn_miss = 0L; + if (type == SOCK_STREAM) { + BIO_ADDR_free(ourpeer); + ourpeer = BIO_ADDR_new(); + if (ourpeer == NULL) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + do { + sock = BIO_accept_ex(asock, ourpeer, 0); + } while (sock < 0 && BIO_sock_should_retry(sock)); + if (sock < 0) { + ERR_print_errors(bio_err); + BIO_closesocket(asock); + break; + } + BIO_set_tcp_ndelay(sock, 1); + i = (*cb)(sock, type, protocol, context); -static struct hostent *GetHostByName(char *name) -{ - struct hostent *ret; - int i, lowi = 0; - unsigned long low = (unsigned long)-1; + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(sock, 1); /* SHUT_WR */ + /* + * We just said we have nothing else to say, but it doesn't mean + * that the other side has nothing. It's even recommended to + * consume incoming data. [In testing context this ensures that + * alerts are passed on...] + */ + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* some extreme round-trip */ + do { + FD_ZERO(&readfds); + openssl_fdset(sock, &readfds); + } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 + && readsocket(sock, sink, sizeof(sink)) > 0); - for (i = 0; i < GHBN_NUM; i++) { - if (low > ghbn_cache[i].order) { - low = ghbn_cache[i].order; - lowi = i; + BIO_closesocket(sock); + } else { + i = (*cb)(asock, type, protocol, context); } - if (ghbn_cache[i].order > 0) { - if (strncmp(name, ghbn_cache[i].name, 128) == 0) - break; - } - } - if (i == GHBN_NUM) { /* no hit */ - ghbn_miss++; - ret = gethostbyname(name); - if (ret == NULL) - return (NULL); - /* else add to cache */ - if (strlen(name) < sizeof(ghbn_cache[0].name)) { - strcpy(ghbn_cache[lowi].name, name); - memcpy((char *)&(ghbn_cache[lowi].ent), ret, - sizeof(struct hostent)); - ghbn_cache[lowi].order = ghbn_miss + ghbn_hits; + + if (naccept != -1) + naccept--; + if (i < 0 || naccept == 0) { + BIO_closesocket(asock); + ret = i; + break; } - return (ret); - } else { - ghbn_hits++; - ret = &(ghbn_cache[i].ent); - ghbn_cache[i].order = ghbn_miss + ghbn_hits; - return (ret); } + end: +# ifdef AF_UNIX + if (family == AF_UNIX) + unlink(host); +# endif + BIO_ADDR_free(ourpeer); + ourpeer = NULL; + return ret; } -#endif +#endif /* OPENSSL_NO_SOCK */ diff --git a/apps/s_time.c b/apps/s_time.c index 0bb2f8cc2aa1..82d40a5a5132 100644 --- a/apps/s_time.c +++ b/apps/s_time.c @@ -1,336 +1,84 @@ -/* apps/s_time.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#define NO_SHUTDOWN - -/* ---------------------------------------- - s_time - SSL client connection timer program - Written and donated by Larry Streepy <streepy@healthcare.com> - -----------------------------------------*/ - #include <stdio.h> #include <stdlib.h> #include <string.h> -#define USE_SOCKETS +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_SOCK + #include "apps.h" -#ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -#endif +#include "progs.h" #include <openssl/x509.h> #include <openssl/ssl.h> #include <openssl/pem.h> #include "s_apps.h" #include <openssl/err.h> -#ifdef WIN32_STUFF -# include "winmain.h" -# include "wintext.h" -#endif +#include <internal/sockets.h> #if !defined(OPENSSL_SYS_MSDOS) # include OPENSSL_UNISTD #endif -#undef PROG -#define PROG s_time_main - -#undef ioctl -#define ioctl ioctlsocket - #define SSL_CONNECT_NAME "localhost:4433" -/* no default cert. */ -/* - * #define TEST_CERT "client.pem" - */ - -#undef BUFSIZZ -#define BUFSIZZ 1024*10 - -#define MYBUFSIZ 1024*8 - -#undef min -#undef max -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -#undef SECONDS #define SECONDS 30 -extern int verify_depth; -extern int verify_error; - -static void s_time_usage(void); -static int parseArgs(int argc, char **argv); -static SSL *doConnection(SSL *scon); -static void s_time_init(void); - -/*********************************************************************** - * Static data declarations - */ - -/* static char *port=PORT_STR;*/ -static char *host = SSL_CONNECT_NAME; -static char *t_cert_file = NULL; -static char *t_key_file = NULL; -static char *CApath = NULL; -static char *CAfile = NULL; -static char *tm_cipher = NULL; -static int tm_verify = SSL_VERIFY_NONE; -static int maxTime = SECONDS; -static SSL_CTX *tm_ctx = NULL; -static const SSL_METHOD *s_time_meth = NULL; -static char *s_www_path = NULL; -static long bytes_read = 0; -static int st_bugs = 0; -static int perform = 0; -#ifdef FIONBIO -static int t_nbio = 0; -#endif -#ifdef OPENSSL_SYS_WIN32 -static int exitNow = 0; /* Set when it's time to exit main */ -#endif +#define SECONDSSTR "30" -static void s_time_init(void) -{ - host = SSL_CONNECT_NAME; - t_cert_file = NULL; - t_key_file = NULL; - CApath = NULL; - CAfile = NULL; - tm_cipher = NULL; - tm_verify = SSL_VERIFY_NONE; - maxTime = SECONDS; - tm_ctx = NULL; - s_time_meth = NULL; - s_www_path = NULL; - bytes_read = 0; - st_bugs = 0; - perform = 0; +static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx); -#ifdef FIONBIO - t_nbio = 0; -#endif -#ifdef OPENSSL_SYS_WIN32 - exitNow = 0; /* Set when it's time to exit main */ -#endif -} - -/*********************************************************************** - * usage - display usage message - */ -static void s_time_usage(void) -{ - static char umsg[] = "\ --time arg - max number of seconds to collect data, default %d\n\ --verify arg - turn on peer certificate verification, arg == depth\n\ --cert arg - certificate file to use, PEM format assumed\n\ --key arg - RSA file to use, PEM format assumed, key is in cert file\n\ - file if not specified by this option\n\ --CApath arg - PEM format directory of CA's\n\ --CAfile arg - PEM format file of CA's\n\ --cipher - preferred cipher to use, play with 'openssl ciphers'\n\n"; - - printf("usage: s_time <args>\n\n"); - - printf("-connect host:port - host:port to connect to (default is %s)\n", - SSL_CONNECT_NAME); -#ifdef FIONBIO - printf("-nbio - Run with non-blocking IO\n"); - printf("-ssl2 - Just use SSLv2\n"); - printf("-ssl3 - Just use SSLv3\n"); - printf("-bugs - Turn on SSL bug compatibility\n"); - printf("-new - Just time new connections\n"); - printf("-reuse - Just time connection reuse\n"); - printf("-www page - Retrieve 'page' from the site\n"); -#endif - printf(umsg, SECONDS); -} - -/*********************************************************************** - * parseArgs - Parse command line arguments and initialize data - * - * Returns 0 if ok, -1 on bad args +/* + * Define a HTTP get command globally. + * Also define the size of the command, this is two bytes less than + * the size of the string because the %s is replaced by the URL. */ -static int parseArgs(int argc, char **argv) -{ - int badop = 0; - - verify_depth = 0; - verify_error = X509_V_OK; - - argc--; - argv++; - - while (argc >= 1) { - if (strcmp(*argv, "-connect") == 0) { - if (--argc < 1) - goto bad; - host = *(++argv); - } -#if 0 - else if (strcmp(*argv, "-host") == 0) { - if (--argc < 1) - goto bad; - host = *(++argv); - } else if (strcmp(*argv, "-port") == 0) { - if (--argc < 1) - goto bad; - port = *(++argv); - } -#endif - else if (strcmp(*argv, "-reuse") == 0) - perform = 2; - else if (strcmp(*argv, "-new") == 0) - perform = 1; - else if (strcmp(*argv, "-verify") == 0) { - - tm_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; - if (--argc < 1) - goto bad; - verify_depth = atoi(*(++argv)); - BIO_printf(bio_err, "verify depth is %d\n", verify_depth); - - } else if (strcmp(*argv, "-cert") == 0) { - - if (--argc < 1) - goto bad; - t_cert_file = *(++argv); - - } else if (strcmp(*argv, "-key") == 0) { - - if (--argc < 1) - goto bad; - t_key_file = *(++argv); - - } else if (strcmp(*argv, "-CApath") == 0) { - - if (--argc < 1) - goto bad; - CApath = *(++argv); +static const char fmt_http_get_cmd[] = "GET %s HTTP/1.0\r\n\r\n"; +static const size_t fmt_http_get_cmd_size = sizeof(fmt_http_get_cmd) - 2; - } else if (strcmp(*argv, "-CAfile") == 0) { +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_CONNECT, OPT_CIPHER, OPT_CIPHERSUITES, OPT_CERT, OPT_NAMEOPT, OPT_KEY, + OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NEW, OPT_REUSE, + OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3, + OPT_WWW +} OPTION_CHOICE; - if (--argc < 1) - goto bad; - CAfile = *(++argv); - - } else if (strcmp(*argv, "-cipher") == 0) { - - if (--argc < 1) - goto bad; - tm_cipher = *(++argv); - } -#ifdef FIONBIO - else if (strcmp(*argv, "-nbio") == 0) { - t_nbio = 1; - } -#endif - else if (strcmp(*argv, "-www") == 0) { - if (--argc < 1) - goto bad; - s_www_path = *(++argv); - if (strlen(s_www_path) > MYBUFSIZ - 100) { - BIO_printf(bio_err, "-www option too long\n"); - badop = 1; - } - } else if (strcmp(*argv, "-bugs") == 0) - st_bugs = 1; -#ifndef OPENSSL_NO_SSL2 - else if (strcmp(*argv, "-ssl2") == 0) - s_time_meth = SSLv2_client_method(); -#endif +const OPTIONS s_time_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"connect", OPT_CONNECT, 's', + "Where to connect as post:port (default is " SSL_CONNECT_NAME ")"}, + {"cipher", OPT_CIPHER, 's', "TLSv1.2 and below cipher list to be used"}, + {"ciphersuites", OPT_CIPHERSUITES, 's', + "Specify TLSv1.3 ciphersuites to be used"}, + {"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"cafile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"new", OPT_NEW, '-', "Just time new connections"}, + {"reuse", OPT_REUSE, '-', "Just time connection reuse"}, + {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"}, + {"verify", OPT_VERIFY, 'p', + "Turn on peer certificate verification, set depth"}, + {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR}, + {"www", OPT_WWW, 's', "Fetch specified page from the site"}, #ifndef OPENSSL_NO_SSL3 - else if (strcmp(*argv, "-ssl3") == 0) - s_time_meth = SSLv3_client_method(); + {"ssl3", OPT_SSL3, '-', "Just use SSLv3"}, #endif - else if (strcmp(*argv, "-time") == 0) { - - if (--argc < 1) - goto bad; - maxTime = atoi(*(++argv)); - if (maxTime <= 0) { - BIO_printf(bio_err, "time must be > 0\n"); - badop = 1; - } - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badop = 1; - break; - } - - argc--; - argv++; - } - - if (perform == 0) - perform = 3; - - if (badop) { - bad: - s_time_usage(); - return -1; - } + {NULL} +}; - return 0; /* Valid args */ -} - -/*********************************************************************** - * TIME - time functions - */ #define START 0 #define STOP 1 @@ -339,113 +87,164 @@ static double tm_Time_F(int s) return app_tminterval(s, 1); } -/*********************************************************************** - * MAIN - main processing area for client - * real name depends on MONOLITH - */ -int MAIN(int, char **); - -int MAIN(int argc, char **argv) +int s_time_main(int argc, char **argv) { - double totalTime = 0.0; - int nConn = 0; + char buf[1024 * 8]; SSL *scon = NULL; - long finishtime = 0; - int ret = 1, i; - MS_STATIC char buf[1024 * 8]; - int ver; + SSL_CTX *ctx = NULL; + const SSL_METHOD *meth = NULL; + char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *ciphersuites = NULL; + char *www_path = NULL; + char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog; + double totalTime = 0.0; + int noCApath = 0, noCAfile = 0; + int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0; + long bytes_read = 0, finishtime = 0; + OPTION_CHOICE o; + int max_version = 0, ver, buf_len; + size_t buf_size; - apps_startup(); - s_time_init(); + meth = TLS_client_method(); - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + prog = opt_init(argc, argv, s_time_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(s_time_options); + ret = 0; + goto end; + case OPT_CONNECT: + host = opt_arg(); + break; + case OPT_REUSE: + perform = 2; + break; + case OPT_NEW: + perform = 1; + break; + case OPT_VERIFY: + if (!opt_int(opt_arg(), &verify_args.depth)) + goto opthelp; + BIO_printf(bio_err, "%s: verify depth is %d\n", + prog, verify_args.depth); + break; + case OPT_CERT: + certfile = opt_arg(); + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_CIPHER: + cipher = opt_arg(); + break; + case OPT_CIPHERSUITES: + ciphersuites = opt_arg(); + break; + case OPT_BUGS: + st_bugs = 1; + break; + case OPT_TIME: + if (!opt_int(opt_arg(), &maxtime)) + goto opthelp; + break; + case OPT_WWW: + www_path = opt_arg(); + buf_size = strlen(www_path) + fmt_http_get_cmd_size; + if (buf_size > sizeof(buf)) { + BIO_printf(bio_err, "%s: -www option is too long\n", prog); + goto end; + } + break; + case OPT_SSL3: + max_version = SSL3_VERSION; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - s_time_meth = SSLv23_client_method(); + if (cipher == NULL) + cipher = getenv("SSL_CIPHER"); - /* parse the command line arguments */ - if (parseArgs(argc, argv) < 0) + if ((ctx = SSL_CTX_new(meth)) == NULL) goto end; - OpenSSL_add_ssl_algorithms(); - if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL) - return (1); - - SSL_CTX_set_quiet_shutdown(tm_ctx, 1); + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + SSL_CTX_set_quiet_shutdown(ctx, 1); + if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto end; if (st_bugs) - SSL_CTX_set_options(tm_ctx, SSL_OP_ALL); - SSL_CTX_set_cipher_list(tm_ctx, tm_cipher); - if (!set_cert_stuff(tm_ctx, t_cert_file, t_key_file)) + SSL_CTX_set_options(ctx, SSL_OP_ALL); + if (cipher != NULL && !SSL_CTX_set_cipher_list(ctx, cipher)) + goto end; + if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) + goto end; + if (!set_cert_stuff(ctx, certfile, keyfile)) goto end; - SSL_load_error_strings(); - - if ((!SSL_CTX_load_verify_locations(tm_ctx, CAfile, CApath)) || - (!SSL_CTX_set_default_verify_paths(tm_ctx))) { - /* - * BIO_printf(bio_err,"error setting default verify locations\n"); - */ + if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { ERR_print_errors(bio_err); - /* goto end; */ - } - - if (tm_cipher == NULL) - tm_cipher = getenv("SSL_CIPHER"); - - if (tm_cipher == NULL) { - fprintf(stderr, "No CIPHER specified\n"); + goto end; } - if (!(perform & 1)) goto next; - printf("Collecting connection statistics for %d seconds\n", maxTime); + printf("Collecting connection statistics for %d seconds\n", maxtime); /* Loop and time how long it takes to make connections */ bytes_read = 0; - finishtime = (long)time(NULL) + maxTime; + finishtime = (long)time(NULL) + maxtime; tm_Time_F(START); for (;;) { if (finishtime < (long)time(NULL)) break; -#ifdef WIN32_STUFF - - if (flushWinMsgs(0) == -1) - goto end; - if (waitingToDie || exitNow) /* we're dead */ + if ((scon = doConnection(NULL, host, ctx)) == NULL) goto end; -#endif - if ((scon = doConnection(NULL)) == NULL) - goto end; - - if (s_www_path != NULL) { - BIO_snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n\r\n", - s_www_path); - SSL_write(scon, buf, strlen(buf)); + if (www_path != NULL) { + buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, + www_path); + if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) + goto end; while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) bytes_read += i; } -#ifdef NO_SHUTDOWN SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); -#else - SSL_shutdown(scon); -#endif - SHUTDOWN2(SSL_get_fd(scon)); + BIO_closesocket(SSL_get_fd(scon)); nConn += 1; - if (SSL_session_reused(scon)) + if (SSL_session_reused(scon)) { ver = 'r'; - else { + } else { ver = SSL_version(scon); if (ver == TLS1_VERSION) ver = 't'; else if (ver == SSL3_VERSION) ver = '3'; - else if (ver == SSL2_VERSION) - ver = '2'; else ver = '*'; } @@ -457,13 +256,13 @@ int MAIN(int argc, char **argv) } totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ - i = (int)((long)time(NULL) - finishtime + maxTime); + i = (int)((long)time(NULL) - finishtime + maxtime); printf ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn / totalTime), bytes_read); printf ("%d connections in %ld real seconds, %ld bytes read per connection\n", - nConn, (long)time(NULL) - finishtime + maxTime, bytes_read / nConn); + nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); /* * Now loop and time connections using the same session id over and over @@ -475,27 +274,25 @@ int MAIN(int argc, char **argv) printf("\n\nNow timing with session id reuse.\n"); /* Get an SSL object so we can reuse the session id */ - if ((scon = doConnection(NULL)) == NULL) { - fprintf(stderr, "Unable to get connection\n"); + if ((scon = doConnection(NULL, host, ctx)) == NULL) { + BIO_printf(bio_err, "Unable to get connection\n"); goto end; } - if (s_www_path != NULL) { - BIO_snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n\r\n", s_www_path); - SSL_write(scon, buf, strlen(buf)); - while (SSL_read(scon, buf, sizeof(buf)) > 0) ; + if (www_path != NULL) { + buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path); + if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) + goto end; + while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) + continue; } -#ifdef NO_SHUTDOWN SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); -#else - SSL_shutdown(scon); -#endif - SHUTDOWN2(SSL_get_fd(scon)); + BIO_closesocket(SSL_get_fd(scon)); nConn = 0; totalTime = 0.0; - finishtime = (long)time(NULL) + maxTime; + finishtime = (long)time(NULL) + maxtime; printf("starting\n"); bytes_read = 0; @@ -505,42 +302,29 @@ int MAIN(int argc, char **argv) if (finishtime < (long)time(NULL)) break; -#ifdef WIN32_STUFF - if (flushWinMsgs(0) == -1) - goto end; - - if (waitingToDie || exitNow) /* we're dead */ - goto end; -#endif - - if ((doConnection(scon)) == NULL) + if ((doConnection(scon, host, ctx)) == NULL) goto end; - if (s_www_path) { - BIO_snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n\r\n", - s_www_path); - SSL_write(scon, buf, strlen(buf)); + if (www_path != NULL) { + buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, + www_path); + if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) + goto end; while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) bytes_read += i; } -#ifdef NO_SHUTDOWN SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); -#else - SSL_shutdown(scon); -#endif - SHUTDOWN2(SSL_get_fd(scon)); + BIO_closesocket(SSL_get_fd(scon)); nConn += 1; - if (SSL_session_reused(scon)) + if (SSL_session_reused(scon)) { ver = 'r'; - else { + } else { ver = SSL_version(scon); if (ver == TLS1_VERSION) ver = 't'; else if (ver == SSL3_VERSION) ver = '3'; - else if (ver == SSL2_VERSION) - ver = '2'; else ver = '*'; } @@ -554,44 +338,33 @@ int MAIN(int argc, char **argv) nConn, totalTime, ((double)nConn / totalTime), bytes_read); printf ("%d connections in %ld real seconds, %ld bytes read per connection\n", - nConn, (long)time(NULL) - finishtime + maxTime, - bytes_read / (nConn?nConn:1)); + nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); ret = 0; - end: - if (scon != NULL) - SSL_free(scon); - if (tm_ctx != NULL) { - SSL_CTX_free(tm_ctx); - tm_ctx = NULL; - } - apps_shutdown(); - OPENSSL_EXIT(ret); + end: + SSL_free(scon); + SSL_CTX_free(ctx); + return ret; } /*- * doConnection - make a connection - * Args: - * scon = earlier ssl connection for session id, or NULL - * Returns: - * SSL * = the connection pointer. */ -static SSL *doConnection(SSL *scon) +static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx) { BIO *conn; SSL *serverCon; - int width, i; - fd_set readfds; + int i; if ((conn = BIO_new(BIO_s_connect())) == NULL) - return (NULL); + return NULL; -/* BIO_set_conn_port(conn,port);*/ BIO_set_conn_hostname(conn, host); + BIO_set_conn_mode(conn, BIO_SOCK_NODELAY); if (scon == NULL) - serverCon = SSL_new(tm_ctx); + serverCon = SSL_new(ctx); else { serverCon = scon; SSL_set_connect_state(serverCon); @@ -599,37 +372,13 @@ static SSL *doConnection(SSL *scon) SSL_set_bio(serverCon, conn, conn); -#if 0 - if (scon != NULL) - SSL_set_session(serverCon, SSL_get_session(scon)); -#endif - /* ok, lets connect */ - for (;;) { - i = SSL_connect(serverCon); - if (BIO_sock_should_retry(i)) { - BIO_printf(bio_err, "DELAY\n"); - - i = SSL_get_fd(serverCon); - width = i + 1; - FD_ZERO(&readfds); - openssl_fdset(i, &readfds); - /* - * Note: under VMS with SOCKETSHR the 2nd parameter is currently - * of type (int *) whereas under other systems it is (void *) if - * you don't have a cast it will choke the compiler: if you do - * have a cast then you can either go for (int *) or (void *). - */ - select(width, (void *)&readfds, NULL, NULL, NULL); - continue; - } - break; - } + i = SSL_connect(serverCon); if (i <= 0) { BIO_printf(bio_err, "ERROR\n"); - if (verify_error != X509_V_OK) + if (verify_args.error != X509_V_OK) BIO_printf(bio_err, "verify error:%s\n", - X509_verify_cert_error_string(verify_error)); + X509_verify_cert_error_string(verify_args.error)); else ERR_print_errors(bio_err); if (scon == NULL) @@ -637,5 +386,20 @@ static SSL *doConnection(SSL *scon) return NULL; } +#if defined(SOL_SOCKET) && defined(SO_LINGER) + { + struct linger no_linger; + int fd; + + no_linger.l_onoff = 1; + no_linger.l_linger = 0; + fd = SSL_get_fd(serverCon); + if (fd >= 0) + (void)setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&no_linger, + sizeof(no_linger)); + } +#endif + return serverCon; } +#endif /* OPENSSL_NO_SOCK */ diff --git a/apps/sess_id.c b/apps/sess_id.c index 7773abec7ed1..8fd584f3b131 100644 --- a/apps/sess_id.c +++ b/apps/sess_id.c @@ -1,215 +1,123 @@ -/* apps/sess_id.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/x509.h> #include <openssl/pem.h> #include <openssl/ssl.h> -#undef PROG -#define PROG sess_id_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, + OPT_TEXT, OPT_CERT, OPT_NOOUT, OPT_CONTEXT +} OPTION_CHOICE; -static const char *sess_id_usage[] = { - "usage: sess_id args\n", - "\n", - " -inform arg - input format - default PEM (DER or PEM)\n", - " -outform arg - output format - default PEM\n", - " -in arg - input file - default stdin\n", - " -out arg - output file - default stdout\n", - " -text - print ssl session id details\n", - " -cert - output certificate \n", - " -noout - no CRL output\n", - " -context arg - set the session ID context\n", - NULL +const OPTIONS sess_id_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'f', + "Output format - default PEM (PEM, DER or NSS)"}, + {"in", OPT_IN, 's', "Input file - default stdin"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"text", OPT_TEXT, '-', "Print ssl session id details"}, + {"cert", OPT_CERT, '-', "Output certificate "}, + {"noout", OPT_NOOUT, '-', "Don't output the encoded session info"}, + {"context", OPT_CONTEXT, 's', "Set the session ID context"}, + {NULL} }; static SSL_SESSION *load_sess_id(char *file, int format); -int MAIN(int, char **); - -int MAIN(int argc, char **argv) +int sess_id_main(int argc, char **argv) { SSL_SESSION *x = NULL; X509 *peer = NULL; - int ret = 1, i, num, badops = 0; BIO *out = NULL; - int informat, outformat; - char *infile = NULL, *outfile = NULL, *context = NULL; - int cert = 0, noout = 0, text = 0; - const char **pp; + char *infile = NULL, *outfile = NULL, *context = NULL, *prog; + int informat = FORMAT_PEM, outformat = FORMAT_PEM; + int cert = 0, noout = 0, text = 0, ret = 1, i, num = 0; + OPTION_CHOICE o; - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - - argc--; - argv++; - num = 0; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-text") == 0) + prog = opt_init(argc, argv, sess_id_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(sess_id_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER | OPT_FMT_NSS, + &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_TEXT: text = ++num; - else if (strcmp(*argv, "-cert") == 0) + break; + case OPT_CERT: cert = ++num; - else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_NOOUT: noout = ++num; - else if (strcmp(*argv, "-context") == 0) { - if (--argc < 1) - goto bad; - context = *++argv; - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; + break; + case OPT_CONTEXT: + context = opt_arg(); break; } - argc--; - argv++; } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - if (badops) { - bad: - for (pp = sess_id_usage; (*pp != NULL); pp++) - BIO_printf(bio_err, "%s", *pp); - goto end; - } - - ERR_load_crypto_strings(); x = load_sess_id(infile, informat); if (x == NULL) { goto end; } peer = SSL_SESSION_get0_peer(x); - if (context) { + if (context != NULL) { size_t ctx_len = strlen(context); if (ctx_len > SSL_MAX_SID_CTX_LENGTH) { BIO_printf(bio_err, "Context too long\n"); goto end; } - SSL_SESSION_set1_id_context(x, (unsigned char *)context, ctx_len); - } -#ifdef undef - /* just testing for memory leaks :-) */ - { - SSL_SESSION *s; - char buf[1024 * 10], *p; - int i; - - s = SSL_SESSION_new(); - - p = &buf; - i = i2d_SSL_SESSION(x, &p); - p = &buf; - d2i_SSL_SESSION(&s, &p, (long)i); - p = &buf; - d2i_SSL_SESSION(&s, &p, (long)i); - p = &buf; - d2i_SSL_SESSION(&s, &p, (long)i); - SSL_SESSION_free(s); + if (!SSL_SESSION_set1_id_context(x, (unsigned char *)context, + ctx_len)) { + BIO_printf(bio_err, "Error setting id context\n"); + goto end; + } } -#endif if (!noout || text) { - out = BIO_new(BIO_s_file()); - if (out == NULL) { - ERR_print_errors(bio_err); + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) goto end; - } - - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } } if (text) { @@ -224,11 +132,13 @@ int MAIN(int argc, char **argv) } if (!noout && !cert) { - if (outformat == FORMAT_ASN1) + if (outformat == FORMAT_ASN1) { i = i2d_SSL_SESSION_bio(out, x); - else if (outformat == FORMAT_PEM) + } else if (outformat == FORMAT_PEM) { i = PEM_write_bio_SSL_SESSION(out, x); - else { + } else if (outformat == FORMAT_NSS) { + i = SSL_SESSION_print_keylog(out, x); + } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } @@ -237,11 +147,11 @@ int MAIN(int argc, char **argv) goto end; } } else if (!noout && (peer != NULL)) { /* just print the certificate */ - if (outformat == FORMAT_ASN1) + if (outformat == FORMAT_ASN1) { i = (int)i2d_X509_bio(out, peer); - else if (outformat == FORMAT_PEM) + } else if (outformat == FORMAT_PEM) { i = PEM_write_bio_X509(out, peer); - else { + } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } @@ -252,12 +162,9 @@ int MAIN(int argc, char **argv) } ret = 0; end: - if (out != NULL) - BIO_free_all(out); - if (x != NULL) - SSL_SESSION_free(x); - apps_shutdown(); - OPENSSL_EXIT(ret); + BIO_free_all(out); + SSL_SESSION_free(x); + return ret; } static SSL_SESSION *load_sess_id(char *infile, int format) @@ -265,28 +172,13 @@ static SSL_SESSION *load_sess_id(char *infile, int format) SSL_SESSION *x = NULL; BIO *in = NULL; - in = BIO_new(BIO_s_file()); - if (in == NULL) { - ERR_print_errors(bio_err); + in = bio_open_default(infile, 'r', format); + if (in == NULL) goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - goto end; - } - } if (format == FORMAT_ASN1) x = d2i_SSL_SESSION_bio(in, NULL); - else if (format == FORMAT_PEM) + else x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); - else { - BIO_printf(bio_err, "bad input format specified for input crl\n"); - goto end; - } if (x == NULL) { BIO_printf(bio_err, "unable to load SSL_SESSION\n"); ERR_print_errors(bio_err); @@ -294,7 +186,6 @@ static SSL_SESSION *load_sess_id(char *infile, int format) } end: - if (in != NULL) - BIO_free(in); - return (x); + BIO_free(in); + return x; } diff --git a/apps/set/set-g-ca.pem b/apps/set/set-g-ca.pem deleted file mode 100644 index 78499f05706c..000000000000 --- a/apps/set/set-g-ca.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDeDCCAuGgAwIBAgIgYCYUeg8NJ9kO1q3z6vGCkAmPRfu5+Nur0FyGF79MADMw -DQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0JDQTEwMTcx -MTA0MSAwHgYDVQQDExdCcmFuZCBOYW1lOlByb2R1Y3QgVHlwZTAeFw05NjEwMjIw -MDAwMDBaFw05NjExMjEyMzU5NTlaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtQ -Q0ExMDIxMTgyODEgMB4GA1UEAxMXQnJhbmQgTmFtZTpQcm9kdWN0IFR5cGUwgZ8w -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJyi5V7l1HohY6hN/2N9x6mvWeMy8rD1 -6lfXjgmiuGmhpaszWYaalesMcS2OGuG8Lq3PkaSzpVzqASKfIOjxLMsdpYyYJRub -vRPDWi3xd8wlp9xUwWHKqn+ki8mPo0yN4eONwZZ4rcZr6K+tWd+5EJZSjuENJoQ/ -SRRmGRzdcS7XAgMBAAGjggFXMIIBUzBUBgNVHSMETTBLoSekJTAjMQswCQYDVQQG -EwJVUzEUMBIGA1UEChMLUkNBMTAxMTE4MjmCIGApUs14Ad7t9VTGq2PpV8DylPQ7 -aATM2mor7lc1fWvZMA4GA1UdDwEB/wQEAwIBBjAuBgNVHRABAf8EJDAigA8xOTk2 -MTAyMjAxMjIwMFqBDzE5OTYxMTIxMjM1OTU5WjAbBgNVHSABAf8EETAPMA0GC2CG -SAGG+EUBBwEBMBIGA1UdEwEB/wQIMAYBAf8CAQAwDwYEho1vAwEB/wQEAwICBDB5 -BgSGjW8HAQH/BG4wbDAkAgEAMAkGBSsOAwIaBQAEFDJmNzRiMWFmNGZjYzA2MGY3 -Njc2Ew90ZXJzZSBzdGF0ZW1lbnSAF2h0dHA6Ly93d3cudmVyaXNpZ24uY29tgRpn -ZXRzZXQtY2VudGVyQHZlcmlzaWduLmNvbTANBgkqhkiG9w0BAQUFAAOBgQBn19R2 -AgGvpJDmfXrHTDdCoYyMkaP2MPzw0hFRwh+wqnw0/pqUXa7MrLXMqtD3rUyOWaNR -9fYpJZd0Bh/1OeIc2+U+VNfUovLLuZ8nNemdxyq2KMYnHtnh7UdO7atZ+PFLVu8x -a+J2Mtj8MGy12CJNTJcjLSrJ/1f3AuVrwELjlQ== ------END CERTIFICATE----- diff --git a/apps/set/set-m-ca.pem b/apps/set/set-m-ca.pem deleted file mode 100644 index 0e74caff67b8..000000000000 --- a/apps/set/set-m-ca.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDeDCCAuGgAwIBAgIgEGvcf5aUnufALdVMa/dmPdflq1CoORGeK5DUwbqhVYcw -DQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0JDQTEwMTcx -MTA0MSAwHgYDVQQDExdCcmFuZCBOYW1lOlByb2R1Y3QgVHlwZTAeFw05NjEwMjIw -MDAwMDBaFw05NjExMjEyMzU5NTlaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtN -Q0ExMDIxMTgyNzEgMB4GA1UEAxMXQnJhbmQgTmFtZTpQcm9kdWN0IFR5cGUwgZ8w -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALuWwr63YrT1GIZpYKfIeiVFHESG/FZO -7RAJKml/p12ZyZ7D5YPP4BBXVsa1H8e8arR1LKC4rdCArrtKKlBeBiMo9+NB+u35 -FnLnTmfzM4iZ2Syw35DXY8+Xn/LM7RJ1RG+vMNcTqpoUg7QPye7flq2Pt7vVROPn -SZxPyVxmILe3AgMBAAGjggFXMIIBUzBUBgNVHSMETTBLoSekJTAjMQswCQYDVQQG -EwJVUzEUMBIGA1UEChMLUkNBMTAxMTE4MjmCIGApUs14Ad7t9VTGq2PpV8DylPQ7 -aATM2mor7lc1fWvZMA4GA1UdDwEB/wQEAwIBBjAuBgNVHRABAf8EJDAigA8xOTk2 -MTAyMjAxMjEwMFqBDzE5OTYxMTIxMjM1OTU5WjAbBgNVHSABAf8EETAPMA0GC2CG -SAGG+EUBBwEBMBIGA1UdEwEB/wQIMAYBAf8CAQAwDwYEho1vAwEB/wQEAwIDCDB5 -BgSGjW8HAQH/BG4wbDAkAgEAMAkGBSsOAwIaBQAEFDJmNzRiMWFmNGZjYzA2MGY3 -Njc2Ew90ZXJzZSBzdGF0ZW1lbnSAF2h0dHA6Ly93d3cudmVyaXNpZ24uY29tgRpn -ZXRzZXQtY2VudGVyQHZlcmlzaWduLmNvbTANBgkqhkiG9w0BAQUFAAOBgQApaj0W -GgyR47URZEZ7z83yivvnVErqtodub/nR1fMgJ4bDC0ofjA0SzXBP1/3eDq9VkPuS -EKUw9BpM2XrSUKhJ6F1CbBjWpM0M7GC1nTSxMxmV+XL+Ab/Gn2SwozUApWtht29/ -x9VLB8qsi6wN2aOsVdQMl5iVCjGQYfEkyuoIgA== ------END CERTIFICATE----- diff --git a/apps/set/set_b_ca.pem b/apps/set/set_b_ca.pem deleted file mode 100644 index eba7d5cf54bd..000000000000 --- a/apps/set/set_b_ca.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID1zCCAr+gAwIBAgIgYClSzXgB3u31VMarY+lXwPKU9DtoBMzaaivuVzV9a9kw -DQYJKoZIhvcNAQEFBQAwIzELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1JDQTEwMTEx -ODI5MB4XDTk2MTAxNzAwMDAwMFoXDTk2MTExNjIzNTk1OVowRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0JDQTEwMTcxMTA0MSAwHgYDVQQDExdCcmFuZCBOYW1lOlBy -b2R1Y3QgVHlwZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApPewvR0BwV02 -9E12ic48pMY/aMB6SkMEWPDx2hURr0DKYGJ6qMvzZn2pSfaVH1BqDtK6oK4Ye5Mj -ItywwQIdXXO9Ut8+TLnvtzq9ByCJ0YThjZJBc7ZcpJxSV7QAoBON/lzxZuAVq3+L -3uc39MgRwmBpRllZEpWrkojxs6166X0CAwEAAaOCAVcwggFTMFQGA1UdIwRNMEuh -J6QlMCMxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtSQ0ExMDExMTgyOYIgVqenwCYv -mmxUIvi9gUMCa+uJGJ60mZecw9HrISXnLaYwDgYDVR0PAQH/BAQDAgEGMC4GA1Ud -EAEB/wQkMCKADzE5OTYxMDE3MTc1NzAwWoEPMTk5NjExMTYyMzU5NTlaMBsGA1Ud -IAEB/wQRMA8wDQYLYIZIAYb4RQEHAQEwEgYDVR0TAQH/BAgwBgEB/wIBATAPBgSG -jW8DAQH/BAQDAgABMHkGBIaNbwcBAf8EbjBsMCQCAQAwCQYFKw4DAhoFAAQUMmY3 -NGIxYWY0ZmNjMDYwZjc2NzYTD3RlcnNlIHN0YXRlbWVudIAXaHR0cDovL3d3dy52 -ZXJpc2lnbi5jb22BGmdldHNldC1jZW50ZXJAdmVyaXNpZ24uY29tMA0GCSqGSIb3 -DQEBBQUAA4IBAQAWoMS8Aj2sO0LDxRoMcnWTKY8nd8Jw2vl2Mgsm+0qCvcndICM5 -43N0y9uHlP8WeCZULbFz95gTL8mfP/QTu4EctMUkQgRHJnx80f0XSF3HE/X6zBbI -9rit/bF6yP1mhkdss/vGanReDpki7q8pLx+VIIcxWst/366HP3dW1Fb7ECW/WmVV -VMN93f/xqk9I4sXchVZcVKQT3W4tzv+qQvugrEi1dSEkbAy1CITEAEGiaFhGUyCe -WPox3guRXaEHoINNeajGrISe6d//alsz5EEroBoLnM2ryqWfLAtRsf4rjNzTgklw -lbiz0fw7bNkXKp5ZVr0wlnOjQnoSM6dTI0AV ------END CERTIFICATE----- diff --git a/apps/set/set_c_ca.pem b/apps/set/set_c_ca.pem deleted file mode 100644 index 48b2cbdc7cd5..000000000000 --- a/apps/set/set_c_ca.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDeDCCAuGgAwIBAgIgOnl8J6lAYNDdTWtIojWCGnloNf4ufHjOZ4Fkxwg5xOsw -DQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0JDQTEwMTcx -MTA0MSAwHgYDVQQDExdCcmFuZCBOYW1lOlByb2R1Y3QgVHlwZTAeFw05NjEwMjIw -MDAwMDBaFw05NjExMjEyMzU5NTlaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtD -Q0ExMDIxMTYxNjEgMB4GA1UEAxMXQnJhbmQgTmFtZTpQcm9kdWN0IFR5cGUwgZ8w -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANA3a9+U8oXU3Dv1wJf8g0A7HjCRZAXc -Y8E4OLOdye5aUssxifCE05qTPVqHMXo6cnCYcfroMdURhjQlswyTGtjQybgUnXjp -pchw+V4D1DkN0ThErrMCh9ZFSykC0lUhQTRLESvbIb4Gal/HMAFAF5sj0GoOFi2H -RRj7gpzBIU3xAgMBAAGjggFXMIIBUzBUBgNVHSMETTBLoSekJTAjMQswCQYDVQQG -EwJVUzEUMBIGA1UEChMLUkNBMTAxMTE4MjmCIGApUs14Ad7t9VTGq2PpV8DylPQ7 -aATM2mor7lc1fWvZMA4GA1UdDwEB/wQEAwIBBjAuBgNVHRABAf8EJDAigA8xOTk2 -MTAyMjAxMTAwMFqBDzE5OTYxMTIxMjM1OTU5WjAbBgNVHSABAf8EETAPMA0GC2CG -SAGG+EUBBwEBMBIGA1UdEwEB/wQIMAYBAf8CAQAwDwYEho1vAwEB/wQEAwIEEDB5 -BgSGjW8HAQH/BG4wbDAkAgEAMAkGBSsOAwIaBQAEFDJmNzRiMWFmNGZjYzA2MGY3 -Njc2Ew90ZXJzZSBzdGF0ZW1lbnSAF2h0dHA6Ly93d3cudmVyaXNpZ24uY29tgRpn -ZXRzZXQtY2VudGVyQHZlcmlzaWduLmNvbTANBgkqhkiG9w0BAQUFAAOBgQBteLaZ -u/TASC64UWPfhxYAUdys9DQ1pG/J1qPWNTkjOmpXFvW+7l/3nkxyRPgUoFNwx1e7 -XVVPr6zhy8LaaXppwfIZvVryzAUdbtijiUf/MO0hvV3w7e9NlCVProdU5H9EvCXr -+IV8rH8fdEkirIVyw0JGHkuWhkmtS1HEwai9vg== ------END CERTIFICATE----- diff --git a/apps/set/set_d_ct.pem b/apps/set/set_d_ct.pem deleted file mode 100644 index 9f8c7d8b086a..000000000000 --- a/apps/set/set_d_ct.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDdjCCAt+gAwIBAgIgRU5t24v72xVDpZ4iHpyoOAQaQmfio1yhTZAOkBfT2uUw -DQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0NDQTEwMjEx -NjE2MSAwHgYDVQQDExdCcmFuZCBOYW1lOlByb2R1Y3QgVHlwZTAeFw05NjEwMjQw -MDAwMDBaFw05NjExMjMyMzU5NTlaMG4xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdC -cmFuZElEMSYwJAYDVQQLEx1Jc3N1aW5nIEZpbmFuY2lhbCBJbnN0aXR1dGlvbjEl -MCMGA1UEAxMcR2lYb0t0VjViN1V0MHZKa2hkSG5RYmNzc2JrPTBcMA0GCSqGSIb3 -DQEBAQUAA0sAMEgCQQDIUxgpNB1aoSW585WErtN8WInCRWCqDj3RGT2mJye0F4SM -/iT5ywdWMasmw18vpEpDlMypfZnRkUAdfyHcRABVAgMBAAGjggFwMIIBbDB2BgNV -HSMEbzBtoUmkRzBFMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLQkNBMTAxNzExMDQx -IDAeBgNVBAMTF0JyYW5kIE5hbWU6UHJvZHVjdCBUeXBlgiA6eXwnqUBg0N1Na0ii -NYIaeWg1/i58eM5ngWTHCDnE6zAOBgNVHQ8BAf8EBAMCB4AwLgYDVR0QAQH/BCQw -IoAPMTk5NjEwMjQwMTA0MDBagQ8xOTk2MTEyMzIzNTk1OVowGAYDVR0gBBEwDzAN -BgtghkgBhvhFAQcBATAMBgNVHRMBAf8EAjAAMA8GBIaNbwMBAf8EBAMCB4AweQYE -ho1vBwEB/wRuMGwwJAIBADAJBgUrDgMCGgUABBQzOTgyMzk4NzIzNzg5MTM0OTc4 -MhMPdGVyc2Ugc3RhdGVtZW50gBdodHRwOi8vd3d3LnZlcmlzaWduLmNvbYEaZ2V0 -c2V0LWNlbnRlckB2ZXJpc2lnbi5jb20wDQYJKoZIhvcNAQEFBQADgYEAVHCjhxeD -mIFSkm3DpQAq7pGfcAFPWvSM9I9bK8qeFT1M5YQ+5fbPqaWlNcQlGKIe3cHd4+0P -ndL5lb6UBhhA0kTzEYA38+HtBxPe/lokCv0bYfyWY9asUmvfbUrTYta0yjN7ixnV -UqvxxHQHOAwhf6bcc7xNHapOxloWzGUU0RQ= ------END CERTIFICATE----- diff --git a/apps/set/set_root.pem b/apps/set/set_root.pem deleted file mode 100644 index 8dd104f058d3..000000000000 --- a/apps/set/set_root.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIgVqenwCYvmmxUIvi9gUMCa+uJGJ60mZecw9HrISXnLaYw -DQYJKoZIhvcNAQEFBQAwIzELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1JDQTEwMTEx -ODI5MB4XDTk2MTAxMjAwMDAwMFoXDTk2MTExMTIzNTk1OVowIzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC1JDQTEwMTExODI5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAukca0PVUGFIYX7EyrShi+dVi9GTNzG0V2Wtdw6DqFzKfedba/KpE -zqnRDV/wRZlBn3oXPS6kNCFiBPRV9mEFXI7y2W+q8/vPurjRDIXMsqQ+dAhKwf4q -rofJBTiET4NUN0YTtpx6aYuoVubjiOgKdbqnUArxAWWP2Dkco17ipEYyUtd4sTAe -/xKR02AHpbYGYPSHjMDS/nzUJ7uX4d51phs0rt7If48ExJSnDV/KoHMfm42mdmH2 -g23005qdHKY3UXeh10tZmb3QtGTSvF6OqpRZ+e9/ALklu7ZcIjqbb944ci4QWemb -ZNWiDFrWWUoO1k942BI/iZ8Fh8pETYSDBQIDAQABo4GGMIGDMA4GA1UdDwEB/wQE -AwIBBjAuBgNVHRABAf8EJDAigA8xOTk2MTAxMjAxMzQwMFqBDzE5OTYxMTExMjM1 -OTU5WjAbBgNVHSABAf8EETAPMA0GC2CGSAGG+EUBBwEBMBIGA1UdEwEB/wQIMAYB -Af8CAQIwEAYEho1vAwEB/wQFAwMHAIAwDQYJKoZIhvcNAQEFBQADggEBAK4tntea -y+ws7PdULwfqAS5osaoNvw73uBn5lROTpx91uhQbJyf0oZ3XG9GUuHZBpqG9qmr9 -vIL40RsvRpNMYgaNHKTxF716yx6rZmruAYZsrE3SpV63tQJCckKLPSge2E5uDhSQ -O8UjusG+IRT9fKMXUHLv4OmZPOQVOSl1qTCN2XoJFqEPtC3Y9P4YR4xHL0P2jb1l -DLdIbruuh+6omH+0XUZd5fKnQZTTi6gjl0iunj3wGnkcqGZtwr3j87ONiB/8tDwY -vz8ceII4YYdX12PrNzn+fu3R5rChvPW4/ah/SaYQ2VQ0AupaIF4xrNJ/gLYYw0YO -bxCrVJLd8tu9WgA= ------END CERTIFICATE----- diff --git a/apps/smime.c b/apps/smime.c index 17583304e4b4..6fd473775f45 100644 --- a/apps/smime.c +++ b/apps/smime.c @@ -1,60 +1,10 @@ -/* smime.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project. - */ -/* ==================================================================== - * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ /* S/MIME utility function */ @@ -62,14 +12,13 @@ #include <stdio.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/crypto.h> #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/x509_vfy.h> #include <openssl/x509v3.h> -#undef PROG -#define PROG smime_main static int save_certs(char *signerfile, STACK_OF(X509) *signers); static int smime_cb(int ok, X509_STORE_CTX *ctx); @@ -83,419 +32,360 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx); #define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) -int MAIN(int, char **); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY, + OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN, + OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, + OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF, + OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN, + OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD, + OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE, + OPT_R_ENUM, + OPT_V_ENUM, + OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, OPT_IN, OPT_INFORM, OPT_OUT, + OPT_OUTFORM, OPT_CONTENT +} OPTION_CHOICE; + +const OPTIONS smime_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, + {OPT_HELP_STR, 1, '-', + " cert.pem... recipient certs for encryption\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, + {"sign", OPT_SIGN, '-', "Sign message"}, + {"verify", OPT_VERIFY, '-', "Verify signed message"}, + {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, + {"nointern", OPT_NOINTERN, '-', + "Don't search certificates in message for signer"}, + {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, + {"nocerts", OPT_NOCERTS, '-', + "Don't include signers certificate when signing"}, + {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, + {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, + {"binary", OPT_BINARY, '-', "Don't translate message to text"}, + {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, + {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, + {"inkey", OPT_INKEY, 's', + "Input private key (if not signer or recipient)"}, + {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"}, + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'c', + "Output format SMIME (default), PEM or DER"}, + {"content", OPT_CONTENT, '<', + "Supply or override content for detached signature"}, + {"to", OPT_TO, 's', "To address"}, + {"from", OPT_FROM, 's', "From address"}, + {"subject", OPT_SUBJECT, 's', "Subject"}, + {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, + {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"}, + {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"resign", OPT_RESIGN, '-', "Resign a signed message"}, + {"nochain", OPT_NOCHAIN, '-', + "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" }, + {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + {"stream", OPT_STREAM, '-', "Enable CMS streaming" }, + {"indef", OPT_INDEF, '-', "Same as -stream" }, + {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, + {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only"}, + OPT_R_OPTIONS, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, + OPT_V_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int smime_main(int argc, char **argv) { - ENGINE *e = NULL; - int operation = 0; - int ret = 0; - char **args; - const char *inmode = "r", *outmode = "w"; - char *infile = NULL, *outfile = NULL; - char *signerfile = NULL, *recipfile = NULL; - STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; - char *certfile = NULL, *keyfile = NULL, *contfile = NULL; - const EVP_CIPHER *cipher = NULL; - PKCS7 *p7 = NULL; - X509_STORE *store = NULL; - X509 *cert = NULL, *recip = NULL, *signer = NULL; + BIO *in = NULL, *out = NULL, *indata = NULL; EVP_PKEY *key = NULL; + PKCS7 *p7 = NULL; + STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; STACK_OF(X509) *encerts = NULL, *other = NULL; - BIO *in = NULL, *out = NULL, *indata = NULL; - int badarg = 0; - int flags = PKCS7_DETACHED; - char *to = NULL, *from = NULL, *subject = NULL; - char *CAfile = NULL, *CApath = NULL; - char *passargin = NULL, *passin = NULL; - char *inrand = NULL; - int need_rand = 0; - int indef = 0; - const EVP_MD *sign_md = NULL; - int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; - int keyform = FORMAT_PEM; - char *engine = NULL; - + X509 *cert = NULL, *recip = NULL, *signer = NULL; + X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; + const EVP_CIPHER *cipher = NULL; + const EVP_MD *sign_md = NULL; + const char *CAfile = NULL, *CApath = NULL, *prog = NULL; + char *certfile = NULL, *keyfile = NULL, *contfile = NULL; + char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL; + char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL, *subject = NULL; + OPTION_CHOICE o; + int noCApath = 0, noCAfile = 0; + int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0; + int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform = + FORMAT_PEM; + int vpmtouched = 0, rv = 0; + ENGINE *e = NULL; + const char *mime_eol = "\n"; - args = argv + 1; - ret = 1; - - apps_startup(); - - if (bio_err == NULL) { - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - } - - if (!load_config(bio_err, NULL)) - goto end; + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + return 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-encrypt")) + prog = opt_init(argc, argv, smime_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(smime_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENCRYPT: operation = SMIME_ENCRYPT; - else if (!strcmp(*args, "-decrypt")) + break; + case OPT_DECRYPT: operation = SMIME_DECRYPT; - else if (!strcmp(*args, "-sign")) + break; + case OPT_SIGN: operation = SMIME_SIGN; - else if (!strcmp(*args, "-resign")) + break; + case OPT_RESIGN: operation = SMIME_RESIGN; - else if (!strcmp(*args, "-verify")) + break; + case OPT_VERIFY: operation = SMIME_VERIFY; - else if (!strcmp(*args, "-pk7out")) + break; + case OPT_PK7OUT: operation = SMIME_PK7OUT; -#ifndef OPENSSL_NO_DES - else if (!strcmp(*args, "-des3")) - cipher = EVP_des_ede3_cbc(); - else if (!strcmp(*args, "-des")) - cipher = EVP_des_cbc(); -#endif -#ifndef OPENSSL_NO_SEED - else if (!strcmp(*args, "-seed")) - cipher = EVP_seed_cbc(); -#endif -#ifndef OPENSSL_NO_RC2 - else if (!strcmp(*args, "-rc2-40")) - cipher = EVP_rc2_40_cbc(); - else if (!strcmp(*args, "-rc2-128")) - cipher = EVP_rc2_cbc(); - else if (!strcmp(*args, "-rc2-64")) - cipher = EVP_rc2_64_cbc(); -#endif -#ifndef OPENSSL_NO_AES - else if (!strcmp(*args, "-aes128")) - cipher = EVP_aes_128_cbc(); - else if (!strcmp(*args, "-aes192")) - cipher = EVP_aes_192_cbc(); - else if (!strcmp(*args, "-aes256")) - cipher = EVP_aes_256_cbc(); -#endif -#ifndef OPENSSL_NO_CAMELLIA - else if (!strcmp(*args, "-camellia128")) - cipher = EVP_camellia_128_cbc(); - else if (!strcmp(*args, "-camellia192")) - cipher = EVP_camellia_192_cbc(); - else if (!strcmp(*args, "-camellia256")) - cipher = EVP_camellia_256_cbc(); -#endif - else if (!strcmp(*args, "-text")) + break; + case OPT_TEXT: flags |= PKCS7_TEXT; - else if (!strcmp(*args, "-nointern")) + break; + case OPT_NOINTERN: flags |= PKCS7_NOINTERN; - else if (!strcmp(*args, "-noverify")) + break; + case OPT_NOVERIFY: flags |= PKCS7_NOVERIFY; - else if (!strcmp(*args, "-nochain")) + break; + case OPT_NOCHAIN: flags |= PKCS7_NOCHAIN; - else if (!strcmp(*args, "-nocerts")) + break; + case OPT_NOCERTS: flags |= PKCS7_NOCERTS; - else if (!strcmp(*args, "-noattr")) + break; + case OPT_NOATTR: flags |= PKCS7_NOATTR; - else if (!strcmp(*args, "-nodetach")) + break; + case OPT_NODETACH: flags &= ~PKCS7_DETACHED; - else if (!strcmp(*args, "-nosmimecap")) + break; + case OPT_NOSMIMECAP: flags |= PKCS7_NOSMIMECAP; - else if (!strcmp(*args, "-binary")) + break; + case OPT_BINARY: flags |= PKCS7_BINARY; - else if (!strcmp(*args, "-nosigs")) + break; + case OPT_NOSIGS: flags |= PKCS7_NOSIGS; - else if (!strcmp(*args, "-stream")) - indef = 1; - else if (!strcmp(*args, "-indef")) + break; + case OPT_STREAM: + case OPT_INDEF: indef = 1; - else if (!strcmp(*args, "-noindef")) + break; + case OPT_NOINDEF: indef = 0; - else if (!strcmp(*args, "-nooldmime")) - flags |= PKCS7_NOOLDMIMETYPE; - else if (!strcmp(*args, "-crlfeol")) + break; + case OPT_CRLFEOL: flags |= PKCS7_CRLFEOL; - else if (!strcmp(*args, "-rand")) { - if (!args[1]) - goto argerr; - args++; - inrand = *args; - need_rand = 1; - } -#ifndef OPENSSL_NO_ENGINE - else if (!strcmp(*args, "-engine")) { - if (!args[1]) - goto argerr; - engine = *++args; - } -#endif - else if (!strcmp(*args, "-passin")) { - if (!args[1]) - goto argerr; - passargin = *++args; - } else if (!strcmp(*args, "-to")) { - if (!args[1]) - goto argerr; - to = *++args; - } else if (!strcmp(*args, "-from")) { - if (!args[1]) - goto argerr; - from = *++args; - } else if (!strcmp(*args, "-subject")) { - if (!args[1]) - goto argerr; - subject = *++args; - } else if (!strcmp(*args, "-signer")) { - if (!args[1]) - goto argerr; + mime_eol = "\r\n"; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_TO: + to = opt_arg(); + break; + case OPT_FROM: + from = opt_arg(); + break; + case OPT_SUBJECT: + subject = opt_arg(); + break; + case OPT_SIGNER: /* If previous -signer argument add signer to list */ - - if (signerfile) { - if (!sksigners) - sksigners = sk_OPENSSL_STRING_new_null(); + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); - if (!keyfile) + if (keyfile == NULL) keyfile = signerfile; - if (!skkeys) - skkeys = sk_OPENSSL_STRING_new_null(); + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(skkeys, keyfile); keyfile = NULL; } - signerfile = *++args; - } else if (!strcmp(*args, "-recip")) { - if (!args[1]) - goto argerr; - recipfile = *++args; - } else if (!strcmp(*args, "-md")) { - if (!args[1]) - goto argerr; - sign_md = EVP_get_digestbyname(*++args); - if (sign_md == NULL) { - BIO_printf(bio_err, "Unknown digest %s\n", *args); - goto argerr; - } - } else if (!strcmp(*args, "-inkey")) { - if (!args[1]) - goto argerr; - /* If previous -inkey arument add signer to list */ - if (keyfile) { - if (!signerfile) { - BIO_puts(bio_err, "Illegal -inkey without -signer\n"); - goto argerr; + signerfile = opt_arg(); + break; + case OPT_RECIP: + recipfile = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_arg(), &sign_md)) + goto opthelp; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &cipher)) + goto opthelp; + break; + case OPT_INKEY: + /* If previous -inkey argument add signer to list */ + if (keyfile != NULL) { + if (signerfile == NULL) { + BIO_printf(bio_err, + "%s: Must have -signer before -inkey\n", prog); + goto opthelp; } - if (!sksigners) - sksigners = sk_OPENSSL_STRING_new_null(); + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); signerfile = NULL; - if (!skkeys) - skkeys = sk_OPENSSL_STRING_new_null(); + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(skkeys, keyfile); } - keyfile = *++args; - } else if (!strcmp(*args, "-keyform")) { - if (!args[1]) - goto argerr; - keyform = str2fmt(*++args); - } else if (!strcmp(*args, "-certfile")) { - if (!args[1]) - goto argerr; - certfile = *++args; - } else if (!strcmp(*args, "-CAfile")) { - if (!args[1]) - goto argerr; - CAfile = *++args; - } else if (!strcmp(*args, "-CApath")) { - if (!args[1]) - goto argerr; - CApath = *++args; - } else if (!strcmp(*args, "-in")) { - if (!args[1]) - goto argerr; - infile = *++args; - } else if (!strcmp(*args, "-inform")) { - if (!args[1]) - goto argerr; - informat = str2fmt(*++args); - } else if (!strcmp(*args, "-outform")) { - if (!args[1]) - goto argerr; - outformat = str2fmt(*++args); - } else if (!strcmp(*args, "-out")) { - if (!args[1]) - goto argerr; - outfile = *++args; - } else if (!strcmp(*args, "-content")) { - if (!args[1]) - goto argerr; - contfile = *++args; - } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) - continue; - else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL) - badarg = 1; - args++; + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_CERTFILE: + certfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_CONTENT: + contfile = opt_arg(); + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto opthelp; + vpmtouched++; + break; + } } + argc = opt_num_rest(); + argv = opt_rest(); - if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { + if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); - goto argerr; + goto opthelp; } if (operation & SMIME_SIGNERS) { /* Check to see if any final signer needs to be appended */ if (keyfile && !signerfile) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); - goto argerr; + goto opthelp; } - if (signerfile) { - if (!sksigners) - sksigners = sk_OPENSSL_STRING_new_null(); + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; sk_OPENSSL_STRING_push(sksigners, signerfile); - if (!skkeys) - skkeys = sk_OPENSSL_STRING_new_null(); + if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; if (!keyfile) keyfile = signerfile; sk_OPENSSL_STRING_push(skkeys, keyfile); } - if (!sksigners) { + if (sksigners == NULL) { BIO_printf(bio_err, "No signer certificate specified\n"); - badarg = 1; + goto opthelp; } signerfile = NULL; keyfile = NULL; - need_rand = 1; } else if (operation == SMIME_DECRYPT) { - if (!recipfile && !keyfile) { + if (recipfile == NULL && keyfile == NULL) { BIO_printf(bio_err, "No recipient certificate or key specified\n"); - badarg = 1; + goto opthelp; } } else if (operation == SMIME_ENCRYPT) { - if (!*args) { + if (argc == 0) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); - badarg = 1; + goto opthelp; } - need_rand = 1; - } else if (!operation) - badarg = 1; - - if (badarg) { - argerr: - BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-encrypt encrypt message\n"); - BIO_printf(bio_err, "-decrypt decrypt encrypted message\n"); - BIO_printf(bio_err, "-sign sign message\n"); - BIO_printf(bio_err, "-verify verify signed message\n"); - BIO_printf(bio_err, "-pk7out output PKCS#7 structure\n"); -#ifndef OPENSSL_NO_DES - BIO_printf(bio_err, "-des3 encrypt with triple DES\n"); - BIO_printf(bio_err, "-des encrypt with DES\n"); -#endif -#ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, "-seed encrypt with SEED\n"); -#endif -#ifndef OPENSSL_NO_RC2 - BIO_printf(bio_err, "-rc2-40 encrypt with RC2-40 (default)\n"); - BIO_printf(bio_err, "-rc2-64 encrypt with RC2-64\n"); - BIO_printf(bio_err, "-rc2-128 encrypt with RC2-128\n"); -#endif -#ifndef OPENSSL_NO_AES - BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc aes\n"); -#endif -#ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); - BIO_printf(bio_err, - " encrypt PEM output with cbc camellia\n"); -#endif - BIO_printf(bio_err, - "-nointern don't search certificates in message for signer\n"); - BIO_printf(bio_err, - "-nosigs don't verify message signature\n"); - BIO_printf(bio_err, - "-noverify don't verify signers certificate\n"); - BIO_printf(bio_err, - "-nocerts don't include signers certificate when signing\n"); - BIO_printf(bio_err, "-nodetach use opaque signing\n"); - BIO_printf(bio_err, - "-noattr don't include any signed attributes\n"); - BIO_printf(bio_err, - "-binary don't translate message to text\n"); - BIO_printf(bio_err, "-certfile file other certificates file\n"); - BIO_printf(bio_err, "-signer file signer certificate file\n"); - BIO_printf(bio_err, - "-recip file recipient certificate file for decryption\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, - "-inform arg input format SMIME (default), PEM or DER\n"); - BIO_printf(bio_err, - "-inkey file input private key (if not signer or recipient)\n"); - BIO_printf(bio_err, - "-keyform arg input private key format (PEM or ENGINE)\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, - "-outform arg output format SMIME (default), PEM or DER\n"); - BIO_printf(bio_err, - "-content file supply or override content for detached signature\n"); - BIO_printf(bio_err, "-to addr to address\n"); - BIO_printf(bio_err, "-from ad from address\n"); - BIO_printf(bio_err, "-subject s subject\n"); - BIO_printf(bio_err, - "-text include or delete text MIME headers\n"); - BIO_printf(bio_err, - "-CApath dir trusted certificates directory\n"); - BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); - BIO_printf(bio_err, - "-no_alt_chains only ever use the first certificate chain found\n"); - BIO_printf(bio_err, - "-crl_check check revocation status of signer's certificate using CRLs\n"); - BIO_printf(bio_err, - "-crl_check_all check revocation status of signer's certificate chain using CRLs\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e use engine e, possibly a hardware device.\n"); -#endif - BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); - BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - BIO_printf(bio_err, - "cert.pem recipient certificate(s) for encryption\n"); - goto end; + } else if (!operation) { + goto opthelp; } - e = setup_engine(bio_err, engine, 0); - if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } - if (need_rand) { - app_RAND_load_file(NULL, bio_err, (inrand != NULL)); - if (inrand != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(inrand)); - } - ret = 2; if (!(operation & SMIME_SIGNERS)) flags &= ~PKCS7_DETACHED; - if (operation & SMIME_OP) { - if (outformat == FORMAT_ASN1) - outmode = "wb"; - } else { + if (!(operation & SMIME_OP)) { if (flags & PKCS7_BINARY) - outmode = "wb"; + outformat = FORMAT_BINARY; } - if (operation & SMIME_IP) { - if (informat == FORMAT_ASN1) - inmode = "rb"; - } else { + if (!(operation & SMIME_IP)) { if (flags & PKCS7_BINARY) - inmode = "rb"; + informat = FORMAT_BINARY; } if (operation == SMIME_ENCRYPT) { - if (!cipher) { + if (cipher == NULL) { #ifndef OPENSSL_NO_DES cipher = EVP_des_ede3_cbc(); #else @@ -504,107 +394,89 @@ int MAIN(int argc, char **argv) #endif } encerts = sk_X509_new_null(); - while (*args) { - if (!(cert = load_cert(bio_err, *args, FORMAT_PEM, - NULL, e, "recipient certificate file"))) { -#if 0 /* An appropriate message is already printed */ - BIO_printf(bio_err, - "Can't read recipient certificate file %s\n", - *args); -#endif + if (encerts == NULL) + goto end; + while (*argv != NULL) { + cert = load_cert(*argv, FORMAT_PEM, + "recipient certificate file"); + if (cert == NULL) goto end; - } sk_X509_push(encerts, cert); cert = NULL; - args++; + argv++; } } - if (certfile) { - if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL, - e, "certificate file"))) { + if (certfile != NULL) { + if (!load_certs(certfile, &other, FORMAT_PEM, NULL, + "certificate file")) { ERR_print_errors(bio_err); goto end; } } - if (recipfile && (operation == SMIME_DECRYPT)) { - if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL, - e, "recipient certificate file"))) { + if (recipfile != NULL && (operation == SMIME_DECRYPT)) { + if ((recip = load_cert(recipfile, FORMAT_PEM, + "recipient certificate file")) == NULL) { ERR_print_errors(bio_err); goto end; } } if (operation == SMIME_DECRYPT) { - if (!keyfile) + if (keyfile == NULL) keyfile = recipfile; } else if (operation == SMIME_SIGN) { - if (!keyfile) + if (keyfile == NULL) keyfile = signerfile; - } else + } else { keyfile = NULL; + } - if (keyfile) { - key = load_key(bio_err, keyfile, keyform, 0, passin, e, - "signing key file"); - if (!key) + if (keyfile != NULL) { + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) goto end; } - if (infile) { - if (!(in = BIO_new_file(infile, inmode))) { - BIO_printf(bio_err, "Can't open input file %s\n", infile); - goto end; - } - } else - in = BIO_new_fp(stdin, BIO_NOCLOSE); + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; if (operation & SMIME_IP) { - if (informat == FORMAT_SMIME) + if (informat == FORMAT_SMIME) { p7 = SMIME_read_PKCS7(in, &indata); - else if (informat == FORMAT_PEM) + } else if (informat == FORMAT_PEM) { p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); - else if (informat == FORMAT_ASN1) + } else if (informat == FORMAT_ASN1) { p7 = d2i_PKCS7_bio(in, NULL); - else { + } else { BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); goto end; } - if (!p7) { + if (p7 == NULL) { BIO_printf(bio_err, "Error reading S/MIME message\n"); goto end; } - if (contfile) { + if (contfile != NULL) { BIO_free(indata); - if (!(indata = BIO_new_file(contfile, "rb"))) { + if ((indata = BIO_new_file(contfile, "rb")) == NULL) { BIO_printf(bio_err, "Can't read content file %s\n", contfile); goto end; } } } - if (outfile) { - if (!(out = BIO_new_file(outfile, outmode))) { - BIO_printf(bio_err, "Can't open output file %s\n", outfile); - goto end; - } - } else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; if (operation == SMIME_VERIFY) { - if (!(store = setup_verify(bio_err, CAfile, CApath))) + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) goto end; X509_STORE_set_verify_cb(store, smime_cb); - if (vpm) + if (vpmtouched) X509_STORE_set1_param(store, vpm); } @@ -624,11 +496,12 @@ int MAIN(int argc, char **argv) if (flags & PKCS7_DETACHED) { if (outformat == FORMAT_SMIME) flags |= PKCS7_STREAM; - } else if (indef) + } else if (indef) { flags |= PKCS7_STREAM; + } flags |= PKCS7_PARTIAL; p7 = PKCS7_sign(NULL, NULL, other, in, flags); - if (!p7) + if (p7 == NULL) goto end; if (flags & PKCS7_NOCERTS) { for (i = 0; i < sk_X509_num(other); i++) { @@ -636,18 +509,18 @@ int MAIN(int argc, char **argv) PKCS7_add_certificate(p7, x); } } - } else + } else { flags |= PKCS7_REUSE_DIGEST; + } for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); - signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL, - e, "signer certificate"); - if (!signer) + signer = load_cert(signerfile, FORMAT_PEM, + "signer certificate"); + if (signer == NULL) goto end; - key = load_key(bio_err, keyfile, keyform, 0, passin, e, - "signing key file"); - if (!key) + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) goto end; if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) goto end; @@ -663,7 +536,7 @@ int MAIN(int argc, char **argv) } } - if (!p7) { + if (p7 == NULL) { BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); goto end; } @@ -689,43 +562,43 @@ int MAIN(int argc, char **argv) goto end; } sk_X509_free(signers); - } else if (operation == SMIME_PK7OUT) + } else if (operation == SMIME_PK7OUT) { PEM_write_bio_PKCS7(out, p7); - else { + } else { if (to) - BIO_printf(out, "To: %s\n", to); + BIO_printf(out, "To: %s%s", to, mime_eol); if (from) - BIO_printf(out, "From: %s\n", from); + BIO_printf(out, "From: %s%s", from, mime_eol); if (subject) - BIO_printf(out, "Subject: %s\n", subject); + BIO_printf(out, "Subject: %s%s", subject, mime_eol); if (outformat == FORMAT_SMIME) { if (operation == SMIME_RESIGN) - SMIME_write_PKCS7(out, p7, indata, flags); + rv = SMIME_write_PKCS7(out, p7, indata, flags); else - SMIME_write_PKCS7(out, p7, in, flags); - } else if (outformat == FORMAT_PEM) - PEM_write_bio_PKCS7_stream(out, p7, in, flags); - else if (outformat == FORMAT_ASN1) - i2d_PKCS7_bio_stream(out, p7, in, flags); - else { + rv = SMIME_write_PKCS7(out, p7, in, flags); + } else if (outformat == FORMAT_PEM) { + rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags); + } else if (outformat == FORMAT_ASN1) { + rv = i2d_PKCS7_bio_stream(out, p7, in, flags); + } else { BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); goto end; } + if (rv == 0) { + BIO_printf(bio_err, "Error writing output\n"); + ret = 3; + goto end; + } } ret = 0; end: - if (need_rand) - app_RAND_write_file(NULL, bio_err); if (ret) ERR_print_errors(bio_err); sk_X509_pop_free(encerts, X509_free); sk_X509_pop_free(other, X509_free); - if (vpm) - X509_VERIFY_PARAM_free(vpm); - if (sksigners) - sk_OPENSSL_STRING_free(sksigners); - if (skkeys) - sk_OPENSSL_STRING_free(skkeys); + X509_VERIFY_PARAM_free(vpm); + sk_OPENSSL_STRING_free(sksigners); + sk_OPENSSL_STRING_free(skkeys); X509_STORE_free(store); X509_free(cert); X509_free(recip); @@ -736,19 +609,19 @@ int MAIN(int argc, char **argv) BIO_free(in); BIO_free(indata); BIO_free_all(out); - if (passin) - OPENSSL_free(passin); - return (ret); + OPENSSL_free(passin); + return ret; } static int save_certs(char *signerfile, STACK_OF(X509) *signers) { int i; BIO *tmp; - if (!signerfile) + + if (signerfile == NULL) return 1; tmp = BIO_new_file(signerfile, "w"); - if (!tmp) + if (tmp == NULL) return 0; for (i = 0; i < sk_X509_num(signers); i++) PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); @@ -768,8 +641,7 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx) && ((error != X509_V_OK) || (ok != 2))) return ok; - policies_print(NULL, ctx); + policies_print(ctx); return ok; - } diff --git a/apps/speed.c b/apps/speed.c index aaa982ee1f74..a4879179e414 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -1,320 +1,242 @@ -/* apps/speed.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * - * Portions of the attached software ("Contribution") are developed by - * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. - * - * The Contribution is licensed pursuant to the OpenSSL open source - * license provided above. - * - * The ECDH and ECDSA speed test software is originally written by - * Sumit Gupta of Sun Microsystems Laboratories. - * - */ - -/* most of this code has been pilfered from my libdes speed.c program */ - -#ifndef OPENSSL_NO_SPEED - -# undef SECONDS -# define SECONDS 3 -# define RSA_SECONDS 10 -# define DSA_SECONDS 10 -# define ECDSA_SECONDS 10 -# define ECDH_SECONDS 10 -/* 11-Sep-92 Andrew Daviel Support for Silicon Graphics IRIX added */ -/* 06-Apr-92 Luke Brennan Support for VMS and add extra signal calls */ +#undef SECONDS +#define SECONDS 3 +#define RSA_SECONDS 10 +#define DSA_SECONDS 10 +#define ECDSA_SECONDS 10 +#define ECDH_SECONDS 10 +#define EdDSA_SECONDS 10 -# undef PROG -# define PROG speed_main +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "apps.h" +#include "progs.h" +#include <openssl/crypto.h> +#include <openssl/rand.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/async.h> +#if !defined(OPENSSL_SYS_MSDOS) +# include OPENSSL_UNISTD +#endif -# include <stdio.h> -# include <stdlib.h> +#if defined(_WIN32) +# include <windows.h> +#endif -# include <string.h> -# include <math.h> -# include "apps.h" -# ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -# endif -# include <openssl/crypto.h> -# include <openssl/rand.h> -# include <openssl/err.h> -# include <openssl/evp.h> -# include <openssl/objects.h> -# if !defined(OPENSSL_SYS_MSDOS) -# include OPENSSL_UNISTD -# endif +#include <openssl/bn.h> +#ifndef OPENSSL_NO_DES +# include <openssl/des.h> +#endif +#include <openssl/aes.h> +#ifndef OPENSSL_NO_CAMELLIA +# include <openssl/camellia.h> +#endif +#ifndef OPENSSL_NO_MD2 +# include <openssl/md2.h> +#endif +#ifndef OPENSSL_NO_MDC2 +# include <openssl/mdc2.h> +#endif +#ifndef OPENSSL_NO_MD4 +# include <openssl/md4.h> +#endif +#ifndef OPENSSL_NO_MD5 +# include <openssl/md5.h> +#endif +#include <openssl/hmac.h> +#include <openssl/sha.h> +#ifndef OPENSSL_NO_RMD160 +# include <openssl/ripemd.h> +#endif +#ifndef OPENSSL_NO_WHIRLPOOL +# include <openssl/whrlpool.h> +#endif +#ifndef OPENSSL_NO_RC4 +# include <openssl/rc4.h> +#endif +#ifndef OPENSSL_NO_RC5 +# include <openssl/rc5.h> +#endif +#ifndef OPENSSL_NO_RC2 +# include <openssl/rc2.h> +#endif +#ifndef OPENSSL_NO_IDEA +# include <openssl/idea.h> +#endif +#ifndef OPENSSL_NO_SEED +# include <openssl/seed.h> +#endif +#ifndef OPENSSL_NO_BF +# include <openssl/blowfish.h> +#endif +#ifndef OPENSSL_NO_CAST +# include <openssl/cast.h> +#endif +#ifndef OPENSSL_NO_RSA +# include <openssl/rsa.h> +# include "./testrsa.h" +#endif +#include <openssl/x509.h> +#ifndef OPENSSL_NO_DSA +# include <openssl/dsa.h> +# include "./testdsa.h" +#endif +#ifndef OPENSSL_NO_EC +# include <openssl/ec.h> +#endif +#include <openssl/modes.h> -# ifndef OPENSSL_SYS_NETWARE -# include <signal.h> +#ifndef HAVE_FORK +# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) +# define HAVE_FORK 0 +# else +# define HAVE_FORK 1 # endif +#endif -# if defined(_WIN32) || defined(__CYGWIN__) -# include <windows.h> -# if defined(__CYGWIN__) && !defined(_WIN32) - /* - * <windows.h> should define _WIN32, which normally is mutually exclusive - * with __CYGWIN__, but if it didn't... - */ -# define _WIN32 - /* this is done because Cygwin alarm() fails sometimes. */ -# endif -# endif +#if HAVE_FORK +# undef NO_FORK +#else +# define NO_FORK +#endif -# include <openssl/bn.h> -# ifndef OPENSSL_NO_DES -# include <openssl/des.h> -# endif -# ifndef OPENSSL_NO_AES -# include <openssl/aes.h> -# endif -# ifndef OPENSSL_NO_CAMELLIA -# include <openssl/camellia.h> -# endif -# ifndef OPENSSL_NO_MD2 -# include <openssl/md2.h> -# endif -# ifndef OPENSSL_NO_MDC2 -# include <openssl/mdc2.h> -# endif -# ifndef OPENSSL_NO_MD4 -# include <openssl/md4.h> -# endif -# ifndef OPENSSL_NO_MD5 -# include <openssl/md5.h> -# endif -# ifndef OPENSSL_NO_HMAC -# include <openssl/hmac.h> -# endif -# include <openssl/evp.h> -# ifndef OPENSSL_NO_SHA -# include <openssl/sha.h> -# endif -# ifndef OPENSSL_NO_RIPEMD -# include <openssl/ripemd.h> -# endif -# ifndef OPENSSL_NO_WHIRLPOOL -# include <openssl/whrlpool.h> -# endif -# ifndef OPENSSL_NO_RC4 -# include <openssl/rc4.h> -# endif -# ifndef OPENSSL_NO_RC5 -# include <openssl/rc5.h> -# endif -# ifndef OPENSSL_NO_RC2 -# include <openssl/rc2.h> -# endif -# ifndef OPENSSL_NO_IDEA -# include <openssl/idea.h> -# endif -# ifndef OPENSSL_NO_SEED -# include <openssl/seed.h> -# endif -# ifndef OPENSSL_NO_BF -# include <openssl/blowfish.h> -# endif -# ifndef OPENSSL_NO_CAST -# include <openssl/cast.h> -# endif -# ifndef OPENSSL_NO_RSA -# include <openssl/rsa.h> -# include "./testrsa.h" -# endif -# include <openssl/x509.h> -# ifndef OPENSSL_NO_DSA -# include <openssl/dsa.h> -# include "./testdsa.h" -# endif -# ifndef OPENSSL_NO_ECDSA -# include <openssl/ecdsa.h> -# endif -# ifndef OPENSSL_NO_ECDH -# include <openssl/ecdh.h> -# endif -# include <openssl/modes.h> +#define MAX_MISALIGNMENT 63 +#define MAX_ECDH_SIZE 256 +#define MISALIGN 64 -# ifdef OPENSSL_FIPS -# ifdef OPENSSL_DOING_MAKEDEPEND -# undef AES_set_encrypt_key -# undef AES_set_decrypt_key -# undef DES_set_key_unchecked -# endif -# define BF_set_key private_BF_set_key -# define CAST_set_key private_CAST_set_key -# define idea_set_encrypt_key private_idea_set_encrypt_key -# define SEED_set_key private_SEED_set_key -# define RC2_set_key private_RC2_set_key -# define RC4_set_key private_RC4_set_key -# define DES_set_key_unchecked private_DES_set_key_unchecked -# define AES_set_encrypt_key private_AES_set_encrypt_key -# define AES_set_decrypt_key private_AES_set_decrypt_key -# define Camellia_set_key private_Camellia_set_key -# endif +typedef struct openssl_speed_sec_st { + int sym; + int rsa; + int dsa; + int ecdsa; + int ecdh; + int eddsa; +} openssl_speed_sec_t; -# ifndef HAVE_FORK -# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_NETWARE) -# define HAVE_FORK 0 -# else -# define HAVE_FORK 1 -# endif -# endif - -# if HAVE_FORK -# undef NO_FORK -# else -# define NO_FORK -# endif - -# undef BUFSIZE -# define BUFSIZE ((long)1024*8+1) static volatile int run = 0; static int mr = 0; static int usertime = 1; +#ifndef OPENSSL_NO_MD2 +static int EVP_Digest_MD2_loop(void *args); +#endif + +#ifndef OPENSSL_NO_MDC2 +static int EVP_Digest_MDC2_loop(void *args); +#endif +#ifndef OPENSSL_NO_MD4 +static int EVP_Digest_MD4_loop(void *args); +#endif +#ifndef OPENSSL_NO_MD5 +static int MD5_loop(void *args); +static int HMAC_loop(void *args); +#endif +static int SHA1_loop(void *args); +static int SHA256_loop(void *args); +static int SHA512_loop(void *args); +#ifndef OPENSSL_NO_WHIRLPOOL +static int WHIRLPOOL_loop(void *args); +#endif +#ifndef OPENSSL_NO_RMD160 +static int EVP_Digest_RMD160_loop(void *args); +#endif +#ifndef OPENSSL_NO_RC4 +static int RC4_loop(void *args); +#endif +#ifndef OPENSSL_NO_DES +static int DES_ncbc_encrypt_loop(void *args); +static int DES_ede3_cbc_encrypt_loop(void *args); +#endif +static int AES_cbc_128_encrypt_loop(void *args); +static int AES_cbc_192_encrypt_loop(void *args); +static int AES_ige_128_encrypt_loop(void *args); +static int AES_cbc_256_encrypt_loop(void *args); +static int AES_ige_192_encrypt_loop(void *args); +static int AES_ige_256_encrypt_loop(void *args); +static int CRYPTO_gcm128_aad_loop(void *args); +static int RAND_bytes_loop(void *args); +static int EVP_Update_loop(void *args); +static int EVP_Update_loop_ccm(void *args); +static int EVP_Update_loop_aead(void *args); +static int EVP_Digest_loop(void *args); +#ifndef OPENSSL_NO_RSA +static int RSA_sign_loop(void *args); +static int RSA_verify_loop(void *args); +#endif +#ifndef OPENSSL_NO_DSA +static int DSA_sign_loop(void *args); +static int DSA_verify_loop(void *args); +#endif +#ifndef OPENSSL_NO_EC +static int ECDSA_sign_loop(void *args); +static int ECDSA_verify_loop(void *args); +static int EdDSA_sign_loop(void *args); +static int EdDSA_verify_loop(void *args); +#endif + static double Time_F(int s); -static void print_message(const char *s, long num, int length); +static void print_message(const char *s, long num, int length, int tm); static void pkey_print_message(const char *str, const char *str2, - long num, int bits, int sec); + long num, unsigned int bits, int sec); static void print_result(int alg, int run_no, int count, double time_used); -# ifndef NO_FORK -static int do_multi(int multi); -# endif - -# define ALGOR_NUM 30 -# define SIZE_NUM 5 -# define RSA_NUM 4 -# define DSA_NUM 3 - -# define EC_NUM 16 -# define MAX_ECDH_SIZE 256 +#ifndef NO_FORK +static int do_multi(int multi, int size_num); +#endif -static const char *names[ALGOR_NUM] = { - "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4", - "des cbc", "des ede3", "idea cbc", "seed cbc", - "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc", - "aes-128 cbc", "aes-192 cbc", "aes-256 cbc", - "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc", - "evp", "sha256", "sha512", "whirlpool", - "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash" +static const int lengths_list[] = { + 16, 64, 256, 1024, 8 * 1024, 16 * 1024 }; +static const int *lengths = lengths_list; -static double results[ALGOR_NUM][SIZE_NUM]; -static int lengths[SIZE_NUM] = { 16, 64, 256, 1024, 8 * 1024 }; +static const int aead_lengths_list[] = { + 2, 31, 136, 1024, 8 * 1024, 16 * 1024 +}; -# ifndef OPENSSL_NO_RSA -static double rsa_results[RSA_NUM][2]; -# endif -# ifndef OPENSSL_NO_DSA -static double dsa_results[DSA_NUM][2]; -# endif -# ifndef OPENSSL_NO_ECDSA -static double ecdsa_results[EC_NUM][2]; -# endif -# ifndef OPENSSL_NO_ECDH -static double ecdh_results[EC_NUM][1]; -# endif +#define START 0 +#define STOP 1 -# if defined(OPENSSL_NO_DSA) && !(defined(OPENSSL_NO_ECDSA) && defined(OPENSSL_NO_ECDH)) -static const char rnd_seed[] = - "string to make the random number generator think it has entropy"; -static int rnd_fake = 0; -# endif +#ifdef SIGALRM -# ifdef SIGALRM -# if defined(__STDC__) || defined(sgi) || defined(_AIX) -# define SIGRETTYPE void -# else -# define SIGRETTYPE int -# endif - -static SIGRETTYPE sig_done(int sig); -static SIGRETTYPE sig_done(int sig) +static void alarmed(int sig) { - signal(SIGALRM, sig_done); + signal(SIGALRM, alarmed); run = 0; -# ifdef LINT - sig = sig; -# endif } -# endif -# define START 0 -# define STOP 1 +static double Time_F(int s) +{ + double ret = app_tminterval(s, usertime); + if (s == STOP) + alarm(0); + return ret; +} -# if defined(_WIN32) +#elif defined(_WIN32) -# if !defined(SIGALRM) -# define SIGALRM -# endif -static volatile unsigned int lapse; +# define SIGALRM -1 + +static unsigned int lapse; static volatile unsigned int schlock; static void alarm_win32(unsigned int secs) { lapse = secs * 1000; } -# define alarm alarm_win32 +# define alarm alarm_win32 static DWORD WINAPI sleepy(VOID * arg) { @@ -326,119 +248,1185 @@ static DWORD WINAPI sleepy(VOID * arg) static double Time_F(int s) { + double ret; + static HANDLE thr; + if (s == START) { - HANDLE thr; schlock = 0; thr = CreateThread(NULL, 4096, sleepy, NULL, 0, NULL); if (thr == NULL) { - DWORD ret = GetLastError(); - BIO_printf(bio_err, "unable to CreateThread (%d)", ret); - ExitProcess(ret); + DWORD err = GetLastError(); + BIO_printf(bio_err, "unable to CreateThread (%lu)", err); + ExitProcess(err); } - CloseHandle(thr); /* detach the thread */ while (!schlock) Sleep(0); /* scheduler spinlock */ + ret = app_tminterval(s, usertime); + } else { + ret = app_tminterval(s, usertime); + if (run) + TerminateThread(thr, 0); + CloseHandle(thr); } - return app_tminterval(s, usertime); + return ret; } -# else - +#else static double Time_F(int s) { return app_tminterval(s, usertime); } -# endif +#endif + +static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, + const openssl_speed_sec_t *seconds); -# ifndef OPENSSL_NO_ECDH -static const int KDF1_SHA1_len = 20; -static void *KDF1_SHA1(const void *in, size_t inlen, void *out, - size_t *outlen) +#define found(value, pairs, result)\ + opt_found(value, result, pairs, OSSL_NELEM(pairs)) +static int opt_found(const char *name, unsigned int *result, + const OPT_PAIR pairs[], unsigned int nbelem) { -# ifndef OPENSSL_NO_SHA - if (*outlen < SHA_DIGEST_LENGTH) - return NULL; - else - *outlen = SHA_DIGEST_LENGTH; - return SHA1(in, inlen, out); -# else - return NULL; -# endif /* OPENSSL_NO_SHA */ + unsigned int idx; + + for (idx = 0; idx < nbelem; ++idx, pairs++) + if (strcmp(name, pairs->name) == 0) { + *result = pairs->retval; + return 1; + } + return 0; } -# endif /* OPENSSL_NO_ECDH */ -static void multiblock_speed(const EVP_CIPHER *evp_cipher); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, + OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, + OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD +} OPTION_CHOICE; + +const OPTIONS speed_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"}, + {"decrypt", OPT_DECRYPT, '-', + "Time decryption instead of encryption (only EVP)"}, + {"aead", OPT_AEAD, '-', + "Benchmark EVP-named AEAD cipher in TLS-like sequence"}, + {"mb", OPT_MB, '-', + "Enable (tls1>=1) multi-block mode on EVP-named cipher"}, + {"mr", OPT_MR, '-', "Produce machine readable output"}, +#ifndef NO_FORK + {"multi", OPT_MULTI, 'p', "Run benchmarks in parallel"}, +#endif +#ifndef OPENSSL_NO_ASYNC + {"async_jobs", OPT_ASYNCJOBS, 'p', + "Enable async mode and start specified number of jobs"}, +#endif + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"elapsed", OPT_ELAPSED, '-', + "Use wall-clock time instead of CPU user time as divisor"}, + {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"}, + {"seconds", OPT_SECONDS, 'p', + "Run benchmarks for specified amount of seconds"}, + {"bytes", OPT_BYTES, 'p', + "Run [non-PKI] benchmarks on custom-sized buffer"}, + {"misalign", OPT_MISALIGN, 'p', + "Use specified offset to mis-align buffers"}, + {NULL} +}; + +#define D_MD2 0 +#define D_MDC2 1 +#define D_MD4 2 +#define D_MD5 3 +#define D_HMAC 4 +#define D_SHA1 5 +#define D_RMD160 6 +#define D_RC4 7 +#define D_CBC_DES 8 +#define D_EDE3_DES 9 +#define D_CBC_IDEA 10 +#define D_CBC_SEED 11 +#define D_CBC_RC2 12 +#define D_CBC_RC5 13 +#define D_CBC_BF 14 +#define D_CBC_CAST 15 +#define D_CBC_128_AES 16 +#define D_CBC_192_AES 17 +#define D_CBC_256_AES 18 +#define D_CBC_128_CML 19 +#define D_CBC_192_CML 20 +#define D_CBC_256_CML 21 +#define D_EVP 22 +#define D_SHA256 23 +#define D_SHA512 24 +#define D_WHIRLPOOL 25 +#define D_IGE_128_AES 26 +#define D_IGE_192_AES 27 +#define D_IGE_256_AES 28 +#define D_GHASH 29 +#define D_RAND 30 +/* name of algorithms to test */ +static const char *names[] = { + "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4", + "des cbc", "des ede3", "idea cbc", "seed cbc", + "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc", + "aes-128 cbc", "aes-192 cbc", "aes-256 cbc", + "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc", + "evp", "sha256", "sha512", "whirlpool", + "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash", + "rand" +}; +#define ALGOR_NUM OSSL_NELEM(names) + +/* list of configured algorithm (remaining) */ +static const OPT_PAIR doit_choices[] = { +#ifndef OPENSSL_NO_MD2 + {"md2", D_MD2}, +#endif +#ifndef OPENSSL_NO_MDC2 + {"mdc2", D_MDC2}, +#endif +#ifndef OPENSSL_NO_MD4 + {"md4", D_MD4}, +#endif +#ifndef OPENSSL_NO_MD5 + {"md5", D_MD5}, + {"hmac", D_HMAC}, +#endif + {"sha1", D_SHA1}, + {"sha256", D_SHA256}, + {"sha512", D_SHA512}, +#ifndef OPENSSL_NO_WHIRLPOOL + {"whirlpool", D_WHIRLPOOL}, +#endif +#ifndef OPENSSL_NO_RMD160 + {"ripemd", D_RMD160}, + {"rmd160", D_RMD160}, + {"ripemd160", D_RMD160}, +#endif +#ifndef OPENSSL_NO_RC4 + {"rc4", D_RC4}, +#endif +#ifndef OPENSSL_NO_DES + {"des-cbc", D_CBC_DES}, + {"des-ede3", D_EDE3_DES}, +#endif + {"aes-128-cbc", D_CBC_128_AES}, + {"aes-192-cbc", D_CBC_192_AES}, + {"aes-256-cbc", D_CBC_256_AES}, + {"aes-128-ige", D_IGE_128_AES}, + {"aes-192-ige", D_IGE_192_AES}, + {"aes-256-ige", D_IGE_256_AES}, +#ifndef OPENSSL_NO_RC2 + {"rc2-cbc", D_CBC_RC2}, + {"rc2", D_CBC_RC2}, +#endif +#ifndef OPENSSL_NO_RC5 + {"rc5-cbc", D_CBC_RC5}, + {"rc5", D_CBC_RC5}, +#endif +#ifndef OPENSSL_NO_IDEA + {"idea-cbc", D_CBC_IDEA}, + {"idea", D_CBC_IDEA}, +#endif +#ifndef OPENSSL_NO_SEED + {"seed-cbc", D_CBC_SEED}, + {"seed", D_CBC_SEED}, +#endif +#ifndef OPENSSL_NO_BF + {"bf-cbc", D_CBC_BF}, + {"blowfish", D_CBC_BF}, + {"bf", D_CBC_BF}, +#endif +#ifndef OPENSSL_NO_CAST + {"cast-cbc", D_CBC_CAST}, + {"cast", D_CBC_CAST}, + {"cast5", D_CBC_CAST}, +#endif + {"ghash", D_GHASH}, + {"rand", D_RAND} +}; + +static double results[ALGOR_NUM][OSSL_NELEM(lengths_list)]; + +#ifndef OPENSSL_NO_DSA +# define R_DSA_512 0 +# define R_DSA_1024 1 +# define R_DSA_2048 2 +static const OPT_PAIR dsa_choices[] = { + {"dsa512", R_DSA_512}, + {"dsa1024", R_DSA_1024}, + {"dsa2048", R_DSA_2048} +}; +# define DSA_NUM OSSL_NELEM(dsa_choices) + +static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_DSA */ + +#define R_RSA_512 0 +#define R_RSA_1024 1 +#define R_RSA_2048 2 +#define R_RSA_3072 3 +#define R_RSA_4096 4 +#define R_RSA_7680 5 +#define R_RSA_15360 6 +#ifndef OPENSSL_NO_RSA +static const OPT_PAIR rsa_choices[] = { + {"rsa512", R_RSA_512}, + {"rsa1024", R_RSA_1024}, + {"rsa2048", R_RSA_2048}, + {"rsa3072", R_RSA_3072}, + {"rsa4096", R_RSA_4096}, + {"rsa7680", R_RSA_7680}, + {"rsa15360", R_RSA_15360} +}; +# define RSA_NUM OSSL_NELEM(rsa_choices) + +static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_RSA */ + +#define R_EC_P160 0 +#define R_EC_P192 1 +#define R_EC_P224 2 +#define R_EC_P256 3 +#define R_EC_P384 4 +#define R_EC_P521 5 +#define R_EC_K163 6 +#define R_EC_K233 7 +#define R_EC_K283 8 +#define R_EC_K409 9 +#define R_EC_K571 10 +#define R_EC_B163 11 +#define R_EC_B233 12 +#define R_EC_B283 13 +#define R_EC_B409 14 +#define R_EC_B571 15 +#define R_EC_BRP256R1 16 +#define R_EC_BRP256T1 17 +#define R_EC_BRP384R1 18 +#define R_EC_BRP384T1 19 +#define R_EC_BRP512R1 20 +#define R_EC_BRP512T1 21 +#define R_EC_X25519 22 +#define R_EC_X448 23 +#ifndef OPENSSL_NO_EC +static OPT_PAIR ecdsa_choices[] = { + {"ecdsap160", R_EC_P160}, + {"ecdsap192", R_EC_P192}, + {"ecdsap224", R_EC_P224}, + {"ecdsap256", R_EC_P256}, + {"ecdsap384", R_EC_P384}, + {"ecdsap521", R_EC_P521}, + {"ecdsak163", R_EC_K163}, + {"ecdsak233", R_EC_K233}, + {"ecdsak283", R_EC_K283}, + {"ecdsak409", R_EC_K409}, + {"ecdsak571", R_EC_K571}, + {"ecdsab163", R_EC_B163}, + {"ecdsab233", R_EC_B233}, + {"ecdsab283", R_EC_B283}, + {"ecdsab409", R_EC_B409}, + {"ecdsab571", R_EC_B571}, + {"ecdsabrp256r1", R_EC_BRP256R1}, + {"ecdsabrp256t1", R_EC_BRP256T1}, + {"ecdsabrp384r1", R_EC_BRP384R1}, + {"ecdsabrp384t1", R_EC_BRP384T1}, + {"ecdsabrp512r1", R_EC_BRP512R1}, + {"ecdsabrp512t1", R_EC_BRP512T1} +}; +# define ECDSA_NUM OSSL_NELEM(ecdsa_choices) + +static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */ + +static const OPT_PAIR ecdh_choices[] = { + {"ecdhp160", R_EC_P160}, + {"ecdhp192", R_EC_P192}, + {"ecdhp224", R_EC_P224}, + {"ecdhp256", R_EC_P256}, + {"ecdhp384", R_EC_P384}, + {"ecdhp521", R_EC_P521}, + {"ecdhk163", R_EC_K163}, + {"ecdhk233", R_EC_K233}, + {"ecdhk283", R_EC_K283}, + {"ecdhk409", R_EC_K409}, + {"ecdhk571", R_EC_K571}, + {"ecdhb163", R_EC_B163}, + {"ecdhb233", R_EC_B233}, + {"ecdhb283", R_EC_B283}, + {"ecdhb409", R_EC_B409}, + {"ecdhb571", R_EC_B571}, + {"ecdhbrp256r1", R_EC_BRP256R1}, + {"ecdhbrp256t1", R_EC_BRP256T1}, + {"ecdhbrp384r1", R_EC_BRP384R1}, + {"ecdhbrp384t1", R_EC_BRP384T1}, + {"ecdhbrp512r1", R_EC_BRP512R1}, + {"ecdhbrp512t1", R_EC_BRP512T1}, + {"ecdhx25519", R_EC_X25519}, + {"ecdhx448", R_EC_X448} +}; +# define EC_NUM OSSL_NELEM(ecdh_choices) + +static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */ -int MAIN(int, char **); +#define R_EC_Ed25519 0 +#define R_EC_Ed448 1 +static OPT_PAIR eddsa_choices[] = { + {"ed25519", R_EC_Ed25519}, + {"ed448", R_EC_Ed448} +}; +# define EdDSA_NUM OSSL_NELEM(eddsa_choices) + +static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_EC */ + +#ifndef SIGALRM +# define COND(d) (count < (d)) +# define COUNT(d) (d) +#else +# define COND(unused_cond) (run && count<0x7fffffff) +# define COUNT(d) (count) +#endif /* SIGALRM */ + +typedef struct loopargs_st { + ASYNC_JOB *inprogress_job; + ASYNC_WAIT_CTX *wait_ctx; + unsigned char *buf; + unsigned char *buf2; + unsigned char *buf_malloc; + unsigned char *buf2_malloc; + unsigned char *key; + unsigned int siglen; + size_t sigsize; +#ifndef OPENSSL_NO_RSA + RSA *rsa_key[RSA_NUM]; +#endif +#ifndef OPENSSL_NO_DSA + DSA *dsa_key[DSA_NUM]; +#endif +#ifndef OPENSSL_NO_EC + EC_KEY *ecdsa[ECDSA_NUM]; + EVP_PKEY_CTX *ecdh_ctx[EC_NUM]; + EVP_MD_CTX *eddsa_ctx[EdDSA_NUM]; + unsigned char *secret_a; + unsigned char *secret_b; + size_t outlen[EC_NUM]; +#endif + EVP_CIPHER_CTX *ctx; + HMAC_CTX *hctx; + GCM128_CONTEXT *gcm_ctx; +} loopargs_t; +static int run_benchmark(int async_jobs, int (*loop_function) (void *), + loopargs_t * loopargs); -int MAIN(int argc, char **argv) +static unsigned int testnum; + +/* Nb of iterations to do per algorithm and key-size */ +static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)]; + +#ifndef OPENSSL_NO_MD2 +static int EVP_Digest_MD2_loop(void *args) { - ENGINE *e = NULL; - unsigned char *buf = NULL, *buf2 = NULL; - int mret = 1; - long count = 0, save_count = 0; - int i, j, k; -# if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) - long rsa_count; -# endif -# ifndef OPENSSL_NO_RSA - unsigned rsa_num; -# endif - unsigned char md[EVP_MAX_MD_SIZE]; -# ifndef OPENSSL_NO_MD2 + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char md2[MD2_DIGEST_LENGTH]; -# endif -# ifndef OPENSSL_NO_MDC2 + int count; + + for (count = 0; COND(c[D_MD2][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(), + NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_MDC2 +static int EVP_Digest_MDC2_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char mdc2[MDC2_DIGEST_LENGTH]; -# endif -# ifndef OPENSSL_NO_MD4 + int count; + + for (count = 0; COND(c[D_MDC2][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(), + NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_MD4 +static int EVP_Digest_MD4_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char md4[MD4_DIGEST_LENGTH]; -# endif -# ifndef OPENSSL_NO_MD5 + int count; + + for (count = 0; COND(c[D_MD4][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(), + NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_MD5 +static int MD5_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char md5[MD5_DIGEST_LENGTH]; + int count; + for (count = 0; COND(c[D_MD5][testnum]); count++) + MD5(buf, lengths[testnum], md5); + return count; +} + +static int HMAC_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + HMAC_CTX *hctx = tempargs->hctx; unsigned char hmac[MD5_DIGEST_LENGTH]; -# endif -# ifndef OPENSSL_NO_SHA + int count; + + for (count = 0; COND(c[D_HMAC][testnum]); count++) { + HMAC_Init_ex(hctx, NULL, 0, NULL, NULL); + HMAC_Update(hctx, buf, lengths[testnum]); + HMAC_Final(hctx, hmac, NULL); + } + return count; +} +#endif + +static int SHA1_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char sha[SHA_DIGEST_LENGTH]; -# ifndef OPENSSL_NO_SHA256 + int count; + for (count = 0; COND(c[D_SHA1][testnum]); count++) + SHA1(buf, lengths[testnum], sha); + return count; +} + +static int SHA256_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char sha256[SHA256_DIGEST_LENGTH]; -# endif -# ifndef OPENSSL_NO_SHA512 + int count; + for (count = 0; COND(c[D_SHA256][testnum]); count++) + SHA256(buf, lengths[testnum], sha256); + return count; +} + +static int SHA512_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char sha512[SHA512_DIGEST_LENGTH]; -# endif -# endif -# ifndef OPENSSL_NO_WHIRLPOOL + int count; + for (count = 0; COND(c[D_SHA512][testnum]); count++) + SHA512(buf, lengths[testnum], sha512); + return count; +} + +#ifndef OPENSSL_NO_WHIRLPOOL +static int WHIRLPOOL_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH]; -# endif -# ifndef OPENSSL_NO_RIPEMD + int count; + for (count = 0; COND(c[D_WHIRLPOOL][testnum]); count++) + WHIRLPOOL(buf, lengths[testnum], whirlpool); + return count; +} +#endif + +#ifndef OPENSSL_NO_RMD160 +static int EVP_Digest_RMD160_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; unsigned char rmd160[RIPEMD160_DIGEST_LENGTH]; -# endif -# ifndef OPENSSL_NO_RC4 - RC4_KEY rc4_ks; -# endif -# ifndef OPENSSL_NO_RC5 + int count; + for (count = 0; COND(c[D_RMD160][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], &(rmd160[0]), + NULL, EVP_ripemd160(), NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_RC4 +static RC4_KEY rc4_ks; +static int RC4_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_RC4][testnum]); count++) + RC4(&rc4_ks, (size_t)lengths[testnum], buf, buf); + return count; +} +#endif + +#ifndef OPENSSL_NO_DES +static unsigned char DES_iv[8]; +static DES_key_schedule sch; +static DES_key_schedule sch2; +static DES_key_schedule sch3; +static int DES_ncbc_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_DES][testnum]); count++) + DES_ncbc_encrypt(buf, buf, lengths[testnum], &sch, + &DES_iv, DES_ENCRYPT); + return count; +} + +static int DES_ede3_cbc_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_EDE3_DES][testnum]); count++) + DES_ede3_cbc_encrypt(buf, buf, lengths[testnum], + &sch, &sch2, &sch3, &DES_iv, DES_ENCRYPT); + return count; +} +#endif + +#define MAX_BLOCK_SIZE 128 + +static unsigned char iv[2 * MAX_BLOCK_SIZE / 8]; +static AES_KEY aes_ks1, aes_ks2, aes_ks3; +static int AES_cbc_128_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_128_AES][testnum]); count++) + AES_cbc_encrypt(buf, buf, + (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT); + return count; +} + +static int AES_cbc_192_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_192_AES][testnum]); count++) + AES_cbc_encrypt(buf, buf, + (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT); + return count; +} + +static int AES_cbc_256_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_256_AES][testnum]); count++) + AES_cbc_encrypt(buf, buf, + (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT); + return count; +} + +static int AES_ige_128_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + int count; + for (count = 0; COND(c[D_IGE_128_AES][testnum]); count++) + AES_ige_encrypt(buf, buf2, + (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT); + return count; +} + +static int AES_ige_192_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + int count; + for (count = 0; COND(c[D_IGE_192_AES][testnum]); count++) + AES_ige_encrypt(buf, buf2, + (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT); + return count; +} + +static int AES_ige_256_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + int count; + for (count = 0; COND(c[D_IGE_256_AES][testnum]); count++) + AES_ige_encrypt(buf, buf2, + (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT); + return count; +} + +static int CRYPTO_gcm128_aad_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + GCM128_CONTEXT *gcm_ctx = tempargs->gcm_ctx; + int count; + for (count = 0; COND(c[D_GHASH][testnum]); count++) + CRYPTO_gcm128_aad(gcm_ctx, buf, lengths[testnum]); + return count; +} + +static int RAND_bytes_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + + for (count = 0; COND(c[D_RAND][testnum]); count++) + RAND_bytes(buf, lengths[testnum]); + return count; +} + +static long save_count = 0; +static int decrypt = 0; +static int EVP_Update_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_CIPHER_CTX *ctx = tempargs->ctx; + int outl, count, rc; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + if (decrypt) { + for (count = 0; COND(nb_iter); count++) { + rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + if (rc != 1) { + /* reset iv in case of counter overflow */ + EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); + } + } + } else { + for (count = 0; COND(nb_iter); count++) { + rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + if (rc != 1) { + /* reset iv in case of counter overflow */ + EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); + } + } + } + if (decrypt) + EVP_DecryptFinal_ex(ctx, buf, &outl); + else + EVP_EncryptFinal_ex(ctx, buf, &outl); + return count; +} + +/* + * CCM does not support streaming. For the purpose of performance measurement, + * each message is encrypted using the same (key,iv)-pair. Do not use this + * code in your application. + */ +static int EVP_Update_loop_ccm(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_CIPHER_CTX *ctx = tempargs->ctx; + int outl, count; + unsigned char tag[12]; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + if (decrypt) { + for (count = 0; COND(nb_iter); count++) { + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag); + /* reset iv */ + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); + /* counter is reset on every update */ + EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + } + } else { + for (count = 0; COND(nb_iter); count++) { + /* restore iv length field */ + EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]); + /* counter is reset on every update */ + EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + } + } + if (decrypt) + EVP_DecryptFinal_ex(ctx, buf, &outl); + else + EVP_EncryptFinal_ex(ctx, buf, &outl); + return count; +} + +/* + * To make AEAD benchmarking more relevant perform TLS-like operations, + * 13-byte AAD followed by payload. But don't use TLS-formatted AAD, as + * payload length is not actually limited by 16KB... + */ +static int EVP_Update_loop_aead(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_CIPHER_CTX *ctx = tempargs->ctx; + int outl, count; + unsigned char aad[13] = { 0xcc }; + unsigned char faketag[16] = { 0xcc }; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + if (decrypt) { + for (count = 0; COND(nb_iter); count++) { + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + sizeof(faketag), faketag); + EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + EVP_DecryptFinal_ex(ctx, buf + outl, &outl); + } + } else { + for (count = 0; COND(nb_iter); count++) { + EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv); + EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + EVP_EncryptFinal_ex(ctx, buf + outl, &outl); + } + } + return count; +} + +static const EVP_MD *evp_md = NULL; +static int EVP_Digest_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char md[EVP_MAX_MD_SIZE]; + int count; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + + for (count = 0; COND(nb_iter); count++) { + if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL)) + return -1; + } + return count; +} + +#ifndef OPENSSL_NO_RSA +static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */ + +static int RSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + unsigned int *rsa_num = &tempargs->siglen; + RSA **rsa_key = tempargs->rsa_key; + int ret, count; + for (count = 0; COND(rsa_c[testnum][0]); count++) { + ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]); + if (ret == 0) { + BIO_printf(bio_err, "RSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int RSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + unsigned int rsa_num = tempargs->siglen; + RSA **rsa_key = tempargs->rsa_key; + int ret, count; + for (count = 0; COND(rsa_c[testnum][1]); count++) { + ret = + RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]); + if (ret <= 0) { + BIO_printf(bio_err, "RSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} +#endif + +#ifndef OPENSSL_NO_DSA +static long dsa_c[DSA_NUM][2]; +static int DSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + DSA **dsa_key = tempargs->dsa_key; + unsigned int *siglen = &tempargs->siglen; + int ret, count; + for (count = 0; COND(dsa_c[testnum][0]); count++) { + ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]); + if (ret == 0) { + BIO_printf(bio_err, "DSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int DSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + DSA **dsa_key = tempargs->dsa_key; + unsigned int siglen = tempargs->siglen; + int ret, count; + for (count = 0; COND(dsa_c[testnum][1]); count++) { + ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]); + if (ret <= 0) { + BIO_printf(bio_err, "DSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} +#endif + +#ifndef OPENSSL_NO_EC +static long ecdsa_c[ECDSA_NUM][2]; +static int ECDSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EC_KEY **ecdsa = tempargs->ecdsa; + unsigned char *ecdsasig = tempargs->buf2; + unsigned int *ecdsasiglen = &tempargs->siglen; + int ret, count; + for (count = 0; COND(ecdsa_c[testnum][0]); count++) { + ret = ECDSA_sign(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]); + if (ret == 0) { + BIO_printf(bio_err, "ECDSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int ECDSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EC_KEY **ecdsa = tempargs->ecdsa; + unsigned char *ecdsasig = tempargs->buf2; + unsigned int ecdsasiglen = tempargs->siglen; + int ret, count; + for (count = 0; COND(ecdsa_c[testnum][1]); count++) { + ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]); + if (ret != 1) { + BIO_printf(bio_err, "ECDSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +/* ******************************************************************** */ +static long ecdh_c[EC_NUM][1]; + +static int ECDH_EVP_derive_key_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->ecdh_ctx[testnum]; + unsigned char *derived_secret = tempargs->secret_a; + int count; + size_t *outlen = &(tempargs->outlen[testnum]); + + for (count = 0; COND(ecdh_c[testnum][0]); count++) + EVP_PKEY_derive(ctx, derived_secret, outlen); + + return count; +} + +static long eddsa_c[EdDSA_NUM][2]; +static int EdDSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_MD_CTX **edctx = tempargs->eddsa_ctx; + unsigned char *eddsasig = tempargs->buf2; + size_t *eddsasigsize = &tempargs->sigsize; + int ret, count; + + for (count = 0; COND(eddsa_c[testnum][0]); count++) { + ret = EVP_DigestSign(edctx[testnum], eddsasig, eddsasigsize, buf, 20); + if (ret == 0) { + BIO_printf(bio_err, "EdDSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int EdDSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_MD_CTX **edctx = tempargs->eddsa_ctx; + unsigned char *eddsasig = tempargs->buf2; + size_t eddsasigsize = tempargs->sigsize; + int ret, count; + + for (count = 0; COND(eddsa_c[testnum][1]); count++) { + ret = EVP_DigestVerify(edctx[testnum], eddsasig, eddsasigsize, buf, 20); + if (ret != 1) { + BIO_printf(bio_err, "EdDSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} +#endif /* OPENSSL_NO_EC */ + +static int run_benchmark(int async_jobs, + int (*loop_function) (void *), loopargs_t * loopargs) +{ + int job_op_count = 0; + int total_op_count = 0; + int num_inprogress = 0; + int error = 0, i = 0, ret = 0; + OSSL_ASYNC_FD job_fd = 0; + size_t num_job_fds = 0; + + run = 1; + + if (async_jobs == 0) { + return loop_function((void *)&loopargs); + } + + for (i = 0; i < async_jobs && !error; i++) { + loopargs_t *looparg_item = loopargs + i; + + /* Copy pointer content (looparg_t item address) into async context */ + ret = ASYNC_start_job(&loopargs[i].inprogress_job, loopargs[i].wait_ctx, + &job_op_count, loop_function, + (void *)&looparg_item, sizeof(looparg_item)); + switch (ret) { + case ASYNC_PAUSE: + ++num_inprogress; + break; + case ASYNC_FINISH: + if (job_op_count == -1) { + error = 1; + } else { + total_op_count += job_op_count; + } + break; + case ASYNC_NO_JOBS: + case ASYNC_ERR: + BIO_printf(bio_err, "Failure in the job\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + } + + while (num_inprogress > 0) { +#if defined(OPENSSL_SYS_WINDOWS) + DWORD avail = 0; +#elif defined(OPENSSL_SYS_UNIX) + int select_result = 0; + OSSL_ASYNC_FD max_fd = 0; + fd_set waitfdset; + + FD_ZERO(&waitfdset); + + for (i = 0; i < async_jobs && num_inprogress > 0; i++) { + if (loopargs[i].inprogress_job == NULL) + continue; + + if (!ASYNC_WAIT_CTX_get_all_fds + (loopargs[i].wait_ctx, NULL, &num_job_fds) + || num_job_fds > 1) { + BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, + &num_job_fds); + FD_SET(job_fd, &waitfdset); + if (job_fd > max_fd) + max_fd = job_fd; + } + + if (max_fd >= (OSSL_ASYNC_FD)FD_SETSIZE) { + BIO_printf(bio_err, + "Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). " + "Decrease the value of async_jobs\n", + max_fd, FD_SETSIZE); + ERR_print_errors(bio_err); + error = 1; + break; + } + + select_result = select(max_fd + 1, &waitfdset, NULL, NULL, NULL); + if (select_result == -1 && errno == EINTR) + continue; + + if (select_result == -1) { + BIO_printf(bio_err, "Failure in the select\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + + if (select_result == 0) + continue; +#endif + + for (i = 0; i < async_jobs; i++) { + if (loopargs[i].inprogress_job == NULL) + continue; + + if (!ASYNC_WAIT_CTX_get_all_fds + (loopargs[i].wait_ctx, NULL, &num_job_fds) + || num_job_fds > 1) { + BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, + &num_job_fds); + +#if defined(OPENSSL_SYS_UNIX) + if (num_job_fds == 1 && !FD_ISSET(job_fd, &waitfdset)) + continue; +#elif defined(OPENSSL_SYS_WINDOWS) + if (num_job_fds == 1 + && !PeekNamedPipe(job_fd, NULL, 0, NULL, &avail, NULL) + && avail > 0) + continue; +#endif + + ret = ASYNC_start_job(&loopargs[i].inprogress_job, + loopargs[i].wait_ctx, &job_op_count, + loop_function, (void *)(loopargs + i), + sizeof(loopargs_t)); + switch (ret) { + case ASYNC_PAUSE: + break; + case ASYNC_FINISH: + if (job_op_count == -1) { + error = 1; + } else { + total_op_count += job_op_count; + } + --num_inprogress; + loopargs[i].inprogress_job = NULL; + break; + case ASYNC_NO_JOBS: + case ASYNC_ERR: + --num_inprogress; + loopargs[i].inprogress_job = NULL; + BIO_printf(bio_err, "Failure in the job\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + } + } + + return error ? -1 : total_op_count; +} + +int speed_main(int argc, char **argv) +{ + ENGINE *e = NULL; + loopargs_t *loopargs = NULL; + const char *prog; + const char *engine_id = NULL; + const EVP_CIPHER *evp_cipher = NULL; + double d = 0.0; + OPTION_CHOICE o; + int async_init = 0, multiblock = 0, pr_header = 0; + int doit[ALGOR_NUM] = { 0 }; + int ret = 1, misalign = 0, lengths_single = 0, aead = 0; + long count = 0; + unsigned int size_num = OSSL_NELEM(lengths_list); + unsigned int i, k, loop, loopargs_len = 0, async_jobs = 0; + int keylen; + int buflen; +#ifndef NO_FORK + int multi = 0; +#endif +#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \ + || !defined(OPENSSL_NO_EC) + long rsa_count = 1; +#endif + openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS, + ECDSA_SECONDS, ECDH_SECONDS, + EdDSA_SECONDS }; + + /* What follows are the buffers and key material. */ +#ifndef OPENSSL_NO_RC5 RC5_32_KEY rc5_ks; -# endif -# ifndef OPENSSL_NO_RC2 +#endif +#ifndef OPENSSL_NO_RC2 RC2_KEY rc2_ks; -# endif -# ifndef OPENSSL_NO_IDEA +#endif +#ifndef OPENSSL_NO_IDEA IDEA_KEY_SCHEDULE idea_ks; -# endif -# ifndef OPENSSL_NO_SEED +#endif +#ifndef OPENSSL_NO_SEED SEED_KEY_SCHEDULE seed_ks; -# endif -# ifndef OPENSSL_NO_BF +#endif +#ifndef OPENSSL_NO_BF BF_KEY bf_ks; -# endif -# ifndef OPENSSL_NO_CAST +#endif +#ifndef OPENSSL_NO_CAST CAST_KEY cast_ks; -# endif +#endif static const unsigned char key16[16] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 }; -# ifndef OPENSSL_NO_AES static const unsigned char key24[24] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, @@ -450,8 +1438,7 @@ int MAIN(int argc, char **argv) 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56 }; -# endif -# ifndef OPENSSL_NO_CAMELLIA +#ifndef OPENSSL_NO_CAMELLIA static const unsigned char ckey24[24] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, @@ -463,792 +1450,381 @@ int MAIN(int argc, char **argv) 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56 }; -# endif -# ifndef OPENSSL_NO_AES -# define MAX_BLOCK_SIZE 128 -# else -# define MAX_BLOCK_SIZE 64 -# endif - unsigned char DES_iv[8]; - unsigned char iv[2 * MAX_BLOCK_SIZE / 8]; -# ifndef OPENSSL_NO_DES - static DES_cblock key = - { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 }; - static DES_cblock key2 = - { 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 }; - static DES_cblock key3 = - { 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 }; - DES_key_schedule sch; - DES_key_schedule sch2; - DES_key_schedule sch3; -# endif -# ifndef OPENSSL_NO_AES - AES_KEY aes_ks1, aes_ks2, aes_ks3; -# endif -# ifndef OPENSSL_NO_CAMELLIA CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3; -# endif -# define D_MD2 0 -# define D_MDC2 1 -# define D_MD4 2 -# define D_MD5 3 -# define D_HMAC 4 -# define D_SHA1 5 -# define D_RMD160 6 -# define D_RC4 7 -# define D_CBC_DES 8 -# define D_EDE3_DES 9 -# define D_CBC_IDEA 10 -# define D_CBC_SEED 11 -# define D_CBC_RC2 12 -# define D_CBC_RC5 13 -# define D_CBC_BF 14 -# define D_CBC_CAST 15 -# define D_CBC_128_AES 16 -# define D_CBC_192_AES 17 -# define D_CBC_256_AES 18 -# define D_CBC_128_CML 19 -# define D_CBC_192_CML 20 -# define D_CBC_256_CML 21 -# define D_EVP 22 -# define D_SHA256 23 -# define D_SHA512 24 -# define D_WHIRLPOOL 25 -# define D_IGE_128_AES 26 -# define D_IGE_192_AES 27 -# define D_IGE_256_AES 28 -# define D_GHASH 29 - double d = 0.0; - long c[ALGOR_NUM][SIZE_NUM]; -# define R_DSA_512 0 -# define R_DSA_1024 1 -# define R_DSA_2048 2 -# define R_RSA_512 0 -# define R_RSA_1024 1 -# define R_RSA_2048 2 -# define R_RSA_4096 3 - -# define R_EC_P160 0 -# define R_EC_P192 1 -# define R_EC_P224 2 -# define R_EC_P256 3 -# define R_EC_P384 4 -# define R_EC_P521 5 -# define R_EC_K163 6 -# define R_EC_K233 7 -# define R_EC_K283 8 -# define R_EC_K409 9 -# define R_EC_K571 10 -# define R_EC_B163 11 -# define R_EC_B233 12 -# define R_EC_B283 13 -# define R_EC_B409 14 -# define R_EC_B571 15 - -# ifndef OPENSSL_NO_RSA - RSA *rsa_key[RSA_NUM]; - long rsa_c[RSA_NUM][2]; - static unsigned int rsa_bits[RSA_NUM] = { - 512, 1024, 2048, 4096 +#endif +#ifndef OPENSSL_NO_DES + static DES_cblock key = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 + }; + static DES_cblock key2 = { + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 + }; + static DES_cblock key3 = { + 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 + }; +#endif +#ifndef OPENSSL_NO_RSA + static const unsigned int rsa_bits[RSA_NUM] = { + 512, 1024, 2048, 3072, 4096, 7680, 15360 }; - static unsigned char *rsa_data[RSA_NUM] = { - test512, test1024, test2048, test4096 + static const unsigned char *rsa_data[RSA_NUM] = { + test512, test1024, test2048, test3072, test4096, test7680, test15360 }; - static int rsa_data_length[RSA_NUM] = { + static const int rsa_data_length[RSA_NUM] = { sizeof(test512), sizeof(test1024), - sizeof(test2048), sizeof(test4096) + sizeof(test2048), sizeof(test3072), + sizeof(test4096), sizeof(test7680), + sizeof(test15360) }; -# endif -# ifndef OPENSSL_NO_DSA - DSA *dsa_key[DSA_NUM]; - long dsa_c[DSA_NUM][2]; - static unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 }; -# endif -# ifndef OPENSSL_NO_EC + int rsa_doit[RSA_NUM] = { 0 }; + int primes = RSA_DEFAULT_PRIME_NUM; +#endif +#ifndef OPENSSL_NO_DSA + static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 }; + int dsa_doit[DSA_NUM] = { 0 }; +#endif +#ifndef OPENSSL_NO_EC /* * We only test over the following curves as they are representative, To * add tests over more curves, simply add the curve NID and curve name to - * the following arrays and increase the EC_NUM value accordingly. + * the following arrays and increase the |ecdh_choices| list accordingly. */ - static unsigned int test_curves[EC_NUM] = { + static const struct { + const char *name; + unsigned int nid; + unsigned int bits; + } test_curves[] = { /* Prime Curves */ - NID_secp160r1, - NID_X9_62_prime192v1, - NID_secp224r1, - NID_X9_62_prime256v1, - NID_secp384r1, - NID_secp521r1, + {"secp160r1", NID_secp160r1, 160}, + {"nistp192", NID_X9_62_prime192v1, 192}, + {"nistp224", NID_secp224r1, 224}, + {"nistp256", NID_X9_62_prime256v1, 256}, + {"nistp384", NID_secp384r1, 384}, + {"nistp521", NID_secp521r1, 521}, /* Binary Curves */ - NID_sect163k1, - NID_sect233k1, - NID_sect283k1, - NID_sect409k1, - NID_sect571k1, - NID_sect163r2, - NID_sect233r1, - NID_sect283r1, - NID_sect409r1, - NID_sect571r1 + {"nistk163", NID_sect163k1, 163}, + {"nistk233", NID_sect233k1, 233}, + {"nistk283", NID_sect283k1, 283}, + {"nistk409", NID_sect409k1, 409}, + {"nistk571", NID_sect571k1, 571}, + {"nistb163", NID_sect163r2, 163}, + {"nistb233", NID_sect233r1, 233}, + {"nistb283", NID_sect283r1, 283}, + {"nistb409", NID_sect409r1, 409}, + {"nistb571", NID_sect571r1, 571}, + {"brainpoolP256r1", NID_brainpoolP256r1, 256}, + {"brainpoolP256t1", NID_brainpoolP256t1, 256}, + {"brainpoolP384r1", NID_brainpoolP384r1, 384}, + {"brainpoolP384t1", NID_brainpoolP384t1, 384}, + {"brainpoolP512r1", NID_brainpoolP512r1, 512}, + {"brainpoolP512t1", NID_brainpoolP512t1, 512}, + /* Other and ECDH only ones */ + {"X25519", NID_X25519, 253}, + {"X448", NID_X448, 448} }; - static const char *test_curves_names[EC_NUM] = { - /* Prime Curves */ - "secp160r1", - "nistp192", - "nistp224", - "nistp256", - "nistp384", - "nistp521", - /* Binary Curves */ - "nistk163", - "nistk233", - "nistk283", - "nistk409", - "nistk571", - "nistb163", - "nistb233", - "nistb283", - "nistb409", - "nistb571" - }; - static int test_curves_bits[EC_NUM] = { - 160, 192, 224, 256, 384, 521, - 163, 233, 283, 409, 571, - 163, 233, 283, 409, 571 + static const struct { + const char *name; + unsigned int nid; + unsigned int bits; + size_t sigsize; + } test_ed_curves[] = { + /* EdDSA */ + {"Ed25519", NID_ED25519, 253, 64}, + {"Ed448", NID_ED448, 456, 114} }; + int ecdsa_doit[ECDSA_NUM] = { 0 }; + int ecdh_doit[EC_NUM] = { 0 }; + int eddsa_doit[EdDSA_NUM] = { 0 }; + OPENSSL_assert(OSSL_NELEM(test_curves) >= EC_NUM); + OPENSSL_assert(OSSL_NELEM(test_ed_curves) >= EdDSA_NUM); +#endif /* ndef OPENSSL_NO_EC */ -# endif - -# ifndef OPENSSL_NO_ECDSA - unsigned char ecdsasig[256]; - unsigned int ecdsasiglen; - EC_KEY *ecdsa[EC_NUM]; - long ecdsa_c[EC_NUM][2]; -# endif - -# ifndef OPENSSL_NO_ECDH - EC_KEY *ecdh_a[EC_NUM], *ecdh_b[EC_NUM]; - unsigned char secret_a[MAX_ECDH_SIZE], secret_b[MAX_ECDH_SIZE]; - int secret_size_a, secret_size_b; - int ecdh_checks = 0; - int secret_idx = 0; - long ecdh_c[EC_NUM][2]; -# endif - - int rsa_doit[RSA_NUM]; - int dsa_doit[DSA_NUM]; -# ifndef OPENSSL_NO_ECDSA - int ecdsa_doit[EC_NUM]; -# endif -# ifndef OPENSSL_NO_ECDH - int ecdh_doit[EC_NUM]; -# endif - int doit[ALGOR_NUM]; - int pr_header = 0; - const EVP_CIPHER *evp_cipher = NULL; - const EVP_MD *evp_md = NULL; - int decrypt = 0; -# ifndef NO_FORK - int multi = 0; -# endif - int multiblock = 0; - -# ifndef TIMES - usertime = -1; -# endif - - apps_startup(); - memset(results, 0, sizeof(results)); -# ifndef OPENSSL_NO_DSA - memset(dsa_key, 0, sizeof(dsa_key)); -# endif -# ifndef OPENSSL_NO_ECDSA - for (i = 0; i < EC_NUM; i++) - ecdsa[i] = NULL; -# endif -# ifndef OPENSSL_NO_ECDH - for (i = 0; i < EC_NUM; i++) { - ecdh_a[i] = NULL; - ecdh_b[i] = NULL; - } -# endif -# ifndef OPENSSL_NO_RSA - for (i = 0; i < RSA_NUM; i++) - rsa_key[i] = NULL; -# endif - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; - - if ((buf = (unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL) { - BIO_printf(bio_err, "out of memory\n"); - goto end; - } - if ((buf2 = (unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL) { - BIO_printf(bio_err, "out of memory\n"); - goto end; - } - - memset(c, 0, sizeof(c)); - memset(DES_iv, 0, sizeof(DES_iv)); - memset(iv, 0, sizeof(iv)); - - for (i = 0; i < ALGOR_NUM; i++) - doit[i] = 0; - for (i = 0; i < RSA_NUM; i++) - rsa_doit[i] = 0; - for (i = 0; i < DSA_NUM; i++) - dsa_doit[i] = 0; -# ifndef OPENSSL_NO_ECDSA - for (i = 0; i < EC_NUM; i++) - ecdsa_doit[i] = 0; -# endif -# ifndef OPENSSL_NO_ECDH - for (i = 0; i < EC_NUM; i++) - ecdh_doit[i] = 0; -# endif - - j = 0; - argc--; - argv++; - while (argc) { - if ((argc > 0) && (strcmp(*argv, "-elapsed") == 0)) { + prog = opt_init(argc, argv, speed_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opterr: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(speed_options); + ret = 0; + goto end; + case OPT_ELAPSED: usertime = 0; - j--; /* Otherwise, -elapsed gets confused with an - * algorithm. */ - } else if ((argc > 0) && (strcmp(*argv, "-evp") == 0)) { - argc--; - argv++; - if (argc == 0) { - BIO_printf(bio_err, "no EVP given\n"); - goto end; - } + break; + case OPT_EVP: evp_md = NULL; - evp_cipher = EVP_get_cipherbyname(*argv); - if (!evp_cipher) { - evp_md = EVP_get_digestbyname(*argv); - } - if (!evp_cipher && !evp_md) { - BIO_printf(bio_err, "%s is an unknown cipher or digest\n", - *argv); + evp_cipher = EVP_get_cipherbyname(opt_arg()); + if (evp_cipher == NULL) + evp_md = EVP_get_digestbyname(opt_arg()); + if (evp_cipher == NULL && evp_md == NULL) { + BIO_printf(bio_err, + "%s: %s is an unknown cipher or digest\n", + prog, opt_arg()); goto end; } doit[D_EVP] = 1; - } else if (argc > 0 && !strcmp(*argv, "-decrypt")) { + break; + case OPT_DECRYPT: decrypt = 1; - j--; /* Otherwise, -elapsed gets confused with an - * algorithm. */ - } -# ifndef OPENSSL_NO_ENGINE - else if ((argc > 0) && (strcmp(*argv, "-engine") == 0)) { - argc--; - argv++; - if (argc == 0) { - BIO_printf(bio_err, "no engine given\n"); - goto end; - } - e = setup_engine(bio_err, *argv, 0); + break; + case OPT_ENGINE: /* - * j will be increased again further down. We just don't want - * speed to confuse an engine with an algorithm, especially when - * none is given (which means all of them should be run) + * In a forked execution, an engine might need to be + * initialised by each child process, not by the parent. + * So store the name here and run setup_engine() later on. */ - j--; - } -# endif -# ifndef NO_FORK - else if ((argc > 0) && (strcmp(*argv, "-multi") == 0)) { - argc--; - argv++; - if (argc == 0) { - BIO_printf(bio_err, "no multi count given\n"); - goto end; + engine_id = opt_arg(); + break; + case OPT_MULTI: +#ifndef NO_FORK + multi = atoi(opt_arg()); +#endif + break; + case OPT_ASYNCJOBS: +#ifndef OPENSSL_NO_ASYNC + async_jobs = atoi(opt_arg()); + if (!ASYNC_is_capable()) { + BIO_printf(bio_err, + "%s: async_jobs specified but async not supported\n", + prog); + goto opterr; } - multi = atoi(argv[0]); - if (multi <= 0) { - BIO_printf(bio_err, "bad multi count\n"); + if (async_jobs > 99999) { + BIO_printf(bio_err, "%s: too many async_jobs\n", prog); + goto opterr; + } +#endif + break; + case OPT_MISALIGN: + if (!opt_int(opt_arg(), &misalign)) goto end; + if (misalign > MISALIGN) { + BIO_printf(bio_err, + "%s: Maximum offset is %d\n", prog, MISALIGN); + goto opterr; } - j--; /* Otherwise, -mr gets confused with an - * algorithm. */ - } -# endif - else if (argc > 0 && !strcmp(*argv, "-mr")) { + break; + case OPT_MR: mr = 1; - j--; /* Otherwise, -mr gets confused with an - * algorithm. */ - } else if (argc > 0 && !strcmp(*argv, "-mb")) { + break; + case OPT_MB: multiblock = 1; - j--; - } else -# ifndef OPENSSL_NO_MD2 - if (strcmp(*argv, "md2") == 0) - doit[D_MD2] = 1; - else -# endif -# ifndef OPENSSL_NO_MDC2 - if (strcmp(*argv, "mdc2") == 0) - doit[D_MDC2] = 1; - else -# endif -# ifndef OPENSSL_NO_MD4 - if (strcmp(*argv, "md4") == 0) - doit[D_MD4] = 1; - else -# endif -# ifndef OPENSSL_NO_MD5 - if (strcmp(*argv, "md5") == 0) - doit[D_MD5] = 1; - else -# endif -# ifndef OPENSSL_NO_MD5 - if (strcmp(*argv, "hmac") == 0) - doit[D_HMAC] = 1; - else -# endif -# ifndef OPENSSL_NO_SHA - if (strcmp(*argv, "sha1") == 0) - doit[D_SHA1] = 1; - else if (strcmp(*argv, "sha") == 0) - doit[D_SHA1] = 1, doit[D_SHA256] = 1, doit[D_SHA512] = 1; - else -# ifndef OPENSSL_NO_SHA256 - if (strcmp(*argv, "sha256") == 0) - doit[D_SHA256] = 1; - else -# endif -# ifndef OPENSSL_NO_SHA512 - if (strcmp(*argv, "sha512") == 0) - doit[D_SHA512] = 1; - else -# endif -# endif -# ifndef OPENSSL_NO_WHIRLPOOL - if (strcmp(*argv, "whirlpool") == 0) - doit[D_WHIRLPOOL] = 1; - else -# endif -# ifndef OPENSSL_NO_RIPEMD - if (strcmp(*argv, "ripemd") == 0) - doit[D_RMD160] = 1; - else if (strcmp(*argv, "rmd160") == 0) - doit[D_RMD160] = 1; - else if (strcmp(*argv, "ripemd160") == 0) - doit[D_RMD160] = 1; - else -# endif -# ifndef OPENSSL_NO_RC4 - if (strcmp(*argv, "rc4") == 0) - doit[D_RC4] = 1; - else -# endif -# ifndef OPENSSL_NO_DES - if (strcmp(*argv, "des-cbc") == 0) - doit[D_CBC_DES] = 1; - else if (strcmp(*argv, "des-ede3") == 0) - doit[D_EDE3_DES] = 1; - else -# endif -# ifndef OPENSSL_NO_AES - if (strcmp(*argv, "aes-128-cbc") == 0) - doit[D_CBC_128_AES] = 1; - else if (strcmp(*argv, "aes-192-cbc") == 0) - doit[D_CBC_192_AES] = 1; - else if (strcmp(*argv, "aes-256-cbc") == 0) - doit[D_CBC_256_AES] = 1; - else if (strcmp(*argv, "aes-128-ige") == 0) - doit[D_IGE_128_AES] = 1; - else if (strcmp(*argv, "aes-192-ige") == 0) - doit[D_IGE_192_AES] = 1; - else if (strcmp(*argv, "aes-256-ige") == 0) - doit[D_IGE_256_AES] = 1; - else -# endif -# ifndef OPENSSL_NO_CAMELLIA - if (strcmp(*argv, "camellia-128-cbc") == 0) - doit[D_CBC_128_CML] = 1; - else if (strcmp(*argv, "camellia-192-cbc") == 0) - doit[D_CBC_192_CML] = 1; - else if (strcmp(*argv, "camellia-256-cbc") == 0) - doit[D_CBC_256_CML] = 1; - else -# endif -# ifndef OPENSSL_NO_RSA -# if 0 /* was: #ifdef RSAref */ - if (strcmp(*argv, "rsaref") == 0) { - RSA_set_default_openssl_method(RSA_PKCS1_RSAref()); - j--; - } else -# endif -# ifndef RSA_NULL - if (strcmp(*argv, "openssl") == 0) { - RSA_set_default_method(RSA_PKCS1_SSLeay()); - j--; - } else -# endif -# endif /* !OPENSSL_NO_RSA */ - if (strcmp(*argv, "dsa512") == 0) - dsa_doit[R_DSA_512] = 2; - else if (strcmp(*argv, "dsa1024") == 0) - dsa_doit[R_DSA_1024] = 2; - else if (strcmp(*argv, "dsa2048") == 0) - dsa_doit[R_DSA_2048] = 2; - else if (strcmp(*argv, "rsa512") == 0) - rsa_doit[R_RSA_512] = 2; - else if (strcmp(*argv, "rsa1024") == 0) - rsa_doit[R_RSA_1024] = 2; - else if (strcmp(*argv, "rsa2048") == 0) - rsa_doit[R_RSA_2048] = 2; - else if (strcmp(*argv, "rsa4096") == 0) - rsa_doit[R_RSA_4096] = 2; - else -# ifndef OPENSSL_NO_RC2 - if (strcmp(*argv, "rc2-cbc") == 0) - doit[D_CBC_RC2] = 1; - else if (strcmp(*argv, "rc2") == 0) - doit[D_CBC_RC2] = 1; - else -# endif -# ifndef OPENSSL_NO_RC5 - if (strcmp(*argv, "rc5-cbc") == 0) - doit[D_CBC_RC5] = 1; - else if (strcmp(*argv, "rc5") == 0) - doit[D_CBC_RC5] = 1; - else -# endif -# ifndef OPENSSL_NO_IDEA - if (strcmp(*argv, "idea-cbc") == 0) - doit[D_CBC_IDEA] = 1; - else if (strcmp(*argv, "idea") == 0) - doit[D_CBC_IDEA] = 1; - else -# endif -# ifndef OPENSSL_NO_SEED - if (strcmp(*argv, "seed-cbc") == 0) - doit[D_CBC_SEED] = 1; - else if (strcmp(*argv, "seed") == 0) - doit[D_CBC_SEED] = 1; - else -# endif -# ifndef OPENSSL_NO_BF - if (strcmp(*argv, "bf-cbc") == 0) - doit[D_CBC_BF] = 1; - else if (strcmp(*argv, "blowfish") == 0) - doit[D_CBC_BF] = 1; - else if (strcmp(*argv, "bf") == 0) - doit[D_CBC_BF] = 1; - else -# endif -# ifndef OPENSSL_NO_CAST - if (strcmp(*argv, "cast-cbc") == 0) - doit[D_CBC_CAST] = 1; - else if (strcmp(*argv, "cast") == 0) - doit[D_CBC_CAST] = 1; - else if (strcmp(*argv, "cast5") == 0) - doit[D_CBC_CAST] = 1; - else -# endif -# ifndef OPENSSL_NO_DES +#ifdef OPENSSL_NO_MULTIBLOCK + BIO_printf(bio_err, + "%s: -mb specified but multi-block support is disabled\n", + prog); + goto end; +#endif + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_PRIMES: + if (!opt_int(opt_arg(), &primes)) + goto end; + break; + case OPT_SECONDS: + seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa + = seconds.ecdh = seconds.eddsa = atoi(opt_arg()); + break; + case OPT_BYTES: + lengths_single = atoi(opt_arg()); + lengths = &lengths_single; + size_num = 1; + break; + case OPT_AEAD: + aead = 1; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + /* Remaining arguments are algorithms. */ + for (; *argv; argv++) { + if (found(*argv, doit_choices, &i)) { + doit[i] = 1; + continue; + } +#ifndef OPENSSL_NO_DES if (strcmp(*argv, "des") == 0) { - doit[D_CBC_DES] = 1; - doit[D_EDE3_DES] = 1; - } else -# endif -# ifndef OPENSSL_NO_AES - if (strcmp(*argv, "aes") == 0) { - doit[D_CBC_128_AES] = 1; - doit[D_CBC_192_AES] = 1; - doit[D_CBC_256_AES] = 1; - } else if (strcmp(*argv, "ghash") == 0) { - doit[D_GHASH] = 1; - } else -# endif -# ifndef OPENSSL_NO_CAMELLIA - if (strcmp(*argv, "camellia") == 0) { - doit[D_CBC_128_CML] = 1; - doit[D_CBC_192_CML] = 1; - doit[D_CBC_256_CML] = 1; - } else -# endif -# ifndef OPENSSL_NO_RSA + doit[D_CBC_DES] = doit[D_EDE3_DES] = 1; + continue; + } +#endif + if (strcmp(*argv, "sha") == 0) { + doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1; + continue; + } +#ifndef OPENSSL_NO_RSA + if (strcmp(*argv, "openssl") == 0) + continue; if (strcmp(*argv, "rsa") == 0) { - rsa_doit[R_RSA_512] = 1; - rsa_doit[R_RSA_1024] = 1; - rsa_doit[R_RSA_2048] = 1; - rsa_doit[R_RSA_4096] = 1; - } else -# endif -# ifndef OPENSSL_NO_DSA + for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++) + rsa_doit[loop] = 1; + continue; + } + if (found(*argv, rsa_choices, &i)) { + rsa_doit[i] = 1; + continue; + } +#endif +#ifndef OPENSSL_NO_DSA if (strcmp(*argv, "dsa") == 0) { - dsa_doit[R_DSA_512] = 1; - dsa_doit[R_DSA_1024] = 1; - dsa_doit[R_DSA_2048] = 1; - } else -# endif -# ifndef OPENSSL_NO_ECDSA - if (strcmp(*argv, "ecdsap160") == 0) - ecdsa_doit[R_EC_P160] = 2; - else if (strcmp(*argv, "ecdsap192") == 0) - ecdsa_doit[R_EC_P192] = 2; - else if (strcmp(*argv, "ecdsap224") == 0) - ecdsa_doit[R_EC_P224] = 2; - else if (strcmp(*argv, "ecdsap256") == 0) - ecdsa_doit[R_EC_P256] = 2; - else if (strcmp(*argv, "ecdsap384") == 0) - ecdsa_doit[R_EC_P384] = 2; - else if (strcmp(*argv, "ecdsap521") == 0) - ecdsa_doit[R_EC_P521] = 2; - else if (strcmp(*argv, "ecdsak163") == 0) - ecdsa_doit[R_EC_K163] = 2; - else if (strcmp(*argv, "ecdsak233") == 0) - ecdsa_doit[R_EC_K233] = 2; - else if (strcmp(*argv, "ecdsak283") == 0) - ecdsa_doit[R_EC_K283] = 2; - else if (strcmp(*argv, "ecdsak409") == 0) - ecdsa_doit[R_EC_K409] = 2; - else if (strcmp(*argv, "ecdsak571") == 0) - ecdsa_doit[R_EC_K571] = 2; - else if (strcmp(*argv, "ecdsab163") == 0) - ecdsa_doit[R_EC_B163] = 2; - else if (strcmp(*argv, "ecdsab233") == 0) - ecdsa_doit[R_EC_B233] = 2; - else if (strcmp(*argv, "ecdsab283") == 0) - ecdsa_doit[R_EC_B283] = 2; - else if (strcmp(*argv, "ecdsab409") == 0) - ecdsa_doit[R_EC_B409] = 2; - else if (strcmp(*argv, "ecdsab571") == 0) - ecdsa_doit[R_EC_B571] = 2; - else if (strcmp(*argv, "ecdsa") == 0) { - for (i = 0; i < EC_NUM; i++) - ecdsa_doit[i] = 1; - } else -# endif -# ifndef OPENSSL_NO_ECDH - if (strcmp(*argv, "ecdhp160") == 0) - ecdh_doit[R_EC_P160] = 2; - else if (strcmp(*argv, "ecdhp192") == 0) - ecdh_doit[R_EC_P192] = 2; - else if (strcmp(*argv, "ecdhp224") == 0) - ecdh_doit[R_EC_P224] = 2; - else if (strcmp(*argv, "ecdhp256") == 0) - ecdh_doit[R_EC_P256] = 2; - else if (strcmp(*argv, "ecdhp384") == 0) - ecdh_doit[R_EC_P384] = 2; - else if (strcmp(*argv, "ecdhp521") == 0) - ecdh_doit[R_EC_P521] = 2; - else if (strcmp(*argv, "ecdhk163") == 0) - ecdh_doit[R_EC_K163] = 2; - else if (strcmp(*argv, "ecdhk233") == 0) - ecdh_doit[R_EC_K233] = 2; - else if (strcmp(*argv, "ecdhk283") == 0) - ecdh_doit[R_EC_K283] = 2; - else if (strcmp(*argv, "ecdhk409") == 0) - ecdh_doit[R_EC_K409] = 2; - else if (strcmp(*argv, "ecdhk571") == 0) - ecdh_doit[R_EC_K571] = 2; - else if (strcmp(*argv, "ecdhb163") == 0) - ecdh_doit[R_EC_B163] = 2; - else if (strcmp(*argv, "ecdhb233") == 0) - ecdh_doit[R_EC_B233] = 2; - else if (strcmp(*argv, "ecdhb283") == 0) - ecdh_doit[R_EC_B283] = 2; - else if (strcmp(*argv, "ecdhb409") == 0) - ecdh_doit[R_EC_B409] = 2; - else if (strcmp(*argv, "ecdhb571") == 0) - ecdh_doit[R_EC_B571] = 2; - else if (strcmp(*argv, "ecdh") == 0) { - for (i = 0; i < EC_NUM; i++) - ecdh_doit[i] = 1; - } else -# endif - { - BIO_printf(bio_err, "Error: bad option or value\n"); - BIO_printf(bio_err, "\n"); - BIO_printf(bio_err, "Available values:\n"); -# ifndef OPENSSL_NO_MD2 - BIO_printf(bio_err, "md2 "); -# endif -# ifndef OPENSSL_NO_MDC2 - BIO_printf(bio_err, "mdc2 "); -# endif -# ifndef OPENSSL_NO_MD4 - BIO_printf(bio_err, "md4 "); -# endif -# ifndef OPENSSL_NO_MD5 - BIO_printf(bio_err, "md5 "); -# ifndef OPENSSL_NO_HMAC - BIO_printf(bio_err, "hmac "); -# endif -# endif -# ifndef OPENSSL_NO_SHA1 - BIO_printf(bio_err, "sha1 "); -# endif -# ifndef OPENSSL_NO_SHA256 - BIO_printf(bio_err, "sha256 "); -# endif -# ifndef OPENSSL_NO_SHA512 - BIO_printf(bio_err, "sha512 "); -# endif -# ifndef OPENSSL_NO_WHIRLPOOL - BIO_printf(bio_err, "whirlpool"); -# endif -# ifndef OPENSSL_NO_RIPEMD160 - BIO_printf(bio_err, "rmd160"); -# endif -# if !defined(OPENSSL_NO_MD2) || !defined(OPENSSL_NO_MDC2) || \ - !defined(OPENSSL_NO_MD4) || !defined(OPENSSL_NO_MD5) || \ - !defined(OPENSSL_NO_SHA1) || !defined(OPENSSL_NO_RIPEMD160) || \ - !defined(OPENSSL_NO_WHIRLPOOL) - BIO_printf(bio_err, "\n"); -# endif - -# ifndef OPENSSL_NO_IDEA - BIO_printf(bio_err, "idea-cbc "); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, "seed-cbc "); -# endif -# ifndef OPENSSL_NO_RC2 - BIO_printf(bio_err, "rc2-cbc "); -# endif -# ifndef OPENSSL_NO_RC5 - BIO_printf(bio_err, "rc5-cbc "); -# endif -# ifndef OPENSSL_NO_BF - BIO_printf(bio_err, "bf-cbc"); -# endif -# if !defined(OPENSSL_NO_IDEA) || !defined(OPENSSL_NO_SEED) || !defined(OPENSSL_NO_RC2) || \ - !defined(OPENSSL_NO_BF) || !defined(OPENSSL_NO_RC5) - BIO_printf(bio_err, "\n"); -# endif -# ifndef OPENSSL_NO_DES - BIO_printf(bio_err, "des-cbc des-ede3 "); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, "aes-128-cbc aes-192-cbc aes-256-cbc "); - BIO_printf(bio_err, "aes-128-ige aes-192-ige aes-256-ige "); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, "\n"); - BIO_printf(bio_err, - "camellia-128-cbc camellia-192-cbc camellia-256-cbc "); -# endif -# ifndef OPENSSL_NO_RC4 - BIO_printf(bio_err, "rc4"); -# endif - BIO_printf(bio_err, "\n"); + dsa_doit[R_DSA_512] = dsa_doit[R_DSA_1024] = + dsa_doit[R_DSA_2048] = 1; + continue; + } + if (found(*argv, dsa_choices, &i)) { + dsa_doit[i] = 2; + continue; + } +#endif + if (strcmp(*argv, "aes") == 0) { + doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1; + continue; + } +#ifndef OPENSSL_NO_CAMELLIA + if (strcmp(*argv, "camellia") == 0) { + doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1; + continue; + } +#endif +#ifndef OPENSSL_NO_EC + if (strcmp(*argv, "ecdsa") == 0) { + for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++) + ecdsa_doit[loop] = 1; + continue; + } + if (found(*argv, ecdsa_choices, &i)) { + ecdsa_doit[i] = 2; + continue; + } + if (strcmp(*argv, "ecdh") == 0) { + for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++) + ecdh_doit[loop] = 1; + continue; + } + if (found(*argv, ecdh_choices, &i)) { + ecdh_doit[i] = 2; + continue; + } + if (strcmp(*argv, "eddsa") == 0) { + for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) + eddsa_doit[loop] = 1; + continue; + } + if (found(*argv, eddsa_choices, &i)) { + eddsa_doit[i] = 2; + continue; + } +#endif + BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv); + goto end; + } -# ifndef OPENSSL_NO_RSA - BIO_printf(bio_err, "rsa512 rsa1024 rsa2048 rsa4096\n"); -# endif + /* Sanity checks */ + if (aead) { + if (evp_cipher == NULL) { + BIO_printf(bio_err, "-aead can be used only with an AEAD cipher\n"); + goto end; + } else if (!(EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_AEAD_CIPHER)) { + BIO_printf(bio_err, "%s is not an AEAD cipher\n", + OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher))); + goto end; + } + } + if (multiblock) { + if (evp_cipher == NULL) { + BIO_printf(bio_err,"-mb can be used only with a multi-block" + " capable cipher\n"); + goto end; + } else if (!(EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) { + BIO_printf(bio_err, "%s is not a multi-block capable\n", + OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher))); + goto end; + } else if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with -mb"); + goto end; + } + } -# ifndef OPENSSL_NO_DSA - BIO_printf(bio_err, "dsa512 dsa1024 dsa2048\n"); -# endif -# ifndef OPENSSL_NO_ECDSA - BIO_printf(bio_err, "ecdsap160 ecdsap192 ecdsap224 " - "ecdsap256 ecdsap384 ecdsap521\n"); - BIO_printf(bio_err, - "ecdsak163 ecdsak233 ecdsak283 ecdsak409 ecdsak571\n"); - BIO_printf(bio_err, - "ecdsab163 ecdsab233 ecdsab283 ecdsab409 ecdsab571\n"); - BIO_printf(bio_err, "ecdsa\n"); -# endif -# ifndef OPENSSL_NO_ECDH - BIO_printf(bio_err, "ecdhp160 ecdhp192 ecdhp224 " - "ecdhp256 ecdhp384 ecdhp521\n"); - BIO_printf(bio_err, - "ecdhk163 ecdhk233 ecdhk283 ecdhk409 ecdhk571\n"); - BIO_printf(bio_err, - "ecdhb163 ecdhb233 ecdhb283 ecdhb409 ecdhb571\n"); - BIO_printf(bio_err, "ecdh\n"); -# endif + /* Initialize the job pool if async mode is enabled */ + if (async_jobs > 0) { + async_init = ASYNC_init_thread(async_jobs, async_jobs); + if (!async_init) { + BIO_printf(bio_err, "Error creating the ASYNC job pool\n"); + goto end; + } + } -# ifndef OPENSSL_NO_IDEA - BIO_printf(bio_err, "idea "); -# endif -# ifndef OPENSSL_NO_SEED - BIO_printf(bio_err, "seed "); -# endif -# ifndef OPENSSL_NO_RC2 - BIO_printf(bio_err, "rc2 "); -# endif -# ifndef OPENSSL_NO_DES - BIO_printf(bio_err, "des "); -# endif -# ifndef OPENSSL_NO_AES - BIO_printf(bio_err, "aes "); -# endif -# ifndef OPENSSL_NO_CAMELLIA - BIO_printf(bio_err, "camellia "); -# endif -# ifndef OPENSSL_NO_RSA - BIO_printf(bio_err, "rsa "); -# endif -# ifndef OPENSSL_NO_BF - BIO_printf(bio_err, "blowfish"); -# endif -# if !defined(OPENSSL_NO_IDEA) || !defined(OPENSSL_NO_SEED) || \ - !defined(OPENSSL_NO_RC2) || !defined(OPENSSL_NO_DES) || \ - !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_BF) || \ - !defined(OPENSSL_NO_AES) || !defined(OPENSSL_NO_CAMELLIA) - BIO_printf(bio_err, "\n"); -# endif + loopargs_len = (async_jobs == 0 ? 1 : async_jobs); + loopargs = + app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs"); + memset(loopargs, 0, loopargs_len * sizeof(loopargs_t)); - BIO_printf(bio_err, "\n"); - BIO_printf(bio_err, "Available options:\n"); -# if defined(TIMES) || defined(USE_TOD) - BIO_printf(bio_err, "-elapsed " - "measure time in real time instead of CPU user time.\n"); -# endif -# ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - "-engine e " - "use engine e, possibly a hardware device.\n"); -# endif - BIO_printf(bio_err, "-evp e " "use EVP e.\n"); - BIO_printf(bio_err, - "-decrypt " - "time decryption instead of encryption (only EVP).\n"); - BIO_printf(bio_err, - "-mr " - "produce machine readable output.\n"); -# ifndef NO_FORK - BIO_printf(bio_err, - "-multi n " "run n benchmarks in parallel.\n"); -# endif - goto end; + for (i = 0; i < loopargs_len; i++) { + if (async_jobs > 0) { + loopargs[i].wait_ctx = ASYNC_WAIT_CTX_new(); + if (loopargs[i].wait_ctx == NULL) { + BIO_printf(bio_err, "Error creating the ASYNC_WAIT_CTX\n"); + goto end; + } } - argc--; - argv++; - j++; + + buflen = lengths[size_num - 1]; + if (buflen < 36) /* size of random vector in RSA bencmark */ + buflen = 36; + buflen += MAX_MISALIGNMENT + 1; + loopargs[i].buf_malloc = app_malloc(buflen, "input buffer"); + loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer"); + memset(loopargs[i].buf_malloc, 0, buflen); + memset(loopargs[i].buf2_malloc, 0, buflen); + + /* Align the start of buffers on a 64 byte boundary */ + loopargs[i].buf = loopargs[i].buf_malloc + misalign; + loopargs[i].buf2 = loopargs[i].buf2_malloc + misalign; +#ifndef OPENSSL_NO_EC + loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a"); + loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b"); +#endif } -# ifndef NO_FORK - if (multi && do_multi(multi)) +#ifndef NO_FORK + if (multi && do_multi(multi, size_num)) goto show_res; -# endif +#endif - if (j == 0) { - for (i = 0; i < ALGOR_NUM; i++) { + /* Initialize the engine after the fork */ + e = setup_engine(engine_id, 0); + + /* No parameters; turn on everything. */ + if ((argc == 0) && !doit[D_EVP]) { + for (i = 0; i < ALGOR_NUM; i++) if (i != D_EVP) doit[i] = 1; - } +#ifndef OPENSSL_NO_RSA for (i = 0; i < RSA_NUM; i++) rsa_doit[i] = 1; +#endif +#ifndef OPENSSL_NO_DSA for (i = 0; i < DSA_NUM; i++) dsa_doit[i] = 1; -# ifndef OPENSSL_NO_ECDSA - for (i = 0; i < EC_NUM; i++) - ecdsa_doit[i] = 1; -# endif -# ifndef OPENSSL_NO_ECDH - for (i = 0; i < EC_NUM; i++) - ecdh_doit[i] = 1; -# endif +#endif +#ifndef OPENSSL_NO_EC + for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++) + ecdsa_doit[loop] = 1; + for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++) + ecdh_doit[loop] = 1; + for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) + eddsa_doit[loop] = 1; +#endif } for (i = 0; i < ALGOR_NUM; i++) if (doit[i]) @@ -1259,77 +1835,69 @@ int MAIN(int argc, char **argv) "You have chosen to measure elapsed time " "instead of user CPU time.\n"); -# ifndef OPENSSL_NO_RSA - for (i = 0; i < RSA_NUM; i++) { - const unsigned char *p; - - p = rsa_data[i]; - rsa_key[i] = d2i_RSAPrivateKey(NULL, &p, rsa_data_length[i]); - if (rsa_key[i] == NULL) { - BIO_printf(bio_err, "internal error loading RSA key number %d\n", - i); - goto end; +#ifndef OPENSSL_NO_RSA + for (i = 0; i < loopargs_len; i++) { + if (primes > RSA_DEFAULT_PRIME_NUM) { + /* for multi-prime RSA, skip this */ + break; } -# if 0 - else { - BIO_printf(bio_err, - mr ? "+RK:%d:" - : "Loaded RSA key, %d bit modulus and e= 0x", - BN_num_bits(rsa_key[i]->n)); - BN_print(bio_err, rsa_key[i]->e); - BIO_printf(bio_err, "\n"); + for (k = 0; k < RSA_NUM; k++) { + const unsigned char *p; + + p = rsa_data[k]; + loopargs[i].rsa_key[k] = + d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]); + if (loopargs[i].rsa_key[k] == NULL) { + BIO_printf(bio_err, + "internal error loading RSA key number %d\n", k); + goto end; + } } -# endif } -# endif - -# ifndef OPENSSL_NO_DSA - dsa_key[0] = get_dsa512(); - dsa_key[1] = get_dsa1024(); - dsa_key[2] = get_dsa2048(); -# endif - -# ifndef OPENSSL_NO_DES +#endif +#ifndef OPENSSL_NO_DSA + for (i = 0; i < loopargs_len; i++) { + loopargs[i].dsa_key[0] = get_dsa(512); + loopargs[i].dsa_key[1] = get_dsa(1024); + loopargs[i].dsa_key[2] = get_dsa(2048); + } +#endif +#ifndef OPENSSL_NO_DES DES_set_key_unchecked(&key, &sch); DES_set_key_unchecked(&key2, &sch2); DES_set_key_unchecked(&key3, &sch3); -# endif -# ifndef OPENSSL_NO_AES +#endif AES_set_encrypt_key(key16, 128, &aes_ks1); AES_set_encrypt_key(key24, 192, &aes_ks2); AES_set_encrypt_key(key32, 256, &aes_ks3); -# endif -# ifndef OPENSSL_NO_CAMELLIA +#ifndef OPENSSL_NO_CAMELLIA Camellia_set_key(key16, 128, &camellia_ks1); Camellia_set_key(ckey24, 192, &camellia_ks2); Camellia_set_key(ckey32, 256, &camellia_ks3); -# endif -# ifndef OPENSSL_NO_IDEA - idea_set_encrypt_key(key16, &idea_ks); -# endif -# ifndef OPENSSL_NO_SEED +#endif +#ifndef OPENSSL_NO_IDEA + IDEA_set_encrypt_key(key16, &idea_ks); +#endif +#ifndef OPENSSL_NO_SEED SEED_set_key(key16, &seed_ks); -# endif -# ifndef OPENSSL_NO_RC4 +#endif +#ifndef OPENSSL_NO_RC4 RC4_set_key(&rc4_ks, 16, key16); -# endif -# ifndef OPENSSL_NO_RC2 +#endif +#ifndef OPENSSL_NO_RC2 RC2_set_key(&rc2_ks, 16, key16, 128); -# endif -# ifndef OPENSSL_NO_RC5 +#endif +#ifndef OPENSSL_NO_RC5 RC5_32_set_key(&rc5_ks, 16, key16, 12); -# endif -# ifndef OPENSSL_NO_BF +#endif +#ifndef OPENSSL_NO_BF BF_set_key(&bf_ks, 16, key16); -# endif -# ifndef OPENSSL_NO_CAST +#endif +#ifndef OPENSSL_NO_CAST CAST_set_key(&cast_ks, 16, key16); -# endif -# ifndef OPENSSL_NO_RSA - memset(rsa_c, 0, sizeof(rsa_c)); -# endif -# ifndef SIGALRM -# ifndef OPENSSL_NO_DES +#endif +#ifndef SIGALRM +# ifndef OPENSSL_NO_DES BIO_printf(bio_err, "First we calculate the approximate speed ...\n"); count = 10; do { @@ -1337,8 +1905,8 @@ int MAIN(int argc, char **argv) count *= 2; Time_F(START); for (it = count; it; it--) - DES_ecb_encrypt((DES_cblock *)buf, - (DES_cblock *)buf, &sch, DES_ENCRYPT); + DES_ecb_encrypt((DES_cblock *)loopargs[0].buf, + (DES_cblock *)loopargs[0].buf, &sch, DES_ENCRYPT); d = Time_F(STOP); } while (d < 3); save_count = count; @@ -1371,24 +1939,29 @@ int MAIN(int argc, char **argv) c[D_IGE_192_AES][0] = count; c[D_IGE_256_AES][0] = count; c[D_GHASH][0] = count; + c[D_RAND][0] = count; - for (i = 1; i < SIZE_NUM; i++) { - c[D_MD2][i] = c[D_MD2][0] * 4 * lengths[0] / lengths[i]; - c[D_MDC2][i] = c[D_MDC2][0] * 4 * lengths[0] / lengths[i]; - c[D_MD4][i] = c[D_MD4][0] * 4 * lengths[0] / lengths[i]; - c[D_MD5][i] = c[D_MD5][0] * 4 * lengths[0] / lengths[i]; - c[D_HMAC][i] = c[D_HMAC][0] * 4 * lengths[0] / lengths[i]; - c[D_SHA1][i] = c[D_SHA1][0] * 4 * lengths[0] / lengths[i]; - c[D_RMD160][i] = c[D_RMD160][0] * 4 * lengths[0] / lengths[i]; - c[D_SHA256][i] = c[D_SHA256][0] * 4 * lengths[0] / lengths[i]; - c[D_SHA512][i] = c[D_SHA512][0] * 4 * lengths[0] / lengths[i]; - c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * lengths[0] / lengths[i]; - } - for (i = 1; i < SIZE_NUM; i++) { + for (i = 1; i < size_num; i++) { long l0, l1; - l0 = (long)lengths[i - 1]; + l0 = (long)lengths[0]; l1 = (long)lengths[i]; + + c[D_MD2][i] = c[D_MD2][0] * 4 * l0 / l1; + c[D_MDC2][i] = c[D_MDC2][0] * 4 * l0 / l1; + c[D_MD4][i] = c[D_MD4][0] * 4 * l0 / l1; + c[D_MD5][i] = c[D_MD5][0] * 4 * l0 / l1; + c[D_HMAC][i] = c[D_HMAC][0] * 4 * l0 / l1; + c[D_SHA1][i] = c[D_SHA1][0] * 4 * l0 / l1; + c[D_RMD160][i] = c[D_RMD160][0] * 4 * l0 / l1; + c[D_SHA256][i] = c[D_SHA256][0] * 4 * l0 / l1; + c[D_SHA512][i] = c[D_SHA512][0] * 4 * l0 / l1; + c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * l0 / l1; + c[D_GHASH][i] = c[D_GHASH][0] * 4 * l0 / l1; + c[D_RAND][i] = c[D_RAND][0] * 4 * l0 / l1; + + l0 = (long)lengths[i - 1]; + c[D_RC4][i] = c[D_RC4][i - 1] * l0 / l1; c[D_CBC_DES][i] = c[D_CBC_DES][i - 1] * l0 / l1; c[D_EDE3_DES][i] = c[D_EDE3_DES][i - 1] * l0 / l1; @@ -1408,50 +1981,51 @@ int MAIN(int argc, char **argv) c[D_IGE_192_AES][i] = c[D_IGE_192_AES][i - 1] * l0 / l1; c[D_IGE_256_AES][i] = c[D_IGE_256_AES][i - 1] * l0 / l1; } -# ifndef OPENSSL_NO_RSA + +# ifndef OPENSSL_NO_RSA rsa_c[R_RSA_512][0] = count / 2000; rsa_c[R_RSA_512][1] = count / 400; for (i = 1; i < RSA_NUM; i++) { rsa_c[i][0] = rsa_c[i - 1][0] / 8; rsa_c[i][1] = rsa_c[i - 1][1] / 4; - if ((rsa_doit[i] <= 1) && (rsa_c[i][0] == 0)) + if (rsa_doit[i] <= 1 && rsa_c[i][0] == 0) rsa_doit[i] = 0; else { if (rsa_c[i][0] == 0) { - rsa_c[i][0] = 1; + rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */ rsa_c[i][1] = 20; } } } -# endif +# endif -# ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_DSA dsa_c[R_DSA_512][0] = count / 1000; dsa_c[R_DSA_512][1] = count / 1000 / 2; for (i = 1; i < DSA_NUM; i++) { dsa_c[i][0] = dsa_c[i - 1][0] / 4; dsa_c[i][1] = dsa_c[i - 1][1] / 4; - if ((dsa_doit[i] <= 1) && (dsa_c[i][0] == 0)) + if (dsa_doit[i] <= 1 && dsa_c[i][0] == 0) dsa_doit[i] = 0; else { - if (dsa_c[i] == 0) { - dsa_c[i][0] = 1; + if (dsa_c[i][0] == 0) { + dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */ dsa_c[i][1] = 1; } } } -# endif +# endif -# ifndef OPENSSL_NO_ECDSA +# ifndef OPENSSL_NO_EC ecdsa_c[R_EC_P160][0] = count / 1000; ecdsa_c[R_EC_P160][1] = count / 1000 / 2; for (i = R_EC_P192; i <= R_EC_P521; i++) { ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; - if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0)) + if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) ecdsa_doit[i] = 0; else { - if (ecdsa_c[i] == 0) { + if (ecdsa_c[i][0] == 0) { ecdsa_c[i][0] = 1; ecdsa_c[i][1] = 1; } @@ -1462,10 +2036,10 @@ int MAIN(int argc, char **argv) for (i = R_EC_K233; i <= R_EC_K571; i++) { ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; - if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0)) + if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) ecdsa_doit[i] = 0; else { - if (ecdsa_c[i] == 0) { + if (ecdsa_c[i][0] == 0) { ecdsa_c[i][0] = 1; ecdsa_c[i][1] = 1; } @@ -1476,1110 +2050,1363 @@ int MAIN(int argc, char **argv) for (i = R_EC_B233; i <= R_EC_B571; i++) { ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; - if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0)) + if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) ecdsa_doit[i] = 0; else { - if (ecdsa_c[i] == 0) { + if (ecdsa_c[i][0] == 0) { ecdsa_c[i][0] = 1; ecdsa_c[i][1] = 1; } } } -# endif -# ifndef OPENSSL_NO_ECDH ecdh_c[R_EC_P160][0] = count / 1000; - ecdh_c[R_EC_P160][1] = count / 1000; for (i = R_EC_P192; i <= R_EC_P521; i++) { ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; - ecdh_c[i][1] = ecdh_c[i - 1][1] / 2; - if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0)) + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) ecdh_doit[i] = 0; else { - if (ecdh_c[i] == 0) { + if (ecdh_c[i][0] == 0) { ecdh_c[i][0] = 1; - ecdh_c[i][1] = 1; } } } ecdh_c[R_EC_K163][0] = count / 1000; - ecdh_c[R_EC_K163][1] = count / 1000; for (i = R_EC_K233; i <= R_EC_K571; i++) { ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; - ecdh_c[i][1] = ecdh_c[i - 1][1] / 2; - if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0)) + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) ecdh_doit[i] = 0; else { - if (ecdh_c[i] == 0) { + if (ecdh_c[i][0] == 0) { ecdh_c[i][0] = 1; - ecdh_c[i][1] = 1; } } } ecdh_c[R_EC_B163][0] = count / 1000; - ecdh_c[R_EC_B163][1] = count / 1000; for (i = R_EC_B233; i <= R_EC_B571; i++) { ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; - ecdh_c[i][1] = ecdh_c[i - 1][1] / 2; - if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0)) + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) + ecdh_doit[i] = 0; + else { + if (ecdh_c[i][0] == 0) { + ecdh_c[i][0] = 1; + } + } + } + /* repeated code good to factorize */ + ecdh_c[R_EC_BRP256R1][0] = count / 1000; + for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) { + ecdh_c[i][0] = ecdh_c[i - 2][0] / 2; + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) ecdh_doit[i] = 0; else { - if (ecdh_c[i] == 0) { + if (ecdh_c[i][0] == 0) { ecdh_c[i][0] = 1; - ecdh_c[i][1] = 1; } } } -# endif + ecdh_c[R_EC_BRP256T1][0] = count / 1000; + for (i = R_EC_BRP384T1; i <= R_EC_BRP512T1; i += 2) { + ecdh_c[i][0] = ecdh_c[i - 2][0] / 2; + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) + ecdh_doit[i] = 0; + else { + if (ecdh_c[i][0] == 0) { + ecdh_c[i][0] = 1; + } + } + } + /* default iteration count for the last two EC Curves */ + ecdh_c[R_EC_X25519][0] = count / 1800; + ecdh_c[R_EC_X448][0] = count / 7200; -# define COND(d) (count < (d)) -# define COUNT(d) (d) -# else -/* not worth fixing */ -# error "You cannot disable DES on systems without SIGALRM." -# endif /* OPENSSL_NO_DES */ -# else -# define COND(c) (run && count<0x7fffffff) -# define COUNT(d) (count) -# ifndef _WIN32 - signal(SIGALRM, sig_done); + eddsa_c[R_EC_Ed25519][0] = count / 1800; + eddsa_c[R_EC_Ed448][0] = count / 7200; # endif -# endif /* SIGALRM */ -# ifndef OPENSSL_NO_MD2 +# else +/* not worth fixing */ +# error "You cannot disable DES on systems without SIGALRM." +# endif /* OPENSSL_NO_DES */ +#elif SIGALRM > 0 + signal(SIGALRM, alarmed); +#endif /* SIGALRM */ + +#ifndef OPENSSL_NO_MD2 if (doit[D_MD2]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_MD2], c[D_MD2][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_MD2][j]); count++) - EVP_Digest(buf, (unsigned long)lengths[j], &(md2[0]), NULL, - EVP_md2(), NULL); + count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs); d = Time_F(STOP); - print_result(D_MD2, j, count, d); + print_result(D_MD2, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_MDC2 +#endif +#ifndef OPENSSL_NO_MDC2 if (doit[D_MDC2]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_MDC2], c[D_MDC2][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_MDC2][j]); count++) - EVP_Digest(buf, (unsigned long)lengths[j], &(mdc2[0]), NULL, - EVP_mdc2(), NULL); + count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs); d = Time_F(STOP); - print_result(D_MDC2, j, count, d); + print_result(D_MDC2, testnum, count, d); } } -# endif +#endif -# ifndef OPENSSL_NO_MD4 +#ifndef OPENSSL_NO_MD4 if (doit[D_MD4]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_MD4], c[D_MD4][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_MD4][j]); count++) - EVP_Digest(&(buf[0]), (unsigned long)lengths[j], &(md4[0]), - NULL, EVP_md4(), NULL); + count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs); d = Time_F(STOP); - print_result(D_MD4, j, count, d); + print_result(D_MD4, testnum, count, d); } } -# endif +#endif -# ifndef OPENSSL_NO_MD5 +#ifndef OPENSSL_NO_MD5 if (doit[D_MD5]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_MD5], c[D_MD5][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_MD5][j]); count++) - EVP_Digest(&(buf[0]), (unsigned long)lengths[j], &(md5[0]), - NULL, EVP_get_digestbyname("md5"), NULL); + count = run_benchmark(async_jobs, MD5_loop, loopargs); d = Time_F(STOP); - print_result(D_MD5, j, count, d); + print_result(D_MD5, testnum, count, d); } } -# endif -# if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_HMAC) if (doit[D_HMAC]) { - HMAC_CTX hctx; + static const char hmac_key[] = "This is a key..."; + int len = strlen(hmac_key); - HMAC_CTX_init(&hctx); - HMAC_Init_ex(&hctx, (unsigned char *)"This is a key...", - 16, EVP_md5(), NULL); + for (i = 0; i < loopargs_len; i++) { + loopargs[i].hctx = HMAC_CTX_new(); + if (loopargs[i].hctx == NULL) { + BIO_printf(bio_err, "HMAC malloc failure, exiting..."); + exit(1); + } - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_HMAC], c[D_HMAC][j], lengths[j]); + HMAC_Init_ex(loopargs[i].hctx, hmac_key, len, EVP_md5(), NULL); + } + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_HMAC][j]); count++) { - HMAC_Init_ex(&hctx, NULL, 0, NULL, NULL); - HMAC_Update(&hctx, buf, lengths[j]); - HMAC_Final(&hctx, &(hmac[0]), NULL); - } + count = run_benchmark(async_jobs, HMAC_loop, loopargs); d = Time_F(STOP); - print_result(D_HMAC, j, count, d); + print_result(D_HMAC, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) { + HMAC_CTX_free(loopargs[i].hctx); } - HMAC_CTX_cleanup(&hctx); } -# endif -# ifndef OPENSSL_NO_SHA +#endif if (doit[D_SHA1]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_SHA1], c[D_SHA1][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_SHA1][j]); count++) - EVP_Digest(buf, (unsigned long)lengths[j], &(sha[0]), NULL, - EVP_sha1(), NULL); + count = run_benchmark(async_jobs, SHA1_loop, loopargs); d = Time_F(STOP); - print_result(D_SHA1, j, count, d); + print_result(D_SHA1, testnum, count, d); } } -# ifndef OPENSSL_NO_SHA256 if (doit[D_SHA256]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_SHA256], c[D_SHA256][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_SHA256], c[D_SHA256][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_SHA256][j]); count++) - SHA256(buf, lengths[j], sha256); + count = run_benchmark(async_jobs, SHA256_loop, loopargs); d = Time_F(STOP); - print_result(D_SHA256, j, count, d); + print_result(D_SHA256, testnum, count, d); } } -# endif - -# ifndef OPENSSL_NO_SHA512 if (doit[D_SHA512]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_SHA512], c[D_SHA512][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_SHA512], c[D_SHA512][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_SHA512][j]); count++) - SHA512(buf, lengths[j], sha512); + count = run_benchmark(async_jobs, SHA512_loop, loopargs); d = Time_F(STOP); - print_result(D_SHA512, j, count, d); + print_result(D_SHA512, testnum, count, d); } } -# endif -# endif - -# ifndef OPENSSL_NO_WHIRLPOOL +#ifndef OPENSSL_NO_WHIRLPOOL if (doit[D_WHIRLPOOL]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_WHIRLPOOL][j]); count++) - WHIRLPOOL(buf, lengths[j], whirlpool); + count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs); d = Time_F(STOP); - print_result(D_WHIRLPOOL, j, count, d); + print_result(D_WHIRLPOOL, testnum, count, d); } } -# endif +#endif -# ifndef OPENSSL_NO_RIPEMD +#ifndef OPENSSL_NO_RMD160 if (doit[D_RMD160]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_RMD160], c[D_RMD160][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_RMD160], c[D_RMD160][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_RMD160][j]); count++) - EVP_Digest(buf, (unsigned long)lengths[j], &(rmd160[0]), NULL, - EVP_ripemd160(), NULL); + count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs); d = Time_F(STOP); - print_result(D_RMD160, j, count, d); + print_result(D_RMD160, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_RC4 +#endif +#ifndef OPENSSL_NO_RC4 if (doit[D_RC4]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_RC4], c[D_RC4][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_RC4][j]); count++) - RC4(&rc4_ks, (unsigned int)lengths[j], buf, buf); + count = run_benchmark(async_jobs, RC4_loop, loopargs); d = Time_F(STOP); - print_result(D_RC4, j, count, d); + print_result(D_RC4, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_DES +#endif +#ifndef OPENSSL_NO_DES if (doit[D_CBC_DES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_DES], c[D_CBC_DES][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_DES], c[D_CBC_DES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_DES][j]); count++) - DES_ncbc_encrypt(buf, buf, lengths[j], &sch, - &DES_iv, DES_ENCRYPT); + count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_CBC_DES, j, count, d); + print_result(D_CBC_DES, testnum, count, d); } } if (doit[D_EDE3_DES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_EDE3_DES], c[D_EDE3_DES][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_EDE3_DES][j]); count++) - DES_ede3_cbc_encrypt(buf, buf, lengths[j], - &sch, &sch2, &sch3, - &DES_iv, DES_ENCRYPT); + count = + run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_EDE3_DES, j, count, d); + print_result(D_EDE3_DES, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_AES +#endif + if (doit[D_CBC_128_AES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][j], - lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_128_AES][j]); count++) - AES_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &aes_ks1, - iv, AES_ENCRYPT); + count = + run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_CBC_128_AES, j, count, d); + print_result(D_CBC_128_AES, testnum, count, d); } } if (doit[D_CBC_192_AES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][j], - lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_192_AES][j]); count++) - AES_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &aes_ks2, - iv, AES_ENCRYPT); + count = + run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_CBC_192_AES, j, count, d); + print_result(D_CBC_192_AES, testnum, count, d); } } if (doit[D_CBC_256_AES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][j], - lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_256_AES][j]); count++) - AES_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &aes_ks3, - iv, AES_ENCRYPT); + count = + run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_CBC_256_AES, j, count, d); + print_result(D_CBC_256_AES, testnum, count, d); } } if (doit[D_IGE_128_AES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][j], - lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_IGE_128_AES][j]); count++) - AES_ige_encrypt(buf, buf2, - (unsigned long)lengths[j], &aes_ks1, - iv, AES_ENCRYPT); + count = + run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_IGE_128_AES, j, count, d); + print_result(D_IGE_128_AES, testnum, count, d); } } if (doit[D_IGE_192_AES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][j], - lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_IGE_192_AES][j]); count++) - AES_ige_encrypt(buf, buf2, - (unsigned long)lengths[j], &aes_ks2, - iv, AES_ENCRYPT); + count = + run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_IGE_192_AES, j, count, d); + print_result(D_IGE_192_AES, testnum, count, d); } } if (doit[D_IGE_256_AES]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][j], - lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_IGE_256_AES][j]); count++) - AES_ige_encrypt(buf, buf2, - (unsigned long)lengths[j], &aes_ks3, - iv, AES_ENCRYPT); + count = + run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs); d = Time_F(STOP); - print_result(D_IGE_256_AES, j, count, d); + print_result(D_IGE_256_AES, testnum, count, d); } } if (doit[D_GHASH]) { - GCM128_CONTEXT *ctx = - CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt); - CRYPTO_gcm128_setiv(ctx, (unsigned char *)"0123456789ab", 12); + for (i = 0; i < loopargs_len; i++) { + loopargs[i].gcm_ctx = + CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt); + CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx, + (unsigned char *)"0123456789ab", 12); + } - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_GHASH], c[D_GHASH][j], lengths[j]); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_GHASH], c[D_GHASH][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_GHASH][j]); count++) - CRYPTO_gcm128_aad(ctx, buf, lengths[j]); + count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs); d = Time_F(STOP); - print_result(D_GHASH, j, count, d); + print_result(D_GHASH, testnum, count, d); } - CRYPTO_gcm128_release(ctx); + for (i = 0; i < loopargs_len; i++) + CRYPTO_gcm128_release(loopargs[i].gcm_ctx); } -# endif -# ifndef OPENSSL_NO_CAMELLIA +#ifndef OPENSSL_NO_CAMELLIA if (doit[D_CBC_128_CML]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][j], - lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_128_CML]); + doit[D_CBC_128_CML] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_128_CML][j]); count++) - Camellia_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &camellia_ks1, + for (count = 0, run = 1; COND(c[D_CBC_128_CML][testnum]); count++) + Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &camellia_ks1, iv, CAMELLIA_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_128_CML, j, count, d); + print_result(D_CBC_128_CML, testnum, count, d); } } if (doit[D_CBC_192_CML]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][j], - lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_192_CML]); + doit[D_CBC_192_CML] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][testnum], + lengths[testnum], seconds.sym); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported, exiting..."); + exit(1); + } Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_192_CML][j]); count++) - Camellia_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &camellia_ks2, + for (count = 0, run = 1; COND(c[D_CBC_192_CML][testnum]); count++) + Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &camellia_ks2, iv, CAMELLIA_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_192_CML, j, count, d); + print_result(D_CBC_192_CML, testnum, count, d); } } if (doit[D_CBC_256_CML]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][j], - lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_256_CML]); + doit[D_CBC_256_CML] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_256_CML][j]); count++) - Camellia_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &camellia_ks3, + for (count = 0, run = 1; COND(c[D_CBC_256_CML][testnum]); count++) + Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &camellia_ks3, iv, CAMELLIA_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_256_CML, j, count, d); + print_result(D_CBC_256_CML, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_IDEA +#endif +#ifndef OPENSSL_NO_IDEA if (doit[D_CBC_IDEA]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][j], lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_IDEA]); + doit[D_CBC_IDEA] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_IDEA][j]); count++) - idea_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &idea_ks, + for (count = 0, run = 1; COND(c[D_CBC_IDEA][testnum]); count++) + IDEA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &idea_ks, iv, IDEA_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_IDEA, j, count, d); + print_result(D_CBC_IDEA, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_SEED +#endif +#ifndef OPENSSL_NO_SEED if (doit[D_CBC_SEED]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_SEED], c[D_CBC_SEED][j], lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_SEED]); + doit[D_CBC_SEED] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_SEED][j]); count++) - SEED_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &seed_ks, iv, 1); + for (count = 0, run = 1; COND(c[D_CBC_SEED][testnum]); count++) + SEED_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &seed_ks, iv, 1); d = Time_F(STOP); - print_result(D_CBC_SEED, j, count, d); + print_result(D_CBC_SEED, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_RC2 +#endif +#ifndef OPENSSL_NO_RC2 if (doit[D_CBC_RC2]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_RC2], c[D_CBC_RC2][j], lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_RC2]); + doit[D_CBC_RC2] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum], + lengths[testnum], seconds.sym); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported, exiting..."); + exit(1); + } Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_RC2][j]); count++) - RC2_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &rc2_ks, + for (count = 0, run = 1; COND(c[D_CBC_RC2][testnum]); count++) + RC2_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &rc2_ks, iv, RC2_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_RC2, j, count, d); + print_result(D_CBC_RC2, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_RC5 +#endif +#ifndef OPENSSL_NO_RC5 if (doit[D_CBC_RC5]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_RC5], c[D_CBC_RC5][j], lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_RC5]); + doit[D_CBC_RC5] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum], + lengths[testnum], seconds.sym); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported, exiting..."); + exit(1); + } Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_RC5][j]); count++) - RC5_32_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &rc5_ks, + for (count = 0, run = 1; COND(c[D_CBC_RC5][testnum]); count++) + RC5_32_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &rc5_ks, iv, RC5_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_RC5, j, count, d); + print_result(D_CBC_RC5, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_BF +#endif +#ifndef OPENSSL_NO_BF if (doit[D_CBC_BF]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_BF], c[D_CBC_BF][j], lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_BF]); + doit[D_CBC_BF] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_BF], c[D_CBC_BF][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_BF][j]); count++) - BF_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &bf_ks, + for (count = 0, run = 1; COND(c[D_CBC_BF][testnum]); count++) + BF_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &bf_ks, iv, BF_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_BF, j, count, d); + print_result(D_CBC_BF, testnum, count, d); } } -# endif -# ifndef OPENSSL_NO_CAST +#endif +#ifndef OPENSSL_NO_CAST if (doit[D_CBC_CAST]) { - for (j = 0; j < SIZE_NUM; j++) { - print_message(names[D_CBC_CAST], c[D_CBC_CAST][j], lengths[j]); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_CAST]); + doit[D_CBC_CAST] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum], + lengths[testnum], seconds.sym); Time_F(START); - for (count = 0, run = 1; COND(c[D_CBC_CAST][j]); count++) - CAST_cbc_encrypt(buf, buf, - (unsigned long)lengths[j], &cast_ks, + for (count = 0, run = 1; COND(c[D_CBC_CAST][testnum]); count++) + CAST_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &cast_ks, iv, CAST_ENCRYPT); d = Time_F(STOP); - print_result(D_CBC_CAST, j, count, d); + print_result(D_CBC_CAST, testnum, count, d); + } + } +#endif + if (doit[D_RAND]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, RAND_bytes_loop, loopargs); + d = Time_F(STOP); + print_result(D_RAND, testnum, count, d); } } -# endif if (doit[D_EVP]) { -# ifdef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK - if (multiblock && evp_cipher) { - if (! - (EVP_CIPHER_flags(evp_cipher) & - EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) { - fprintf(stderr, "%s is not multi-block capable\n", - OBJ_nid2ln(evp_cipher->nid)); + if (evp_cipher != NULL) { + int (*loopfunc)(void *args) = EVP_Update_loop; + + if (multiblock && (EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) { + multiblock_speed(evp_cipher, lengths_single, &seconds); + ret = 0; goto end; } - multiblock_speed(evp_cipher); - mret = 0; - goto end; - } -# endif - for (j = 0; j < SIZE_NUM; j++) { - if (evp_cipher) { - EVP_CIPHER_CTX ctx; - int outl; - names[D_EVP] = OBJ_nid2ln(evp_cipher->nid); - /* - * -O3 -fschedule-insns messes up an optimization here! - * names[D_EVP] somehow becomes NULL - */ - print_message(names[D_EVP], save_count, lengths[j]); + names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)); + + if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) { + loopfunc = EVP_Update_loop_ccm; + } else if (aead && (EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_AEAD_CIPHER)) { + loopfunc = EVP_Update_loop_aead; + if (lengths == lengths_list) { + lengths = aead_lengths_list; + size_num = OSSL_NELEM(aead_lengths_list); + } + } + + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_EVP], save_count, lengths[testnum], + seconds.sym); + + for (k = 0; k < loopargs_len; k++) { + loopargs[k].ctx = EVP_CIPHER_CTX_new(); + EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, NULL, + iv, decrypt ? 0 : 1); - EVP_CIPHER_CTX_init(&ctx); - if (decrypt) - EVP_DecryptInit_ex(&ctx, evp_cipher, NULL, key16, iv); - else - EVP_EncryptInit_ex(&ctx, evp_cipher, NULL, key16, iv); - EVP_CIPHER_CTX_set_padding(&ctx, 0); + EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0); + + keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx); + loopargs[k].key = app_malloc(keylen, "evp_cipher key"); + EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key); + EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL, + loopargs[k].key, NULL, -1); + OPENSSL_clear_free(loopargs[k].key, keylen); + } Time_F(START); - if (decrypt) - for (count = 0, run = 1; - COND(save_count * 4 * lengths[0] / lengths[j]); - count++) - EVP_DecryptUpdate(&ctx, buf, &outl, buf, lengths[j]); - else - for (count = 0, run = 1; - COND(save_count * 4 * lengths[0] / lengths[j]); - count++) - EVP_EncryptUpdate(&ctx, buf, &outl, buf, lengths[j]); - if (decrypt) - EVP_DecryptFinal_ex(&ctx, buf, &outl); - else - EVP_EncryptFinal_ex(&ctx, buf, &outl); + count = run_benchmark(async_jobs, loopfunc, loopargs); d = Time_F(STOP); - EVP_CIPHER_CTX_cleanup(&ctx); + for (k = 0; k < loopargs_len; k++) { + EVP_CIPHER_CTX_free(loopargs[k].ctx); + } + print_result(D_EVP, testnum, count, d); } - if (evp_md) { - names[D_EVP] = OBJ_nid2ln(evp_md->type); - print_message(names[D_EVP], save_count, lengths[j]); + } else if (evp_md != NULL) { + names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md)); + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_EVP], save_count, lengths[testnum], + seconds.sym); Time_F(START); - for (count = 0, run = 1; - COND(save_count * 4 * lengths[0] / lengths[j]); count++) - EVP_Digest(buf, lengths[j], &(md[0]), NULL, evp_md, NULL); - + count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs); d = Time_F(STOP); + print_result(D_EVP, testnum, count, d); } - print_result(D_EVP, j, count, d); } } - RAND_pseudo_bytes(buf, 36); -# ifndef OPENSSL_NO_RSA - for (j = 0; j < RSA_NUM; j++) { - int ret; - if (!rsa_doit[j]) + for (i = 0; i < loopargs_len; i++) + if (RAND_bytes(loopargs[i].buf, 36) <= 0) + goto end; + +#ifndef OPENSSL_NO_RSA + for (testnum = 0; testnum < RSA_NUM; testnum++) { + int st = 0; + if (!rsa_doit[testnum]) continue; - ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, &rsa_num, rsa_key[j]); - if (ret == 0) { + for (i = 0; i < loopargs_len; i++) { + if (primes > 2) { + /* we haven't set keys yet, generate multi-prime RSA keys */ + BIGNUM *bn = BN_new(); + + if (bn == NULL) + goto end; + if (!BN_set_word(bn, RSA_F4)) { + BN_free(bn); + goto end; + } + + BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n", + rsa_choices[testnum].name); + + loopargs[i].rsa_key[testnum] = RSA_new(); + if (loopargs[i].rsa_key[testnum] == NULL) { + BN_free(bn); + goto end; + } + + if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum], + rsa_bits[testnum], + primes, bn, NULL)) { + BN_free(bn); + goto end; + } + BN_free(bn); + } + st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2, + &loopargs[i].siglen, loopargs[i].rsa_key[testnum]); + if (st == 0) + break; + } + if (st == 0) { BIO_printf(bio_err, "RSA sign failure. No RSA sign will be done.\n"); ERR_print_errors(bio_err); rsa_count = 1; } else { pkey_print_message("private", "rsa", - rsa_c[j][0], rsa_bits[j], RSA_SECONDS); - /* RSA_blinding_on(rsa_key[j],NULL); */ + rsa_c[testnum][0], rsa_bits[testnum], + seconds.rsa); + /* RSA_blinding_on(rsa_key[testnum],NULL); */ Time_F(START); - for (count = 0, run = 1; COND(rsa_c[j][0]); count++) { - ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, - &rsa_num, rsa_key[j]); - if (ret == 0) { - BIO_printf(bio_err, "RSA sign failure\n"); - ERR_print_errors(bio_err); - count = 1; - break; - } - } + count = run_benchmark(async_jobs, RSA_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, mr ? "+R1:%ld:%d:%.2f\n" - : "%ld %d bit private RSA's in %.2fs\n", - count, rsa_bits[j], d); - rsa_results[j][0] = d / (double)count; + : "%ld %u bits private RSA's in %.2fs\n", + count, rsa_bits[testnum], d); + rsa_results[testnum][0] = (double)count / d; rsa_count = count; } -# if 1 - ret = RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[j]); - if (ret <= 0) { + for (i = 0; i < loopargs_len; i++) { + st = RSA_verify(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2, + loopargs[i].siglen, loopargs[i].rsa_key[testnum]); + if (st <= 0) + break; + } + if (st <= 0) { BIO_printf(bio_err, "RSA verify failure. No RSA verify will be done.\n"); ERR_print_errors(bio_err); - rsa_doit[j] = 0; + rsa_doit[testnum] = 0; } else { pkey_print_message("public", "rsa", - rsa_c[j][1], rsa_bits[j], RSA_SECONDS); + rsa_c[testnum][1], rsa_bits[testnum], + seconds.rsa); Time_F(START); - for (count = 0, run = 1; COND(rsa_c[j][1]); count++) { - ret = RSA_verify(NID_md5_sha1, buf, 36, buf2, - rsa_num, rsa_key[j]); - if (ret <= 0) { - BIO_printf(bio_err, "RSA verify failure\n"); - ERR_print_errors(bio_err); - count = 1; - break; - } - } + count = run_benchmark(async_jobs, RSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, mr ? "+R2:%ld:%d:%.2f\n" - : "%ld %d bit public RSA's in %.2fs\n", - count, rsa_bits[j], d); - rsa_results[j][1] = d / (double)count; + : "%ld %u bits public RSA's in %.2fs\n", + count, rsa_bits[testnum], d); + rsa_results[testnum][1] = (double)count / d; } -# endif if (rsa_count <= 1) { /* if longer than 10s, don't do any more */ - for (j++; j < RSA_NUM; j++) - rsa_doit[j] = 0; + for (testnum++; testnum < RSA_NUM; testnum++) + rsa_doit[testnum] = 0; } } -# endif +#endif /* OPENSSL_NO_RSA */ - RAND_pseudo_bytes(buf, 20); -# ifndef OPENSSL_NO_DSA - if (RAND_status() != 1) { - RAND_seed(rnd_seed, sizeof(rnd_seed)); - rnd_fake = 1; - } - for (j = 0; j < DSA_NUM; j++) { - unsigned int kk; - int ret; + for (i = 0; i < loopargs_len; i++) + if (RAND_bytes(loopargs[i].buf, 36) <= 0) + goto end; - if (!dsa_doit[j]) +#ifndef OPENSSL_NO_DSA + for (testnum = 0; testnum < DSA_NUM; testnum++) { + int st = 0; + if (!dsa_doit[testnum]) continue; - /* DSA_generate_key(dsa_key[j]); */ - /* DSA_sign_setup(dsa_key[j],NULL); */ - ret = DSA_sign(EVP_PKEY_DSA, buf, 20, buf2, &kk, dsa_key[j]); - if (ret == 0) { + /* DSA_generate_key(dsa_key[testnum]); */ + /* DSA_sign_setup(dsa_key[testnum],NULL); */ + for (i = 0; i < loopargs_len; i++) { + st = DSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2, + &loopargs[i].siglen, loopargs[i].dsa_key[testnum]); + if (st == 0) + break; + } + if (st == 0) { BIO_printf(bio_err, "DSA sign failure. No DSA sign will be done.\n"); ERR_print_errors(bio_err); rsa_count = 1; } else { pkey_print_message("sign", "dsa", - dsa_c[j][0], dsa_bits[j], DSA_SECONDS); + dsa_c[testnum][0], dsa_bits[testnum], + seconds.dsa); Time_F(START); - for (count = 0, run = 1; COND(dsa_c[j][0]); count++) { - ret = DSA_sign(EVP_PKEY_DSA, buf, 20, buf2, &kk, dsa_key[j]); - if (ret == 0) { - BIO_printf(bio_err, "DSA sign failure\n"); - ERR_print_errors(bio_err); - count = 1; - break; - } - } + count = run_benchmark(async_jobs, DSA_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R3:%ld:%d:%.2f\n" - : "%ld %d bit DSA signs in %.2fs\n", - count, dsa_bits[j], d); - dsa_results[j][0] = d / (double)count; + mr ? "+R3:%ld:%u:%.2f\n" + : "%ld %u bits DSA signs in %.2fs\n", + count, dsa_bits[testnum], d); + dsa_results[testnum][0] = (double)count / d; rsa_count = count; } - ret = DSA_verify(EVP_PKEY_DSA, buf, 20, buf2, kk, dsa_key[j]); - if (ret <= 0) { + for (i = 0; i < loopargs_len; i++) { + st = DSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2, + loopargs[i].siglen, loopargs[i].dsa_key[testnum]); + if (st <= 0) + break; + } + if (st <= 0) { BIO_printf(bio_err, "DSA verify failure. No DSA verify will be done.\n"); ERR_print_errors(bio_err); - dsa_doit[j] = 0; + dsa_doit[testnum] = 0; } else { pkey_print_message("verify", "dsa", - dsa_c[j][1], dsa_bits[j], DSA_SECONDS); + dsa_c[testnum][1], dsa_bits[testnum], + seconds.dsa); Time_F(START); - for (count = 0, run = 1; COND(dsa_c[j][1]); count++) { - ret = DSA_verify(EVP_PKEY_DSA, buf, 20, buf2, kk, dsa_key[j]); - if (ret <= 0) { - BIO_printf(bio_err, "DSA verify failure\n"); - ERR_print_errors(bio_err); - count = 1; - break; - } - } + count = run_benchmark(async_jobs, DSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R4:%ld:%d:%.2f\n" - : "%ld %d bit DSA verify in %.2fs\n", - count, dsa_bits[j], d); - dsa_results[j][1] = d / (double)count; + mr ? "+R4:%ld:%u:%.2f\n" + : "%ld %u bits DSA verify in %.2fs\n", + count, dsa_bits[testnum], d); + dsa_results[testnum][1] = (double)count / d; } if (rsa_count <= 1) { /* if longer than 10s, don't do any more */ - for (j++; j < DSA_NUM; j++) - dsa_doit[j] = 0; + for (testnum++; testnum < DSA_NUM; testnum++) + dsa_doit[testnum] = 0; } } - if (rnd_fake) - RAND_cleanup(); -# endif +#endif /* OPENSSL_NO_DSA */ -# ifndef OPENSSL_NO_ECDSA - if (RAND_status() != 1) { - RAND_seed(rnd_seed, sizeof(rnd_seed)); - rnd_fake = 1; - } - for (j = 0; j < EC_NUM; j++) { - int ret; +#ifndef OPENSSL_NO_EC + for (testnum = 0; testnum < ECDSA_NUM; testnum++) { + int st = 1; - if (!ecdsa_doit[j]) + if (!ecdsa_doit[testnum]) continue; /* Ignore Curve */ - ecdsa[j] = EC_KEY_new_by_curve_name(test_curves[j]); - if (ecdsa[j] == NULL) { + for (i = 0; i < loopargs_len; i++) { + loopargs[i].ecdsa[testnum] = + EC_KEY_new_by_curve_name(test_curves[testnum].nid); + if (loopargs[i].ecdsa[testnum] == NULL) { + st = 0; + break; + } + } + if (st == 0) { BIO_printf(bio_err, "ECDSA failure.\n"); ERR_print_errors(bio_err); rsa_count = 1; } else { -# if 1 - EC_KEY_precompute_mult(ecdsa[j], NULL); -# endif - /* Perform ECDSA signature test */ - EC_KEY_generate_key(ecdsa[j]); - ret = ECDSA_sign(0, buf, 20, ecdsasig, &ecdsasiglen, ecdsa[j]); - if (ret == 0) { + for (i = 0; i < loopargs_len; i++) { + EC_KEY_precompute_mult(loopargs[i].ecdsa[testnum], NULL); + /* Perform ECDSA signature test */ + EC_KEY_generate_key(loopargs[i].ecdsa[testnum]); + st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2, + &loopargs[i].siglen, + loopargs[i].ecdsa[testnum]); + if (st == 0) + break; + } + if (st == 0) { BIO_printf(bio_err, "ECDSA sign failure. No ECDSA sign will be done.\n"); ERR_print_errors(bio_err); rsa_count = 1; } else { pkey_print_message("sign", "ecdsa", - ecdsa_c[j][0], - test_curves_bits[j], ECDSA_SECONDS); - + ecdsa_c[testnum][0], + test_curves[testnum].bits, seconds.ecdsa); Time_F(START); - for (count = 0, run = 1; COND(ecdsa_c[j][0]); count++) { - ret = ECDSA_sign(0, buf, 20, - ecdsasig, &ecdsasiglen, ecdsa[j]); - if (ret == 0) { - BIO_printf(bio_err, "ECDSA sign failure\n"); - ERR_print_errors(bio_err); - count = 1; - break; - } - } + count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R5:%ld:%d:%.2f\n" : - "%ld %d bit ECDSA signs in %.2fs \n", - count, test_curves_bits[j], d); - ecdsa_results[j][0] = d / (double)count; + mr ? "+R5:%ld:%u:%.2f\n" : + "%ld %u bits ECDSA signs in %.2fs \n", + count, test_curves[testnum].bits, d); + ecdsa_results[testnum][0] = (double)count / d; rsa_count = count; } /* Perform ECDSA verification test */ - ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[j]); - if (ret != 1) { + for (i = 0; i < loopargs_len; i++) { + st = ECDSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2, + loopargs[i].siglen, + loopargs[i].ecdsa[testnum]); + if (st != 1) + break; + } + if (st != 1) { BIO_printf(bio_err, "ECDSA verify failure. No ECDSA verify will be done.\n"); ERR_print_errors(bio_err); - ecdsa_doit[j] = 0; + ecdsa_doit[testnum] = 0; } else { pkey_print_message("verify", "ecdsa", - ecdsa_c[j][1], - test_curves_bits[j], ECDSA_SECONDS); + ecdsa_c[testnum][1], + test_curves[testnum].bits, seconds.ecdsa); Time_F(START); - for (count = 0, run = 1; COND(ecdsa_c[j][1]); count++) { - ret = - ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, - ecdsa[j]); - if (ret != 1) { - BIO_printf(bio_err, "ECDSA verify failure\n"); - ERR_print_errors(bio_err); - count = 1; - break; - } - } + count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R6:%ld:%d:%.2f\n" - : "%ld %d bit ECDSA verify in %.2fs\n", - count, test_curves_bits[j], d); - ecdsa_results[j][1] = d / (double)count; + mr ? "+R6:%ld:%u:%.2f\n" + : "%ld %u bits ECDSA verify in %.2fs\n", + count, test_curves[testnum].bits, d); + ecdsa_results[testnum][1] = (double)count / d; } if (rsa_count <= 1) { /* if longer than 10s, don't do any more */ - for (j++; j < EC_NUM; j++) - ecdsa_doit[j] = 0; + for (testnum++; testnum < EC_NUM; testnum++) + ecdsa_doit[testnum] = 0; } } } - if (rnd_fake) - RAND_cleanup(); -# endif -# ifndef OPENSSL_NO_ECDH - if (RAND_status() != 1) { - RAND_seed(rnd_seed, sizeof(rnd_seed)); - rnd_fake = 1; - } - for (j = 0; j < EC_NUM; j++) { - if (!ecdh_doit[j]) + for (testnum = 0; testnum < EC_NUM; testnum++) { + int ecdh_checks = 1; + + if (!ecdh_doit[testnum]) continue; - ecdh_a[j] = EC_KEY_new_by_curve_name(test_curves[j]); - ecdh_b[j] = EC_KEY_new_by_curve_name(test_curves[j]); - if ((ecdh_a[j] == NULL) || (ecdh_b[j] == NULL)) { - BIO_printf(bio_err, "ECDH failure.\n"); - ERR_print_errors(bio_err); - rsa_count = 1; - } else { - /* generate two ECDH key pairs */ - if (!EC_KEY_generate_key(ecdh_a[j]) || - !EC_KEY_generate_key(ecdh_b[j])) { - BIO_printf(bio_err, "ECDH key generation failure.\n"); + + for (i = 0; i < loopargs_len; i++) { + EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY_CTX *test_ctx = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *key_A = NULL; + EVP_PKEY *key_B = NULL; + size_t outlen; + size_t test_outlen; + + /* Ensure that the error queue is empty */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "WARNING: the error queue contains previous unhandled errors.\n"); ERR_print_errors(bio_err); - rsa_count = 1; - } else { - /* - * If field size is not more than 24 octets, then use SHA-1 - * hash of result; otherwise, use result (see section 4.8 of - * draft-ietf-tls-ecc-03.txt). - */ - int field_size, outlen; - void *(*kdf) (const void *in, size_t inlen, void *out, - size_t *xoutlen); - field_size = - EC_GROUP_get_degree(EC_KEY_get0_group(ecdh_a[j])); - if (field_size <= 24 * 8) { - outlen = KDF1_SHA1_len; - kdf = KDF1_SHA1; - } else { - outlen = (field_size + 7) / 8; - kdf = NULL; - } - secret_size_a = - ECDH_compute_key(secret_a, outlen, - EC_KEY_get0_public_key(ecdh_b[j]), - ecdh_a[j], kdf); - secret_size_b = - ECDH_compute_key(secret_b, outlen, - EC_KEY_get0_public_key(ecdh_a[j]), - ecdh_b[j], kdf); - if (secret_size_a != secret_size_b) - ecdh_checks = 0; - else - ecdh_checks = 1; + } + + /* Let's try to create a ctx directly from the NID: this works for + * curves like Curve25519 that are not implemented through the low + * level EC interface. + * If this fails we try creating a EVP_PKEY_EC generic param ctx, + * then we set the curve by NID before deriving the actual keygen + * ctx for that specific curve. */ + kctx = EVP_PKEY_CTX_new_id(test_curves[testnum].nid, NULL); /* keygen ctx from NID */ + if (!kctx) { + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *params = NULL; - for (secret_idx = 0; (secret_idx < secret_size_a) - && (ecdh_checks == 1); secret_idx++) { - if (secret_a[secret_idx] != secret_b[secret_idx]) - ecdh_checks = 0; + /* If we reach this code EVP_PKEY_CTX_new_id() failed and a + * "int_ctx_new:unsupported algorithm" error was added to the + * error queue. + * We remove it from the error queue as we are handling it. */ + unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */ + if (error == ERR_peek_last_error() && /* oldest and latest errors match */ + /* check that the error origin matches */ + ERR_GET_LIB(error) == ERR_LIB_EVP && + ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW && + ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM) + ERR_get_error(); /* pop error from queue */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "Unhandled error in the error queue during ECDH init.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; } - if (ecdh_checks == 0) { - BIO_printf(bio_err, "ECDH computations don't match.\n"); + if ( /* Create the context for parameter generation */ + !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) || + /* Initialise the parameter generation */ + !EVP_PKEY_paramgen_init(pctx) || + /* Set the curve by NID */ + !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, + test_curves + [testnum].nid) || + /* Create the parameter object params */ + !EVP_PKEY_paramgen(pctx, ¶ms)) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH EC params init failure.\n"); ERR_print_errors(bio_err); rsa_count = 1; + break; } + /* Create the context for the key generation */ + kctx = EVP_PKEY_CTX_new(params, NULL); + + EVP_PKEY_free(params); + params = NULL; + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + } + if (kctx == NULL || /* keygen ctx is not null */ + !EVP_PKEY_keygen_init(kctx) /* init keygen ctx */ ) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH keygen failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + if (!EVP_PKEY_keygen(kctx, &key_A) || /* generate secret key A */ + !EVP_PKEY_keygen(kctx, &key_B) || /* generate secret key B */ + !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */ + !EVP_PKEY_derive_init(ctx) || /* init derivation ctx */ + !EVP_PKEY_derive_set_peer(ctx, key_B) || /* set peer pubkey in ctx */ + !EVP_PKEY_derive(ctx, NULL, &outlen) || /* determine max length */ + outlen == 0 || /* ensure outlen is a valid size */ + outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH key generation failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + /* Here we perform a test run, comparing the output of a*B and b*A; + * we try this here and assume that further EVP_PKEY_derive calls + * never fail, so we can skip checks in the actually benchmarked + * code, for maximum performance. */ + if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */ + !EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */ + !EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */ + !EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */ + !EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */ + !EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */ + test_outlen != outlen /* compare output length */ ) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH computation failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } - pkey_print_message("", "ecdh", - ecdh_c[j][0], - test_curves_bits[j], ECDH_SECONDS); + /* Compare the computation results: CRYPTO_memcmp() returns 0 if equal */ + if (CRYPTO_memcmp(loopargs[i].secret_a, + loopargs[i].secret_b, outlen)) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH computations don't match.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + loopargs[i].ecdh_ctx[testnum] = ctx; + loopargs[i].outlen[testnum] = outlen; + + EVP_PKEY_free(key_A); + EVP_PKEY_free(key_B); + EVP_PKEY_CTX_free(kctx); + kctx = NULL; + EVP_PKEY_CTX_free(test_ctx); + test_ctx = NULL; + } + if (ecdh_checks != 0) { + pkey_print_message("", "ecdh", + ecdh_c[testnum][0], + test_curves[testnum].bits, seconds.ecdh); + Time_F(START); + count = + run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R7:%ld:%d:%.2f\n" : + "%ld %u-bits ECDH ops in %.2fs\n", count, + test_curves[testnum].bits, d); + ecdh_results[testnum][0] = (double)count / d; + rsa_count = count; + } + + if (rsa_count <= 1) { + /* if longer than 10s, don't do any more */ + for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++) + ecdh_doit[testnum] = 0; + } + } + + for (testnum = 0; testnum < EdDSA_NUM; testnum++) { + int st = 1; + EVP_PKEY *ed_pkey = NULL; + EVP_PKEY_CTX *ed_pctx = NULL; + + if (!eddsa_doit[testnum]) + continue; /* Ignore Curve */ + for (i = 0; i < loopargs_len; i++) { + loopargs[i].eddsa_ctx[testnum] = EVP_MD_CTX_new(); + if (loopargs[i].eddsa_ctx[testnum] == NULL) { + st = 0; + break; + } + + if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL)) + == NULL + || !EVP_PKEY_keygen_init(ed_pctx) + || !EVP_PKEY_keygen(ed_pctx, &ed_pkey)) { + st = 0; + EVP_PKEY_CTX_free(ed_pctx); + break; + } + EVP_PKEY_CTX_free(ed_pctx); + + if (!EVP_DigestSignInit(loopargs[i].eddsa_ctx[testnum], NULL, NULL, + NULL, ed_pkey)) { + st = 0; + EVP_PKEY_free(ed_pkey); + break; + } + EVP_PKEY_free(ed_pkey); + } + if (st == 0) { + BIO_printf(bio_err, "EdDSA failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + for (i = 0; i < loopargs_len; i++) { + /* Perform EdDSA signature test */ + loopargs[i].sigsize = test_ed_curves[testnum].sigsize; + st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum], + loopargs[i].buf2, &loopargs[i].sigsize, + loopargs[i].buf, 20); + if (st == 0) + break; + } + if (st == 0) { + BIO_printf(bio_err, + "EdDSA sign failure. No EdDSA sign will be done.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + pkey_print_message("sign", test_ed_curves[testnum].name, + eddsa_c[testnum][0], + test_ed_curves[testnum].bits, seconds.eddsa); Time_F(START); - for (count = 0, run = 1; COND(ecdh_c[j][0]); count++) { - ECDH_compute_key(secret_a, outlen, - EC_KEY_get0_public_key(ecdh_b[j]), - ecdh_a[j], kdf); - } + count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs); d = Time_F(STOP); + BIO_printf(bio_err, - mr ? "+R7:%ld:%d:%.2f\n" : - "%ld %d-bit ECDH ops in %.2fs\n", count, - test_curves_bits[j], d); - ecdh_results[j][0] = d / (double)count; + mr ? "+R8:%ld:%u:%s:%.2f\n" : + "%ld %u bits %s signs in %.2fs \n", + count, test_ed_curves[testnum].bits, + test_ed_curves[testnum].name, d); + eddsa_results[testnum][0] = (double)count / d; rsa_count = count; } - } - if (rsa_count <= 1) { - /* if longer than 10s, don't do any more */ - for (j++; j < EC_NUM; j++) - ecdh_doit[j] = 0; + /* Perform EdDSA verification test */ + for (i = 0; i < loopargs_len; i++) { + st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum], + loopargs[i].buf2, loopargs[i].sigsize, + loopargs[i].buf, 20); + if (st != 1) + break; + } + if (st != 1) { + BIO_printf(bio_err, + "EdDSA verify failure. No EdDSA verify will be done.\n"); + ERR_print_errors(bio_err); + eddsa_doit[testnum] = 0; + } else { + pkey_print_message("verify", test_ed_curves[testnum].name, + eddsa_c[testnum][1], + test_ed_curves[testnum].bits, seconds.eddsa); + Time_F(START); + count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R9:%ld:%u:%s:%.2f\n" + : "%ld %u bits %s verify in %.2fs\n", + count, test_ed_curves[testnum].bits, + test_ed_curves[testnum].name, d); + eddsa_results[testnum][1] = (double)count / d; + } + + if (rsa_count <= 1) { + /* if longer than 10s, don't do any more */ + for (testnum++; testnum < EdDSA_NUM; testnum++) + eddsa_doit[testnum] = 0; + } } } - if (rnd_fake) - RAND_cleanup(); -# endif -# ifndef NO_FORK + +#endif /* OPENSSL_NO_EC */ +#ifndef NO_FORK show_res: -# endif +#endif if (!mr) { - fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_VERSION)); - fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_BUILT_ON)); + printf("%s\n", OpenSSL_version(OPENSSL_VERSION)); + printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON)); printf("options:"); printf("%s ", BN_options()); -# ifndef OPENSSL_NO_MD2 +#ifndef OPENSSL_NO_MD2 printf("%s ", MD2_options()); -# endif -# ifndef OPENSSL_NO_RC4 +#endif +#ifndef OPENSSL_NO_RC4 printf("%s ", RC4_options()); -# endif -# ifndef OPENSSL_NO_DES +#endif +#ifndef OPENSSL_NO_DES printf("%s ", DES_options()); -# endif -# ifndef OPENSSL_NO_AES +#endif printf("%s ", AES_options()); -# endif -# ifndef OPENSSL_NO_IDEA - printf("%s ", idea_options()); -# endif -# ifndef OPENSSL_NO_BF +#ifndef OPENSSL_NO_IDEA + printf("%s ", IDEA_options()); +#endif +#ifndef OPENSSL_NO_BF printf("%s ", BF_options()); -# endif - fprintf(stdout, "\n%s\n", SSLeay_version(SSLEAY_CFLAGS)); +#endif + printf("\n%s\n", OpenSSL_version(OPENSSL_CFLAGS)); } if (pr_header) { if (mr) - fprintf(stdout, "+H"); + printf("+H"); else { - fprintf(stdout, - "The 'numbers' are in 1000s of bytes per second processed.\n"); - fprintf(stdout, "type "); + printf + ("The 'numbers' are in 1000s of bytes per second processed.\n"); + printf("type "); } - for (j = 0; j < SIZE_NUM; j++) - fprintf(stdout, mr ? ":%d" : "%7d bytes", lengths[j]); - fprintf(stdout, "\n"); + for (testnum = 0; testnum < size_num; testnum++) + printf(mr ? ":%d" : "%7d bytes", lengths[testnum]); + printf("\n"); } for (k = 0; k < ALGOR_NUM; k++) { if (!doit[k]) continue; if (mr) - fprintf(stdout, "+F:%d:%s", k, names[k]); + printf("+F:%u:%s", k, names[k]); else - fprintf(stdout, "%-13s", names[k]); - for (j = 0; j < SIZE_NUM; j++) { - if (results[k][j] > 10000 && !mr) - fprintf(stdout, " %11.2fk", results[k][j] / 1e3); + printf("%-13s", names[k]); + for (testnum = 0; testnum < size_num; testnum++) { + if (results[k][testnum] > 10000 && !mr) + printf(" %11.2fk", results[k][testnum] / 1e3); else - fprintf(stdout, mr ? ":%.2f" : " %11.2f ", results[k][j]); + printf(mr ? ":%.2f" : " %11.2f ", results[k][testnum]); } - fprintf(stdout, "\n"); + printf("\n"); } -# ifndef OPENSSL_NO_RSA - j = 1; +#ifndef OPENSSL_NO_RSA + testnum = 1; for (k = 0; k < RSA_NUM; k++) { if (!rsa_doit[k]) continue; - if (j && !mr) { + if (testnum && !mr) { printf("%18ssign verify sign/s verify/s\n", " "); - j = 0; + testnum = 0; } if (mr) - fprintf(stdout, "+F2:%u:%u:%f:%f\n", - k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]); + printf("+F2:%u:%u:%f:%f\n", + k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]); else - fprintf(stdout, "rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", - rsa_bits[k], rsa_results[k][0], rsa_results[k][1], - 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1]); + printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", + rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1], + rsa_results[k][0], rsa_results[k][1]); } -# endif -# ifndef OPENSSL_NO_DSA - j = 1; +#endif +#ifndef OPENSSL_NO_DSA + testnum = 1; for (k = 0; k < DSA_NUM; k++) { if (!dsa_doit[k]) continue; - if (j && !mr) { + if (testnum && !mr) { printf("%18ssign verify sign/s verify/s\n", " "); - j = 0; + testnum = 0; } if (mr) - fprintf(stdout, "+F3:%u:%u:%f:%f\n", - k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]); + printf("+F3:%u:%u:%f:%f\n", + k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]); else - fprintf(stdout, "dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", - dsa_bits[k], dsa_results[k][0], dsa_results[k][1], - 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1]); + printf("dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", + dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1], + dsa_results[k][0], dsa_results[k][1]); } -# endif -# ifndef OPENSSL_NO_ECDSA - j = 1; - for (k = 0; k < EC_NUM; k++) { +#endif +#ifndef OPENSSL_NO_EC + testnum = 1; + for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) { if (!ecdsa_doit[k]) continue; - if (j && !mr) { + if (testnum && !mr) { printf("%30ssign verify sign/s verify/s\n", " "); - j = 0; + testnum = 0; } if (mr) - fprintf(stdout, "+F4:%u:%u:%f:%f\n", - k, test_curves_bits[k], - ecdsa_results[k][0], ecdsa_results[k][1]); + printf("+F4:%u:%u:%f:%f\n", + k, test_curves[k].bits, + ecdsa_results[k][0], ecdsa_results[k][1]); else - fprintf(stdout, - "%4u bit ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n", - test_curves_bits[k], - test_curves_names[k], - ecdsa_results[k][0], ecdsa_results[k][1], - 1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1]); + printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n", + test_curves[k].bits, test_curves[k].name, + 1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1], + ecdsa_results[k][0], ecdsa_results[k][1]); } -# endif -# ifndef OPENSSL_NO_ECDH - j = 1; + testnum = 1; for (k = 0; k < EC_NUM; k++) { if (!ecdh_doit[k]) continue; - if (j && !mr) { + if (testnum && !mr) { printf("%30sop op/s\n", " "); - j = 0; + testnum = 0; } if (mr) - fprintf(stdout, "+F5:%u:%u:%f:%f\n", - k, test_curves_bits[k], - ecdh_results[k][0], 1.0 / ecdh_results[k][0]); + printf("+F5:%u:%u:%f:%f\n", + k, test_curves[k].bits, + ecdh_results[k][0], 1.0 / ecdh_results[k][0]); else - fprintf(stdout, "%4u bit ecdh (%s) %8.4fs %8.1f\n", - test_curves_bits[k], - test_curves_names[k], - ecdh_results[k][0], 1.0 / ecdh_results[k][0]); + printf("%4u bits ecdh (%s) %8.4fs %8.1f\n", + test_curves[k].bits, test_curves[k].name, + 1.0 / ecdh_results[k][0], ecdh_results[k][0]); } -# endif - mret = 0; + testnum = 1; + for (k = 0; k < OSSL_NELEM(eddsa_doit); k++) { + if (!eddsa_doit[k]) + continue; + if (testnum && !mr) { + printf("%30ssign verify sign/s verify/s\n", " "); + testnum = 0; + } + + if (mr) + printf("+F6:%u:%u:%s:%f:%f\n", + k, test_ed_curves[k].bits, test_ed_curves[k].name, + eddsa_results[k][0], eddsa_results[k][1]); + else + printf("%4u bits EdDSA (%s) %8.4fs %8.4fs %8.1f %8.1f\n", + test_ed_curves[k].bits, test_ed_curves[k].name, + 1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1], + eddsa_results[k][0], eddsa_results[k][1]); + } +#endif + + ret = 0; end: ERR_print_errors(bio_err); - if (buf != NULL) - OPENSSL_free(buf); - if (buf2 != NULL) - OPENSSL_free(buf2); -# ifndef OPENSSL_NO_RSA - for (i = 0; i < RSA_NUM; i++) - if (rsa_key[i] != NULL) - RSA_free(rsa_key[i]); -# endif -# ifndef OPENSSL_NO_DSA - for (i = 0; i < DSA_NUM; i++) - if (dsa_key[i] != NULL) - DSA_free(dsa_key[i]); -# endif + for (i = 0; i < loopargs_len; i++) { + OPENSSL_free(loopargs[i].buf_malloc); + OPENSSL_free(loopargs[i].buf2_malloc); -# ifndef OPENSSL_NO_ECDSA - for (i = 0; i < EC_NUM; i++) - if (ecdsa[i] != NULL) - EC_KEY_free(ecdsa[i]); -# endif -# ifndef OPENSSL_NO_ECDH - for (i = 0; i < EC_NUM; i++) { - if (ecdh_a[i] != NULL) - EC_KEY_free(ecdh_a[i]); - if (ecdh_b[i] != NULL) - EC_KEY_free(ecdh_b[i]); +#ifndef OPENSSL_NO_RSA + for (k = 0; k < RSA_NUM; k++) + RSA_free(loopargs[i].rsa_key[k]); +#endif +#ifndef OPENSSL_NO_DSA + for (k = 0; k < DSA_NUM; k++) + DSA_free(loopargs[i].dsa_key[k]); +#endif +#ifndef OPENSSL_NO_EC + for (k = 0; k < ECDSA_NUM; k++) + EC_KEY_free(loopargs[i].ecdsa[k]); + for (k = 0; k < EC_NUM; k++) + EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]); + for (k = 0; k < EdDSA_NUM; k++) + EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]); + OPENSSL_free(loopargs[i].secret_a); + OPENSSL_free(loopargs[i].secret_b); +#endif + } + + if (async_jobs > 0) { + for (i = 0; i < loopargs_len; i++) + ASYNC_WAIT_CTX_free(loopargs[i].wait_ctx); } -# endif + if (async_init) { + ASYNC_cleanup_thread(); + } + OPENSSL_free(loopargs); release_engine(e); - apps_shutdown(); - OPENSSL_EXIT(mret); + return ret; } -static void print_message(const char *s, long num, int length) +static void print_message(const char *s, long num, int length, int tm) { -# ifdef SIGALRM +#ifdef SIGALRM BIO_printf(bio_err, mr ? "+DT:%s:%d:%d\n" - : "Doing %s for %ds on %d size blocks: ", s, SECONDS, length); + : "Doing %s for %ds on %d size blocks: ", s, tm, length); (void)BIO_flush(bio_err); - alarm(SECONDS); -# else + alarm(tm); +#else BIO_printf(bio_err, mr ? "+DN:%s:%ld:%d\n" : "Doing %s %ld times on %d size blocks: ", s, num, length); (void)BIO_flush(bio_err); -# endif -# ifdef LINT - num = num; -# endif +#endif } static void pkey_print_message(const char *str, const char *str2, long num, - int bits, int tm) + unsigned int bits, int tm) { -# ifdef SIGALRM +#ifdef SIGALRM BIO_printf(bio_err, mr ? "+DTP:%d:%s:%s:%d\n" - : "Doing %d bit %s %s's for %ds: ", bits, str, str2, tm); + : "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm); (void)BIO_flush(bio_err); alarm(tm); -# else +#else BIO_printf(bio_err, mr ? "+DNP:%ld:%d:%s:%s\n" - : "Doing %ld %d bit %s %s's: ", num, bits, str, str2); + : "Doing %ld %u bits %s %s's: ", num, bits, str, str2); (void)BIO_flush(bio_err); -# endif -# ifdef LINT - num = num; -# endif +#endif } static void print_result(int alg, int run_no, int count, double time_used) { + if (count == -1) { + BIO_puts(bio_err, "EVP error!\n"); + exit(1); + } BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n" : "%d %s's in %.2fs\n", count, names[alg], time_used); results[alg][run_no] = ((double)count) / time_used * lengths[run_no]; } -# ifndef NO_FORK +#ifndef NO_FORK static char *sstrsep(char **string, const char *delim) { char isdelim[256]; @@ -2608,25 +3435,21 @@ static char *sstrsep(char **string, const char *delim) return token; } -static int do_multi(int multi) +static int do_multi(int multi, int size_num) { int n; int fd[2]; int *fds; static char sep[] = ":"; - fds = malloc(multi * sizeof(*fds)); - if (fds == NULL) { - fprintf(stderr, "Out of memory in speed (do_multi)\n"); - exit(1); - } + fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi"); for (n = 0; n < multi; ++n) { if (pipe(fd) == -1) { - fprintf(stderr, "pipe failure\n"); + BIO_printf(bio_err, "pipe failure\n"); exit(1); } fflush(stdout); - fflush(stderr); + (void)BIO_flush(bio_err); if (fork()) { close(fd[1]); fds[n] = fd[0]; @@ -2634,7 +3457,7 @@ static int do_multi(int multi) close(fd[0]); close(1); if (dup(fd[1]) == -1) { - fprintf(stderr, "dup failed\n"); + BIO_printf(bio_err, "dup failed\n"); exit(1); } close(fd[1]); @@ -2658,21 +3481,22 @@ static int do_multi(int multi) if (p) *p = '\0'; if (buf[0] != '+') { - fprintf(stderr, "Don't understand line '%s' from child %d\n", - buf, n); + BIO_printf(bio_err, + "Don't understand line '%s' from child %d\n", buf, + n); continue; } printf("Got: %s from %d\n", buf, n); - if (!strncmp(buf, "+F:", 3)) { + if (strncmp(buf, "+F:", 3) == 0) { int alg; int j; p = buf + 3; alg = atoi(sstrsep(&p, sep)); sstrsep(&p, sep); - for (j = 0; j < SIZE_NUM; ++j) + for (j = 0; j < size_num; ++j) results[alg][j] += atof(sstrsep(&p, sep)); - } else if (!strncmp(buf, "+F2:", 4)) { + } else if (strncmp(buf, "+F2:", 4) == 0) { int k; double d; @@ -2681,19 +3505,13 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - rsa_results[k][0] = 1 / (1 / rsa_results[k][0] + 1 / d); - else - rsa_results[k][0] = d; + rsa_results[k][0] += d; d = atof(sstrsep(&p, sep)); - if (n) - rsa_results[k][1] = 1 / (1 / rsa_results[k][1] + 1 / d); - else - rsa_results[k][1] = d; + rsa_results[k][1] += d; } -# ifndef OPENSSL_NO_DSA - else if (!strncmp(buf, "+F3:", 4)) { +# ifndef OPENSSL_NO_DSA + else if (strncmp(buf, "+F3:", 4) == 0) { int k; double d; @@ -2702,20 +3520,14 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - dsa_results[k][0] = 1 / (1 / dsa_results[k][0] + 1 / d); - else - dsa_results[k][0] = d; + dsa_results[k][0] += d; d = atof(sstrsep(&p, sep)); - if (n) - dsa_results[k][1] = 1 / (1 / dsa_results[k][1] + 1 / d); - else - dsa_results[k][1] = d; + dsa_results[k][1] += d; } -# endif -# ifndef OPENSSL_NO_ECDSA - else if (!strncmp(buf, "+F4:", 4)) { +# endif +# ifndef OPENSSL_NO_EC + else if (strncmp(buf, "+F4:", 4) == 0) { int k; double d; @@ -2724,23 +3536,21 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - ecdsa_results[k][0] = - 1 / (1 / ecdsa_results[k][0] + 1 / d); - else - ecdsa_results[k][0] = d; + ecdsa_results[k][0] += d; d = atof(sstrsep(&p, sep)); - if (n) - ecdsa_results[k][1] = - 1 / (1 / ecdsa_results[k][1] + 1 / d); - else - ecdsa_results[k][1] = d; - } -# endif + ecdsa_results[k][1] += d; + } else if (strncmp(buf, "+F5:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); -# ifndef OPENSSL_NO_ECDH - else if (!strncmp(buf, "+F5:", 4)) { + d = atof(sstrsep(&p, sep)); + ecdh_results[k][0] += d; + } else if (strncmp(buf, "+F6:", 4) == 0) { int k; double d; @@ -2749,17 +3559,18 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - ecdh_results[k][0] = 1 / (1 / ecdh_results[k][0] + 1 / d); - else - ecdh_results[k][0] = d; + eddsa_results[k][0] += d; + d = atof(sstrsep(&p, sep)); + eddsa_results[k][1] += d; } -# endif +# endif - else if (!strncmp(buf, "+H:", 3)) { + else if (strncmp(buf, "+H:", 3) == 0) { + ; } else - fprintf(stderr, "Unknown type '%s' from child %d\n", buf, n); + BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf, + n); } fclose(f); @@ -2767,34 +3578,41 @@ static int do_multi(int multi) free(fds); return 1; } -# endif +#endif -static void multiblock_speed(const EVP_CIPHER *evp_cipher) +static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, + const openssl_speed_sec_t *seconds) { - static int mblengths[] = + static const int mblengths_list[] = { 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 }; - int j, count, num = sizeof(lengths) / sizeof(lengths[0]); + const int *mblengths = mblengths_list; + int j, count, keylen, num = OSSL_NELEM(mblengths_list); const char *alg_name; - unsigned char *inp, *out, no_key[32], no_iv[16]; - EVP_CIPHER_CTX ctx; + unsigned char *inp, *out, *key, no_key[32], no_iv[16]; + EVP_CIPHER_CTX *ctx; double d = 0.0; - inp = OPENSSL_malloc(mblengths[num - 1]); - out = OPENSSL_malloc(mblengths[num - 1] + 1024); - if (!inp || !out) { - BIO_printf(bio_err,"Out of memory\n"); - goto end; + if (lengths_single) { + mblengths = &lengths_single; + num = 1; } + inp = app_malloc(mblengths[num - 1], "multiblock input buffer"); + out = app_malloc(mblengths[num - 1] + 1024, "multiblock output buffer"); + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv); + + keylen = EVP_CIPHER_CTX_key_length(ctx); + key = app_malloc(keylen, "evp_cipher key"); + EVP_CIPHER_CTX_rand_key(ctx, key); + EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL); + OPENSSL_clear_free(key, keylen); - EVP_CIPHER_CTX_init(&ctx); - EVP_EncryptInit_ex(&ctx, evp_cipher, NULL, no_key, no_iv); - EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), - no_key); - alg_name = OBJ_nid2ln(evp_cipher->nid); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), no_key); + alg_name = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)); for (j = 0; j < num; j++) { - print_message(alg_name, 0, mblengths[j]); + print_message(alg_name, 0, mblengths[j], seconds->sym); Time_F(START); for (count = 0, run = 1; run && count < 0x7fffffff; count++) { unsigned char aad[EVP_AEAD_TLS1_AAD_LEN]; @@ -2813,16 +3631,14 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher) mb_param.len = len; mb_param.interleave = 8; - packlen = EVP_CIPHER_CTX_ctrl(&ctx, - EVP_CTRL_TLS1_1_MULTIBLOCK_AAD, + packlen = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_AAD, sizeof(mb_param), &mb_param); if (packlen > 0) { mb_param.out = out; mb_param.inp = inp; mb_param.len = len; - EVP_CIPHER_CTX_ctrl(&ctx, - EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, sizeof(mb_param), &mb_param); } else { int pad; @@ -2831,15 +3647,13 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher) len += 16; aad[11] = (unsigned char)(len >> 8); aad[12] = (unsigned char)(len); - pad = EVP_CIPHER_CTX_ctrl(&ctx, - EVP_CTRL_AEAD_TLS1_AAD, + pad = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, EVP_AEAD_TLS1_AAD_LEN, aad); - EVP_Cipher(&ctx, out, inp, len + pad); + EVP_Cipher(ctx, out, inp, len + pad); } } d = Time_F(STOP); - BIO_printf(bio_err, - mr ? "+R:%d:%s:%f\n" + BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n" : "%d %s's in %.2fs\n", count, "evp", d); results[D_EVP][j] = ((double)count) / d * mblengths[j]; } @@ -2871,10 +3685,7 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher) fprintf(stdout, "\n"); } -end: - if (inp) - OPENSSL_free(inp); - if (out) - OPENSSL_free(out); + OPENSSL_free(inp); + OPENSSL_free(out); + EVP_CIPHER_CTX_free(ctx); } -#endif diff --git a/apps/spkac.c b/apps/spkac.c index 4b4106d03b99..f384af6eb60b 100644 --- a/apps/spkac.c +++ b/apps/spkac.c @@ -1,194 +1,130 @@ -/* apps/spkac.c */ - /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 1999. Based on an original idea by Massimiliano Pala (madwolf@openca.org). - */ -/* ==================================================================== - * Copyright (c) 1999-2017 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/conf.h> #include <openssl/err.h> #include <openssl/evp.h> -#include <openssl/lhash.h> #include <openssl/x509.h> #include <openssl/pem.h> -#undef PROG -#define PROG spkac_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_NOOUT, OPT_PUBKEY, OPT_VERIFY, OPT_IN, OPT_OUT, + OPT_ENGINE, OPT_KEY, OPT_CHALLENGE, OPT_PASSIN, OPT_SPKAC, + OPT_SPKSECT, OPT_KEYFORM +} OPTION_CHOICE; -/*- - * -in arg - input file - default stdin - * -out arg - output file - default stdout - */ - -int MAIN(int, char **); +const OPTIONS spkac_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"key", OPT_KEY, '<', "Create SPKAC using private key"}, + {"keyform", OPT_KEYFORM, 'f', "Private key file format - default PEM (PEM, DER, or ENGINE)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"challenge", OPT_CHALLENGE, 's', "Challenge string"}, + {"spkac", OPT_SPKAC, 's', "Alternative SPKAC name"}, + {"noout", OPT_NOOUT, '-', "Don't print SPKAC"}, + {"pubkey", OPT_PUBKEY, '-', "Output public key"}, + {"verify", OPT_VERIFY, '-', "Verify SPKAC signature"}, + {"spksect", OPT_SPKSECT, 's', + "Specify the name of an SPKAC-dedicated section of configuration"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int spkac_main(int argc, char **argv) { - ENGINE *e = NULL; - int i, badops = 0, ret = 1; - BIO *in = NULL, *out = NULL; - int verify = 0, noout = 0, pubkey = 0; - char *infile = NULL, *outfile = NULL, *prog; - char *passargin = NULL, *passin = NULL; - const char *spkac = "SPKAC", *spksect = "default"; - char *spkstr = NULL; - char *challenge = NULL, *keyfile = NULL; + BIO *out = NULL; CONF *conf = NULL; - NETSCAPE_SPKI *spki = NULL; + ENGINE *e = NULL; EVP_PKEY *pkey = NULL; - char *engine = NULL; - - apps_startup(); - - if (!bio_err) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; + NETSCAPE_SPKI *spki = NULL; + char *challenge = NULL, *keyfile = NULL; + char *infile = NULL, *outfile = NULL, *passinarg = NULL, *passin = NULL; + char *spkstr = NULL, *prog; + const char *spkac = "SPKAC", *spksect = "default"; + int i, ret = 1, verify = 0, noout = 0, pubkey = 0; + int keyformat = FORMAT_PEM; + OPTION_CHOICE o; - prog = argv[0]; - argc--; - argv++; - while (argc >= 1) { - if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-key") == 0) { - if (--argc < 1) - goto bad; - keyfile = *(++argv); - } else if (strcmp(*argv, "-challenge") == 0) { - if (--argc < 1) - goto bad; - challenge = *(++argv); - } else if (strcmp(*argv, "-spkac") == 0) { - if (--argc < 1) - goto bad; - spkac = *(++argv); - } else if (strcmp(*argv, "-spksect") == 0) { - if (--argc < 1) - goto bad; - spksect = *(++argv); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -#endif - else if (strcmp(*argv, "-noout") == 0) + prog = opt_init(argc, argv, spkac_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(spkac_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOOUT: noout = 1; - else if (strcmp(*argv, "-pubkey") == 0) + break; + case OPT_PUBKEY: pubkey = 1; - else if (strcmp(*argv, "-verify") == 0) + break; + case OPT_VERIFY: verify = 1; - else - badops = 1; - argc--; - argv++; - } - - if (badops) { - bad: - BIO_printf(bio_err, "%s [options]\n", prog); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, " -in arg input file\n"); - BIO_printf(bio_err, " -out arg output file\n"); - BIO_printf(bio_err, - " -key arg create SPKAC using private key\n"); - BIO_printf(bio_err, - " -passin arg input file pass phrase source\n"); - BIO_printf(bio_err, " -challenge arg challenge string\n"); - BIO_printf(bio_err, " -spkac arg alternative SPKAC name\n"); - BIO_printf(bio_err, " -noout don't print SPKAC\n"); - BIO_printf(bio_err, " -pubkey output public key\n"); - BIO_printf(bio_err, " -verify verify SPKAC signature\n"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, - " -engine e use engine e, possibly a hardware device.\n"); -#endif - goto end; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) + goto opthelp; + break; + case OPT_CHALLENGE: + challenge = opt_arg(); + break; + case OPT_SPKAC: + spkac = opt_arg(); + break; + case OPT_SPKSECT: + spksect = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + } } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; - ERR_load_crypto_strings(); - if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } - e = setup_engine(bio_err, engine, 0); if (keyfile != NULL) { - pkey = load_key(bio_err, - strcmp(keyfile, "-") ? keyfile : NULL, - FORMAT_PEM, 1, passin, e, "private key"); + pkey = load_key(strcmp(keyfile, "-") ? keyfile : NULL, + keyformat, 1, passin, e, "private key"); if (pkey == NULL) goto end; spki = NETSCAPE_SPKI_new(); @@ -203,21 +139,9 @@ int MAIN(int argc, char **argv) if (spkstr == NULL) goto end; - if (outfile) - out = BIO_new_file(outfile, "w"); - else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } - - if (!out) { - BIO_printf(bio_err, "Error opening output file\n"); - ERR_print_errors(bio_err); + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) { + OPENSSL_free(spkstr); goto end; } BIO_printf(out, "SPKAC=%s\n", spkstr); @@ -226,29 +150,12 @@ int MAIN(int argc, char **argv) goto end; } - if (infile) - in = BIO_new_file(infile, "r"); - else - in = BIO_new_fp(stdin, BIO_NOCLOSE); - - if (!in) { - BIO_printf(bio_err, "Error opening input file\n"); - ERR_print_errors(bio_err); - goto end; - } - - conf = NCONF_new(NULL); - i = NCONF_load_bio(conf, in, NULL); - - if (!i) { - BIO_printf(bio_err, "Error parsing config file\n"); - ERR_print_errors(bio_err); + if ((conf = app_load_config(infile)) == NULL) goto end; - } spkstr = NCONF_get_string(conf, spksect, spkac); - if (!spkstr) { + if (spkstr == NULL) { BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n", spkac); ERR_print_errors(bio_err); goto end; @@ -262,23 +169,9 @@ int MAIN(int argc, char **argv) goto end; } - if (outfile) - out = BIO_new_file(outfile, "w"); - else { - out = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } - - if (!out) { - BIO_printf(bio_err, "Error opening output file\n"); - ERR_print_errors(bio_err); + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) goto end; - } if (!noout) NETSCAPE_SPKI_print(out, spki); @@ -301,12 +194,9 @@ int MAIN(int argc, char **argv) end: NCONF_free(conf); NETSCAPE_SPKI_free(spki); - BIO_free(in); BIO_free_all(out); EVP_PKEY_free(pkey); release_engine(e); - if (passin) - OPENSSL_free(passin); - apps_shutdown(); - OPENSSL_EXIT(ret); + OPENSSL_free(passin); + return ret; } diff --git a/apps/srp.c b/apps/srp.c index 491445df60b0..689574a4854c 100644 --- a/apps/srp.c +++ b/apps/srp.c @@ -1,64 +1,21 @@ -/* apps/srp.c */ /* - * Written by Peter Sylvester (peter.sylvester@edelweb.fr) for the EdelKey - * project and contributed to the OpenSSL project 2004. - */ -/* ==================================================================== - * Copyright (c) 2004 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2004, EdelKey Project. All Rights Reserved. * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html * + * Originally written by Christophe Renou and Peter Sylvester, + * for the EdelKey project. */ + #include <openssl/opensslconf.h> +#ifdef OPENSSL_NO_SRP +NON_EMPTY_TRANSLATION_UNIT +#else -#ifndef OPENSSL_NO_SRP # include <stdio.h> # include <stdlib.h> # include <string.h> @@ -68,55 +25,16 @@ # include <openssl/txt_db.h> # include <openssl/buffer.h> # include <openssl/srp.h> - # include "apps.h" - -# undef PROG -# define PROG srp_main +# include "progs.h" # define BASE_SECTION "srp" # define CONFIG_FILE "openssl.cnf" -# define ENV_RANDFILE "RANDFILE" # define ENV_DATABASE "srpvfile" # define ENV_DEFAULT_SRP "default_srp" -static char *srp_usage[] = { - "usage: srp [args] [user] \n", - "\n", - " -verbose Talk alot while doing things\n", - " -config file A config file\n", - " -name arg The particular srp definition to use\n", - " -srpvfile arg The srp verifier file name\n", - " -add add an user and srp verifier\n", - " -modify modify the srp verifier of an existing user\n", - " -delete delete user from verifier file\n", - " -list list user\n", - " -gn arg g and N values to be used for new verifier\n", - " -userinfo arg additional info to be set for user\n", - " -passin arg input file pass phrase source\n", - " -passout arg output file pass phrase source\n", -# ifndef OPENSSL_NO_ENGINE - " -engine e - use engine e, possibly a hardware device.\n", -# endif - NULL -}; - -# ifdef EFENCE -extern int EF_PROTECT_FREE; -extern int EF_PROTECT_BELOW; -extern int EF_ALIGNMENT; -# endif - -static CONF *conf = NULL; -static char *section = NULL; - -# define VERBOSE if (verbose) -# define VVERBOSE if (verbose>1) - -int MAIN(int, char **); - static int get_index(CA_DB *db, char *id, char type) { char **pp; @@ -127,7 +45,7 @@ static int get_index(CA_DB *db, char *id, char type) for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_srptype][0] == DB_SRP_INDEX - && !strcmp(id, pp[DB_srpid])) + && strcmp(id, pp[DB_srpid]) == 0) return i; } } else { @@ -135,7 +53,7 @@ static int get_index(CA_DB *db, char *id, char type) pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_srptype][0] != DB_SRP_INDEX - && !strcmp(id, pp[DB_srpid])) + && strcmp(id, pp[DB_srpid]) == 0) return i; } } @@ -143,69 +61,67 @@ static int get_index(CA_DB *db, char *id, char type) return -1; } -static void print_entry(CA_DB *db, BIO *bio, int indx, int verbose, char *s) +static void print_entry(CA_DB *db, int indx, int verbose, char *s) { if (indx >= 0 && verbose) { int j; char **pp = sk_OPENSSL_PSTRING_value(db->db->data, indx); - BIO_printf(bio, "%s \"%s\"\n", s, pp[DB_srpid]); + BIO_printf(bio_err, "%s \"%s\"\n", s, pp[DB_srpid]); for (j = 0; j < DB_NUMBER; j++) { BIO_printf(bio_err, " %d = \"%s\"\n", j, pp[j]); } } } -static void print_index(CA_DB *db, BIO *bio, int indexindex, int verbose) +static void print_index(CA_DB *db, int indexindex, int verbose) { - print_entry(db, bio, indexindex, verbose, "g N entry"); + print_entry(db, indexindex, verbose, "g N entry"); } -static void print_user(CA_DB *db, BIO *bio, int userindex, int verbose) +static void print_user(CA_DB *db, int userindex, int verbose) { if (verbose > 0) { char **pp = sk_OPENSSL_PSTRING_value(db->db->data, userindex); if (pp[DB_srptype][0] != 'I') { - print_entry(db, bio, userindex, verbose, "User entry"); - print_entry(db, bio, get_index(db, pp[DB_srpgN], 'I'), verbose, + print_entry(db, userindex, verbose, "User entry"); + print_entry(db, get_index(db, pp[DB_srpgN], 'I'), verbose, "g N entry"); } } } -static int update_index(CA_DB *db, BIO *bio, char **row) +static int update_index(CA_DB *db, char **row) { char **irow; int i; - irow = (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1)); - if (irow == NULL) { - BIO_printf(bio_err, "Memory allocation failure\n"); - return 0; - } - + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row pointers"); for (i = 0; i < DB_NUMBER; i++) irow[i] = row[i]; irow[DB_NUMBER] = NULL; if (!TXT_DB_insert(db->db, irow)) { - BIO_printf(bio, "failed to update srpvfile\n"); - BIO_printf(bio, "TXT_DB error number %ld\n", db->db->error); + BIO_printf(bio_err, "failed to update srpvfile\n"); + BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); OPENSSL_free(irow); return 0; } return 1; } -static void lookup_fail(const char *name, char *tag) +static char *lookup_conf(const CONF *conf, const char *section, const char *tag) { - BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag); + char *entry = NCONF_get_string(conf, section, tag); + if (entry == NULL) + BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag); + return entry; } static char *srp_verify_user(const char *user, const char *srp_verifier, char *srp_usersalt, const char *g, const char *N, - const char *passin, BIO *bio, int verbose) + const char *passin, int verbose) { char password[1025]; PW_CB_DATA cb_tmp; @@ -219,14 +135,17 @@ static char *srp_verify_user(const char *user, const char *srp_verifier, len = password_callback(password, sizeof(password)-1, 0, &cb_tmp); if (len > 0) { password[len] = 0; - VERBOSE BIO_printf(bio, - "Validating\n user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n", - user, srp_verifier, srp_usersalt, g, N); - VVERBOSE BIO_printf(bio, "Pass %s\n", password); + if (verbose) + BIO_printf(bio_err, + "Validating\n user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n", + user, srp_verifier, srp_usersalt, g, N); + if (verbose > 1) + BIO_printf(bio_err, "Pass %s\n", password); - if (!(gNid = SRP_create_verifier(user, password, &srp_usersalt, - &verifier, N, g))) { - BIO_printf(bio, "Internal error validating SRP verifier\n"); + OPENSSL_assert(srp_usersalt != NULL); + if ((gNid = SRP_create_verifier(user, password, &srp_usersalt, + &verifier, N, g)) == NULL) { + BIO_printf(bio_err, "Internal error validating SRP verifier\n"); } else { if (strcmp(verifier, srp_verifier)) gNid = NULL; @@ -239,7 +158,7 @@ static char *srp_verify_user(const char *user, const char *srp_verifier, static char *srp_create_user(char *user, char **srp_verifier, char **srp_usersalt, char *g, char *N, - char *passout, BIO *bio, int verbose) + char *passout, int verbose) { char password[1025]; PW_CB_DATA cb_tmp; @@ -252,268 +171,199 @@ static char *srp_create_user(char *user, char **srp_verifier, len = password_callback(password, sizeof(password)-1, 1, &cb_tmp); if (len > 0) { password[len] = 0; - VERBOSE BIO_printf(bio, - "Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n", - user, g, N); - if (!(gNid = SRP_create_verifier(user, password, &salt, - srp_verifier, N, g))) { - BIO_printf(bio, "Internal error creating SRP verifier\n"); + if (verbose) + BIO_printf(bio_err, "Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n", + user, g, N); + if ((gNid = SRP_create_verifier(user, password, &salt, + srp_verifier, N, g)) == NULL) { + BIO_printf(bio_err, "Internal error creating SRP verifier\n"); } else { *srp_usersalt = salt; } OPENSSL_cleanse(password, len); - VVERBOSE BIO_printf(bio, "gNid=%s salt =\"%s\"\n verifier =\"%s\"\n", - gNid, salt, *srp_verifier); + if (verbose > 1) + BIO_printf(bio_err, "gNid=%s salt =\"%s\"\n verifier =\"%s\"\n", + gNid, salt, *srp_verifier); } return gNid; } -int MAIN(int argc, char **argv) -{ - int add_user = 0; - int list_user = 0; - int delete_user = 0; - int modify_user = 0; - char *user = NULL; - - char *passargin = NULL, *passargout = NULL; - char *passin = NULL, *passout = NULL; - char *gN = NULL; - int gNindex = -1; - char **gNrow = NULL; - int maxgN = -1; - - char *userinfo = NULL; - - int badops = 0; - int ret = 1; - int errors = 0; - int verbose = 0; - int doupdatedb = 0; - char *configfile = NULL; - char *dbfile = NULL; - CA_DB *db = NULL; - char **pp; - int i; - long errorline = -1; - char *randfile = NULL; - ENGINE *e = NULL; - char *engine = NULL; - char *tofree = NULL; - DB_ATTR db_attr; +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD, + OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO, + OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM +} OPTION_CHOICE; -# ifdef EFENCE - EF_PROTECT_FREE = 1; - EF_PROTECT_BELOW = 1; - EF_ALIGNMENT = 0; +const OPTIONS srp_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"verbose", OPT_VERBOSE, '-', "Talk a lot while doing things"}, + {"config", OPT_CONFIG, '<', "A config file"}, + {"name", OPT_NAME, 's', "The particular srp definition to use"}, + {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"}, + {"add", OPT_ADD, '-', "Add a user and srp verifier"}, + {"modify", OPT_MODIFY, '-', + "Modify the srp verifier of an existing user"}, + {"delete", OPT_DELETE, '-', "Delete user from verifier file"}, + {"list", OPT_LIST, '-', "List users"}, + {"gn", OPT_GN, 's', "Set g and N values to be used for new verifier"}, + {"userinfo", OPT_USERINFO, 's', "Additional info to be set for user"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, # endif + {NULL} +}; - apps_startup(); - - conf = NULL; - section = NULL; - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); +int srp_main(int argc, char **argv) +{ + ENGINE *e = NULL; + CA_DB *db = NULL; + CONF *conf = NULL; + int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose = 0, i; + int doupdatedb = 0, mode = OPT_ERR; + char *user = NULL, *passinarg = NULL, *passoutarg = NULL; + char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL; + char *section = NULL; + char **gNrow = NULL, *configfile = NULL; + char *srpvfile = NULL, **pp, *prog; + OPTION_CHOICE o; - argc--; - argv++; - while (argc >= 1 && badops == 0) { - if (strcmp(*argv, "-verbose") == 0) { + prog = opt_init(argc, argv, srp_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(srp_options); + ret = 0; + goto end; + case OPT_VERBOSE: verbose++; - } else if (strcmp(*argv, "-config") == 0) { - if (--argc < 1) - goto bad; - configfile = *(++argv); - } else if (strcmp(*argv, "-name") == 0) { - if (--argc < 1) - goto bad; - section = *(++argv); - } else if (strcmp(*argv, "-srpvfile") == 0) { - if (--argc < 1) - goto bad; - dbfile = *(++argv); - } else if (strcmp(*argv, "-add") == 0) { - add_user = 1; - } else if (strcmp(*argv, "-delete") == 0) { - delete_user = 1; - } else if (strcmp(*argv, "-modify") == 0) { - modify_user = 1; - } else if (strcmp(*argv, "-list") == 0) { - list_user = 1; - } else if (strcmp(*argv, "-gn") == 0) { - if (--argc < 1) - goto bad; - gN = *(++argv); - } else if (strcmp(*argv, "-userinfo") == 0) { - if (--argc < 1) - goto bad; - userinfo = *(++argv); - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-passout") == 0) { - if (--argc < 1) - goto bad; - passargout = *(++argv); - } -# ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -# endif - - else if (**argv == '-') { - bad: - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; break; - } else { + case OPT_CONFIG: + configfile = opt_arg(); + break; + case OPT_NAME: + section = opt_arg(); + break; + case OPT_SRPVFILE: + srpvfile = opt_arg(); + break; + case OPT_ADD: + case OPT_DELETE: + case OPT_MODIFY: + case OPT_LIST: + if (mode != OPT_ERR) { + BIO_printf(bio_err, + "%s: Only one of -add/-delete/-modify/-list\n", + prog); + goto opthelp; + } + mode = o; + break; + case OPT_GN: + gN = opt_arg(); + break; + case OPT_USERINFO: + userinfo = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; break; } - - argc--; - argv++; } + argc = opt_num_rest(); + argv = opt_rest(); - if (dbfile && configfile) { + if (srpvfile != NULL && configfile != NULL) { BIO_printf(bio_err, - "-dbfile and -configfile cannot be specified together.\n"); - badops = 1; + "-srpvfile and -configfile cannot be specified together.\n"); + goto end; } - if (add_user + delete_user + modify_user + list_user != 1) { + if (mode == OPT_ERR) { BIO_printf(bio_err, "Exactly one of the options -add, -delete, -modify -list must be specified.\n"); - badops = 1; + goto opthelp; } - if (delete_user + modify_user + delete_user == 1 && argc <= 0) { - BIO_printf(bio_err, - "Need at least one user for options -add, -delete, -modify. \n"); - badops = 1; + if (mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD) { + if (argc == 0) { + BIO_printf(bio_err, "Need at least one user.\n"); + goto opthelp; + } + user = *argv++; } - if ((passargin || passargout) && argc != 1) { + if ((passinarg != NULL || passoutarg != NULL) && argc != 1) { BIO_printf(bio_err, "-passin, -passout arguments only valid with one user.\n"); - badops = 1; + goto opthelp; } - if (badops) { - for (pp = srp_usage; (*pp != NULL); pp++) - BIO_printf(bio_err, "%s", *pp); - - BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, - LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, - " load the file (or the files in the directory) into\n"); - BIO_printf(bio_err, " the random number generator\n"); - goto err; - } - - ERR_load_crypto_strings(); - - e = setup_engine(bio_err, engine, 0); - - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); - goto err; + goto end; } - if (!dbfile) { - - /*****************************************************************/ - tofree = NULL; - if (configfile == NULL) - configfile = getenv("OPENSSL_CONF"); + if (srpvfile == NULL) { if (configfile == NULL) - configfile = getenv("SSLEAY_CONF"); - if (configfile == NULL) { - const char *s = X509_get_default_cert_area(); - size_t len; + configfile = default_config_file; -# ifdef OPENSSL_SYS_VMS - len = strlen(s) + sizeof(CONFIG_FILE); - tofree = OPENSSL_malloc(len); - if (!tofree) { - BIO_printf(bio_err, "Out of memory\n"); - goto err; - } - strcpy(tofree, s); -# else - len = strlen(s) + sizeof(CONFIG_FILE) + 1; - tofree = OPENSSL_malloc(len); - if (!tofree) { - BIO_printf(bio_err, "Out of memory\n"); - goto err; - } - BUF_strlcpy(tofree, s, len); - BUF_strlcat(tofree, "/", len); -# endif - BUF_strlcat(tofree, CONFIG_FILE, len); - configfile = tofree; - } - - VERBOSE BIO_printf(bio_err, "Using configuration from %s\n", - configfile); - conf = NCONF_new(NULL); - if (NCONF_load(conf, configfile, &errorline) <= 0) { - if (errorline <= 0) - BIO_printf(bio_err, "error loading the config file '%s'\n", - configfile); - else - BIO_printf(bio_err, "error on line %ld of config file '%s'\n", - errorline, configfile); - goto err; - } - if (tofree) { - OPENSSL_free(tofree); - tofree = NULL; - } - - if (!load_config(bio_err, conf)) - goto err; + if (verbose) + BIO_printf(bio_err, "Using configuration from %s\n", + configfile); + conf = app_load_config(configfile); + if (conf == NULL) + goto end; + if (configfile != default_config_file && !app_load_modules(conf)) + goto end; /* Lets get the config section we are using */ if (section == NULL) { - VERBOSE BIO_printf(bio_err, - "trying to read " ENV_DEFAULT_SRP - " in \" BASE_SECTION \"\n"); + if (verbose) + BIO_printf(bio_err, + "trying to read " ENV_DEFAULT_SRP + " in " BASE_SECTION "\n"); - section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_SRP); - if (section == NULL) { - lookup_fail(BASE_SECTION, ENV_DEFAULT_SRP); - goto err; - } + section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_SRP); + if (section == NULL) + goto end; } - if (randfile == NULL && conf) - randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); - - VERBOSE BIO_printf(bio_err, - "trying to read " ENV_DATABASE - " in section \"%s\"\n", section); + app_RAND_load_conf(conf, BASE_SECTION); - if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) { - lookup_fail(section, ENV_DATABASE); - goto err; - } + if (verbose) + BIO_printf(bio_err, + "trying to read " ENV_DATABASE " in section \"%s\"\n", + section); + srpvfile = lookup_conf(conf, section, ENV_DATABASE); + if (srpvfile == NULL) + goto end; } - if (randfile == NULL) - ERR_clear_error(); - else - app_RAND_load_file(randfile, bio_err, 0); - VERBOSE BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n", - dbfile); + if (verbose) + BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n", + srpvfile); - db = load_index(dbfile, &db_attr); + db = load_index(srpvfile, NULL); if (db == NULL) - goto err; + goto end; /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { @@ -521,53 +371,51 @@ int MAIN(int argc, char **argv) if (pp[DB_srptype][0] == DB_SRP_INDEX) { maxgN = i; - if (gNindex < 0 && gN != NULL && !strcmp(gN, pp[DB_srpid])) + if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0) gNindex = i; - print_index(db, bio_err, i, verbose > 1); + print_index(db, i, verbose > 1); } } - VERBOSE BIO_printf(bio_err, "Database initialised\n"); + if (verbose) + BIO_printf(bio_err, "Database initialised\n"); if (gNindex >= 0) { gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex); - print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N"); + print_entry(db, gNindex, verbose > 1, "Default g and N"); } else if (maxgN > 0 && !SRP_get_default_gN(gN)) { BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN); - goto err; + goto end; } else { - VERBOSE BIO_printf(bio_err, "Database has no g N information.\n"); + if (verbose) + BIO_printf(bio_err, "Database has no g N information.\n"); gNrow = NULL; } - VVERBOSE BIO_printf(bio_err, "Starting user processing\n"); + if (verbose > 1) + BIO_printf(bio_err, "Starting user processing\n"); - if (argc > 0) - user = *(argv++); - - while (list_user || user) { + while (mode == OPT_LIST || user != NULL) { int userindex = -1; - if (user) - VVERBOSE BIO_printf(bio_err, "Processing user \"%s\"\n", user); - if ((userindex = get_index(db, user, 'U')) >= 0) { - print_user(db, bio_err, userindex, (verbose > 0) || list_user); - } - if (list_user) { + if (user != NULL && verbose > 1) + BIO_printf(bio_err, "Processing user \"%s\"\n", user); + if ((userindex = get_index(db, user, 'U')) >= 0) + print_user(db, userindex, (verbose > 0) || mode == OPT_LIST); + + if (mode == OPT_LIST) { if (user == NULL) { BIO_printf(bio_err, "List all users\n"); - for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { - print_user(db, bio_err, i, 1); - } - list_user = 0; + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) + print_user(db, i, 1); } else if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, ignored. t\n", user); errors++; } - } else if (add_user) { + } else if (mode == OPT_ADD) { if (userindex >= 0) { /* reactivation of a new user */ char **row = @@ -588,43 +436,36 @@ int MAIN(int argc, char **argv) &(row[DB_srpsalt]), gNrow ? gNrow[DB_srpsalt] : gN, gNrow ? gNrow[DB_srpverifier] : NULL, - passout, bio_err, verbose))) { + passout, verbose))) { BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned .\n", user); errors++; - goto err; + goto end; } - row[DB_srpid] = BUF_strdup(user); - row[DB_srptype] = BUF_strdup("v"); - row[DB_srpgN] = BUF_strdup(gNid); + row[DB_srpid] = OPENSSL_strdup(user); + row[DB_srptype] = OPENSSL_strdup("v"); + row[DB_srpgN] = OPENSSL_strdup(gNid); - if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] - || !row[DB_srpverifier] || !row[DB_srpsalt] || (userinfo - && - (!(row - [DB_srpinfo] - = - BUF_strdup - (userinfo)))) - || !update_index(db, bio_err, row)) { - if (row[DB_srpid]) - OPENSSL_free(row[DB_srpid]); - if (row[DB_srpgN]) - OPENSSL_free(row[DB_srpgN]); - if (row[DB_srpinfo]) - OPENSSL_free(row[DB_srpinfo]); - if (row[DB_srptype]) - OPENSSL_free(row[DB_srptype]); - if (row[DB_srpverifier]) - OPENSSL_free(row[DB_srpverifier]); - if (row[DB_srpsalt]) - OPENSSL_free(row[DB_srpsalt]); - goto err; + if ((row[DB_srpid] == NULL) + || (row[DB_srpgN] == NULL) + || (row[DB_srptype] == NULL) + || (row[DB_srpverifier] == NULL) + || (row[DB_srpsalt] == NULL) + || (userinfo + && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) == NULL)) + || !update_index(db, row)) { + OPENSSL_free(row[DB_srpid]); + OPENSSL_free(row[DB_srpgN]); + OPENSSL_free(row[DB_srpinfo]); + OPENSSL_free(row[DB_srptype]); + OPENSSL_free(row[DB_srpverifier]); + OPENSSL_free(row[DB_srpsalt]); + goto end; } doupdatedb = 1; } - } else if (modify_user) { + } else if (mode == OPT_MODIFY) { if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored.\n", @@ -646,31 +487,31 @@ int MAIN(int argc, char **argv) if (row[DB_srptype][0] == 'V') { int user_gN; char **irow = NULL; - VERBOSE BIO_printf(bio_err, - "Verifying password for user \"%s\"\n", - user); + if (verbose) + BIO_printf(bio_err, + "Verifying password for user \"%s\"\n", + user); if ((user_gN = get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0) irow = - (char **)sk_OPENSSL_PSTRING_value(db-> - db->data, - userindex); + sk_OPENSSL_PSTRING_value(db->db->data, + userindex); if (!srp_verify_user (user, row[DB_srpverifier], row[DB_srpsalt], irow ? irow[DB_srpsalt] : row[DB_srpgN], irow ? irow[DB_srpverifier] : NULL, passin, - bio_err, verbose)) { + verbose)) { BIO_printf(bio_err, "Invalid password for user \"%s\", operation abandoned.\n", user); errors++; - goto err; + goto end; } } - VERBOSE BIO_printf(bio_err, - "Password for user \"%s\" ok.\n", - user); + if (verbose) + BIO_printf(bio_err, "Password for user \"%s\" ok.\n", + user); if (! (gNid = @@ -678,51 +519,53 @@ int MAIN(int argc, char **argv) &(row[DB_srpsalt]), gNrow ? gNrow[DB_srpsalt] : NULL, gNrow ? gNrow[DB_srpverifier] : NULL, - passout, bio_err, verbose))) { + passout, verbose))) { BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user); errors++; - goto err; + goto end; } row[DB_srptype][0] = 'v'; - row[DB_srpgN] = BUF_strdup(gNid); + row[DB_srpgN] = OPENSSL_strdup(gNid); - if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] - || !row[DB_srpverifier] || !row[DB_srpsalt] + if (row[DB_srpid] == NULL + || row[DB_srpgN] == NULL + || row[DB_srptype] == NULL + || row[DB_srpverifier] == NULL + || row[DB_srpsalt] == NULL || (userinfo - && (!(row[DB_srpinfo] = BUF_strdup(userinfo))))) - goto err; + && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) + == NULL))) + goto end; doupdatedb = 1; } } - } else if (delete_user) { + } else if (mode == OPT_DELETE) { if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored. t\n", user); errors++; } else { - char **xpp = - sk_OPENSSL_PSTRING_value(db->db->data, userindex); - BIO_printf(bio_err, "user \"%s\" revoked. t\n", user); + char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex); + BIO_printf(bio_err, "user \"%s\" revoked. t\n", user); xpp[DB_srptype][0] = 'R'; - doupdatedb = 1; } } - if (--argc > 0) { - user = *(argv++); - } else { - user = NULL; - list_user = 0; + user = *argv++; + if (user == NULL) { + /* no more processing in any mode if no users left */ + break; } } - VERBOSE BIO_printf(bio_err, "User procession done.\n"); + if (verbose) + BIO_printf(bio_err, "User procession done.\n"); if (doupdatedb) { /* Lets check some fields */ @@ -731,44 +574,40 @@ int MAIN(int argc, char **argv) if (pp[DB_srptype][0] == 'v') { pp[DB_srptype][0] = 'V'; - print_user(db, bio_err, i, verbose); + print_user(db, i, verbose); } } - VERBOSE BIO_printf(bio_err, "Trying to update srpvfile.\n"); - if (!save_index(dbfile, "new", db)) - goto err; + if (verbose) + BIO_printf(bio_err, "Trying to update srpvfile.\n"); + if (!save_index(srpvfile, "new", db)) + goto end; - VERBOSE BIO_printf(bio_err, "Temporary srpvfile created.\n"); - if (!rotate_index(dbfile, "new", "old")) - goto err; + if (verbose) + BIO_printf(bio_err, "Temporary srpvfile created.\n"); + if (!rotate_index(srpvfile, "new", "old")) + goto end; - VERBOSE BIO_printf(bio_err, "srpvfile updated.\n"); + if (verbose) + BIO_printf(bio_err, "srpvfile updated.\n"); } ret = (errors != 0); - err: + end: if (errors != 0) - VERBOSE BIO_printf(bio_err, "User errors %d.\n", errors); + if (verbose) + BIO_printf(bio_err, "User errors %d.\n", errors); + + if (verbose) + BIO_printf(bio_err, "SRP terminating with code %d.\n", ret); - VERBOSE BIO_printf(bio_err, "SRP terminating with code %d.\n", ret); - if (tofree) - OPENSSL_free(tofree); + OPENSSL_free(passin); + OPENSSL_free(passout); if (ret) ERR_print_errors(bio_err); - if (randfile) - app_RAND_write_file(randfile, bio_err); - if (conf) - NCONF_free(conf); - if (db) - free_index(db); - + NCONF_free(conf); + free_index(db); release_engine(e); - OBJ_cleanup(); - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } - -#else -static void *dummy = &dummy; #endif diff --git a/apps/storeutl.c b/apps/storeutl.c new file mode 100644 index 000000000000..50007f6e8b69 --- /dev/null +++ b/apps/storeutl.c @@ -0,0 +1,473 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/opensslconf.h> + +#include "apps.h" +#include "progs.h" +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/store.h> +#include <openssl/x509v3.h> /* s2i_ASN1_INTEGER */ + +static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, + int expected, int criterion, OSSL_STORE_SEARCH *search, + int text, int noout, int recursive, int indent, BIO *out, + const char *prog); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN, + OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE, + OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS, + OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL, + OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS, + OPT_MD +} OPTION_CHOICE; + +const OPTIONS storeutl_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"text", OPT_TEXT, '-', "Print a text form of the objects"}, + {"noout", OPT_NOOUT, '-', "No PEM output, just status"}, + {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"}, + {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"}, + {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"}, + {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"}, + {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"}, + {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"}, + {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"}, + {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"r", OPT_RECURSIVE, '-', "Recurse through names"}, + {NULL} +}; + +int storeutl_main(int argc, char *argv[]) +{ + int ret = 1, noout = 0, text = 0, recursive = 0; + char *outfile = NULL, *passin = NULL, *passinarg = NULL; + BIO *out = NULL; + ENGINE *e = NULL; + OPTION_CHOICE o; + char *prog = opt_init(argc, argv, storeutl_options); + PW_CB_DATA pw_cb_data; + int expected = 0; + int criterion = 0; + X509_NAME *subject = NULL, *issuer = NULL; + ASN1_INTEGER *serial = NULL; + unsigned char *fingerprint = NULL; + size_t fingerprintlen = 0; + char *alias = NULL; + OSSL_STORE_SEARCH *search = NULL; + const EVP_MD *digest = NULL; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(storeutl_options); + ret = 0; + goto end; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_RECURSIVE: + recursive = 1; + break; + case OPT_SEARCHFOR_CERTS: + case OPT_SEARCHFOR_KEYS: + case OPT_SEARCHFOR_CRLS: + if (expected != 0) { + BIO_printf(bio_err, "%s: only one search type can be given.\n", + prog); + goto end; + } + { + static const struct { + enum OPTION_choice choice; + int type; + } map[] = { + {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT}, + {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY}, + {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL}, + }; + size_t i; + + for (i = 0; i < OSSL_NELEM(map); i++) { + if (o == map[i].choice) { + expected = map[i].type; + break; + } + } + /* + * If expected wasn't set at this point, it means the map + * isn't syncronised with the possible options leading here. + */ + OPENSSL_assert(expected != 0); + } + break; + case OPT_CRITERION_SUBJECT: + if (criterion != 0) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_NAME; + if (subject != NULL) { + BIO_printf(bio_err, "%s: subject already given.\n", + prog); + goto end; + } + if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { + BIO_printf(bio_err, "%s: can't parse subject argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_ISSUER: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL + && issuer != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + if (issuer != NULL) { + BIO_printf(bio_err, "%s: issuer already given.\n", + prog); + goto end; + } + if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { + BIO_printf(bio_err, "%s: can't parse issuer argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_SERIAL: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL + && serial != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + if (serial != NULL) { + BIO_printf(bio_err, "%s: serial number already given.\n", + prog); + goto end; + } + if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) { + BIO_printf(bio_err, "%s: can't parse serial number argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_FINGERPRINT: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT + && fingerprint != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT; + if (fingerprint != NULL) { + BIO_printf(bio_err, "%s: fingerprint already given.\n", + prog); + goto end; + } + { + long tmplen = 0; + + if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen)) + == NULL) { + BIO_printf(bio_err, + "%s: can't parse fingerprint argument.\n", + prog); + goto end; + } + fingerprintlen = (size_t)tmplen; + } + break; + case OPT_CRITERION_ALIAS: + if (criterion != 0) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ALIAS; + if (alias != NULL) { + BIO_printf(bio_err, "%s: alias already given.\n", + prog); + goto end; + } + if ((alias = OPENSSL_strdup(opt_arg())) == NULL) { + BIO_printf(bio_err, "%s: can't parse alias argument.\n", + prog); + goto end; + } + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &digest)) + goto opthelp; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (argc == 0) { + BIO_printf(bio_err, "%s: No URI given, nothing to do...\n", prog); + goto opthelp; + } + if (argc > 1) { + BIO_printf(bio_err, "%s: Unknown extra parameters after URI\n", prog); + goto opthelp; + } + + if (criterion != 0) { + switch (criterion) { + case OSSL_STORE_SEARCH_BY_NAME: + if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL: + if (issuer == NULL || serial == NULL) { + BIO_printf(bio_err, + "%s: both -issuer and -serial must be given.\n", + prog); + goto end; + } + if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial)) + == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT: + if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest, + fingerprint, + fingerprintlen)) + == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_ALIAS: + if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + } + } + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + pw_cb_data.password = passin; + pw_cb_data.prompt_info = argv[0]; + + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) + goto end; + + ret = process(argv[0], get_ui_method(), &pw_cb_data, + expected, criterion, search, + text, noout, recursive, 0, out, prog); + + end: + OPENSSL_free(fingerprint); + OPENSSL_free(alias); + ASN1_INTEGER_free(serial); + X509_NAME_free(subject); + X509_NAME_free(issuer); + OSSL_STORE_SEARCH_free(search); + BIO_free_all(out); + OPENSSL_free(passin); + release_engine(e); + return ret; +} + +static int indent_printf(int indent, BIO *bio, const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_printf(bio, "%*s", indent, "") + BIO_vprintf(bio, format, args); + + va_end(args); + return ret; +} + +static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, + int expected, int criterion, OSSL_STORE_SEARCH *search, + int text, int noout, int recursive, int indent, BIO *out, + const char *prog) +{ + OSSL_STORE_CTX *store_ctx = NULL; + int ret = 1, items = 0; + + if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL)) + == NULL) { + BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri); + ERR_print_errors(bio_err); + return ret; + } + + if (expected != 0) { + if (!OSSL_STORE_expect(store_ctx, expected)) { + ERR_print_errors(bio_err); + goto end2; + } + } + + if (criterion != 0) { + if (!OSSL_STORE_supports_search(store_ctx, criterion)) { + BIO_printf(bio_err, + "%s: the store scheme doesn't support the given search criteria.\n", + prog); + goto end2; + } + + if (!OSSL_STORE_find(store_ctx, search)) { + ERR_print_errors(bio_err); + goto end2; + } + } + + /* From here on, we count errors, and we'll return the count at the end */ + ret = 0; + + for (;;) { + OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx); + int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info); + const char *infostr = + info == NULL ? NULL : OSSL_STORE_INFO_type_string(type); + + if (info == NULL) { + if (OSSL_STORE_eof(store_ctx)) + break; + + if (OSSL_STORE_error(store_ctx)) { + if (recursive) + ERR_clear_error(); + else + ERR_print_errors(bio_err); + ret++; + continue; + } + + BIO_printf(bio_err, + "ERROR: OSSL_STORE_load() returned NULL without " + "eof or error indications\n"); + BIO_printf(bio_err, " This is an error in the loader\n"); + ERR_print_errors(bio_err); + ret++; + break; + } + + if (type == OSSL_STORE_INFO_NAME) { + const char *name = OSSL_STORE_INFO_get0_NAME(info); + const char *desc = OSSL_STORE_INFO_get0_NAME_description(info); + indent_printf(indent, bio_out, "%d: %s: %s\n", items, infostr, + name); + if (desc != NULL) + indent_printf(indent, bio_out, "%s\n", desc); + } else { + indent_printf(indent, bio_out, "%d: %s\n", items, infostr); + } + + /* + * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in + * functionality, so we must figure out how exactly to write things + * ourselves... + */ + switch (type) { + case OSSL_STORE_INFO_NAME: + if (recursive) { + const char *suburi = OSSL_STORE_INFO_get0_NAME(info); + ret += process(suburi, uimeth, uidata, + expected, criterion, search, + text, noout, recursive, indent + 2, out, prog); + } + break; + case OSSL_STORE_INFO_PARAMS: + if (text) + EVP_PKEY_print_params(out, OSSL_STORE_INFO_get0_PARAMS(info), + 0, NULL); + if (!noout) + PEM_write_bio_Parameters(out, + OSSL_STORE_INFO_get0_PARAMS(info)); + break; + case OSSL_STORE_INFO_PKEY: + if (text) + EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info), + 0, NULL); + if (!noout) + PEM_write_bio_PrivateKey(out, OSSL_STORE_INFO_get0_PKEY(info), + NULL, NULL, 0, NULL, NULL); + break; + case OSSL_STORE_INFO_CERT: + if (text) + X509_print(out, OSSL_STORE_INFO_get0_CERT(info)); + if (!noout) + PEM_write_bio_X509(out, OSSL_STORE_INFO_get0_CERT(info)); + break; + case OSSL_STORE_INFO_CRL: + if (text) + X509_CRL_print(out, OSSL_STORE_INFO_get0_CRL(info)); + if (!noout) + PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info)); + break; + default: + BIO_printf(bio_err, "!!! Unknown code\n"); + ret++; + break; + } + items++; + OSSL_STORE_INFO_free(info); + } + indent_printf(indent, out, "Total found: %d\n", items); + + end2: + if (!OSSL_STORE_close(store_ctx)) { + ERR_print_errors(bio_err); + ret++; + } + + return ret; +} diff --git a/apps/testdsa.h b/apps/testdsa.h index 550c6253e69e..3c4b459db117 100644 --- a/apps/testdsa.h +++ b/apps/testdsa.h @@ -1,8 +1,15 @@ -/* NOCW */ -/* used by apps/speed.c */ -DSA *get_dsa512(void); -DSA *get_dsa1024(void); -DSA *get_dsa2048(void); +/* + * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* used by speed.c */ +DSA *get_dsa(int); + static unsigned char dsa512_priv[] = { 0x65, 0xe5, 0xc7, 0x38, 0x60, 0x24, 0xb5, 0x89, 0xd4, 0x9c, 0xeb, 0x4c, 0x9c, 0x1d, 0x7a, 0x22, 0xbd, 0xd1, 0xc2, 0xd2, @@ -40,23 +47,6 @@ static unsigned char dsa512_g[] = { 0xA2, 0x03, 0x9D, 0x20, }; -DSA *get_dsa512() -{ - DSA *dsa; - - if ((dsa = DSA_new()) == NULL) - return (NULL); - dsa->priv_key = BN_bin2bn(dsa512_priv, sizeof(dsa512_priv), NULL); - dsa->pub_key = BN_bin2bn(dsa512_pub, sizeof(dsa512_pub), NULL); - dsa->p = BN_bin2bn(dsa512_p, sizeof(dsa512_p), NULL); - dsa->q = BN_bin2bn(dsa512_q, sizeof(dsa512_q), NULL); - dsa->g = BN_bin2bn(dsa512_g, sizeof(dsa512_g), NULL); - if ((dsa->priv_key == NULL) || (dsa->pub_key == NULL) || (dsa->p == NULL) - || (dsa->q == NULL) || (dsa->g == NULL)) - return (NULL); - return (dsa); -} - static unsigned char dsa1024_priv[] = { 0x7d, 0x21, 0xda, 0xbb, 0x62, 0x15, 0x47, 0x36, 0x07, 0x67, 0x12, 0xe8, 0x8c, 0xaa, 0x1c, 0xcd, 0x38, 0x12, 0x61, 0x18, @@ -109,23 +99,6 @@ static unsigned char dsa1024_g[] = { 0x6A, 0x7E, 0xD8, 0x32, 0xED, 0x0E, 0x02, 0xB8, }; -DSA *get_dsa1024() -{ - DSA *dsa; - - if ((dsa = DSA_new()) == NULL) - return (NULL); - dsa->priv_key = BN_bin2bn(dsa1024_priv, sizeof(dsa1024_priv), NULL); - dsa->pub_key = BN_bin2bn(dsa1024_pub, sizeof(dsa1024_pub), NULL); - dsa->p = BN_bin2bn(dsa1024_p, sizeof(dsa1024_p), NULL); - dsa->q = BN_bin2bn(dsa1024_q, sizeof(dsa1024_q), NULL); - dsa->g = BN_bin2bn(dsa1024_g, sizeof(dsa1024_g), NULL); - if ((dsa->priv_key == NULL) || (dsa->pub_key == NULL) || (dsa->p == NULL) - || (dsa->q == NULL) || (dsa->g == NULL)) - return (NULL); - return (dsa); -} - static unsigned char dsa2048_priv[] = { 0x32, 0x67, 0x92, 0xf6, 0xc4, 0xe2, 0xe2, 0xe8, 0xa0, 0x8b, 0x6b, 0x45, 0x0c, 0x8a, 0x76, 0xb0, 0xee, 0xcf, 0x91, 0xa7, @@ -211,23 +184,77 @@ static unsigned char dsa2048_g[] = { 0xF8, 0xB2, 0xE5, 0x38, }; -DSA *get_dsa2048() +typedef struct testdsa_st { + unsigned char *priv; + unsigned char *pub; + unsigned char *p; + unsigned char *g; + unsigned char *q; + int priv_l; + int pub_l; + int p_l; + int g_l; + int q_l; +} testdsa; + +#define set_dsa_ptr(st, bits) \ + do { \ + st.priv = dsa##bits##_priv; \ + st.pub = dsa##bits##_pub; \ + st.p = dsa##bits##_p; \ + st.g = dsa##bits##_g; \ + st.q = dsa##bits##_q; \ + st.priv_l = sizeof(dsa##bits##_priv); \ + st.pub_l = sizeof(dsa##bits##_pub); \ + st.p_l = sizeof(dsa##bits##_p); \ + st.g_l = sizeof(dsa##bits##_g); \ + st.q_l = sizeof(dsa##bits##_q); \ + } while (0) + +DSA *get_dsa(int dsa_bits) { DSA *dsa; + BIGNUM *priv_key, *pub_key, *p, *q, *g; + testdsa dsa_t; + + switch (dsa_bits) { + case 512: + set_dsa_ptr(dsa_t, 512); + break; + case 1024: + set_dsa_ptr(dsa_t, 1024); + break; + case 2048: + set_dsa_ptr(dsa_t, 2048); + break; + default: + return NULL; + } if ((dsa = DSA_new()) == NULL) - return (NULL); - dsa->priv_key = BN_bin2bn(dsa2048_priv, sizeof(dsa2048_priv), NULL); - dsa->pub_key = BN_bin2bn(dsa2048_pub, sizeof(dsa2048_pub), NULL); - dsa->p = BN_bin2bn(dsa2048_p, sizeof(dsa2048_p), NULL); - dsa->q = BN_bin2bn(dsa2048_q, sizeof(dsa2048_q), NULL); - dsa->g = BN_bin2bn(dsa2048_g, sizeof(dsa2048_g), NULL); - if ((dsa->priv_key == NULL) || (dsa->pub_key == NULL) || (dsa->p == NULL) - || (dsa->q == NULL) || (dsa->g == NULL)) - return (NULL); - return (dsa); -} + return NULL; + priv_key = BN_bin2bn(dsa_t.priv, dsa_t.priv_l, NULL); + pub_key = BN_bin2bn(dsa_t.pub, dsa_t.pub_l, NULL); + p = BN_bin2bn(dsa_t.p, dsa_t.p_l, NULL); + q = BN_bin2bn(dsa_t.q, dsa_t.q_l, NULL); + g = BN_bin2bn(dsa_t.g, dsa_t.g_l, NULL); + if ((priv_key == NULL) || (pub_key == NULL) || (p == NULL) || (q == NULL) + || (g == NULL)) { + goto err; + } + if (!DSA_set0_pqg(dsa, p, q, g)) + goto err; -static const char rnd_seed[] = - "string to make the random number generator think it has entropy"; -static int rnd_fake = 0; + if (!DSA_set0_key(dsa, pub_key, priv_key)) + goto err; + + return dsa; + err: + DSA_free(dsa); + BN_free(priv_key); + BN_free(pub_key); + BN_free(p); + BN_free(q); + BN_free(g); + return NULL; +} diff --git a/apps/testrsa.h b/apps/testrsa.h index a7913fdd74e4..1350ce54e3fb 100644 --- a/apps/testrsa.h +++ b/apps/testrsa.h @@ -1,60 +1,10 @@ -/* apps/testrsa.h */ -/* used by apps/speed.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ static unsigned char test512[] = { @@ -279,6 +229,186 @@ static unsigned char test2048[] = { 0x95, }; +static unsigned char test3072[] = { + 0x30, 0x82, 0x06, 0xe3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x81, 0x00, 0xbc, 0x3b, 0x23, 0xc0, 0x33, 0xa7, 0x8b, 0xaa, + 0xca, 0xa3, 0x8c, 0x94, 0xf2, 0x4c, 0x52, 0x08, 0x85, 0x80, + 0xfc, 0x36, 0x15, 0xfa, 0x03, 0x06, 0xb6, 0xd6, 0x3f, 0x60, + 0x8a, 0x89, 0x0d, 0xba, 0x1a, 0x51, 0x0b, 0x12, 0xea, 0x71, + 0x77, 0xf6, 0x3a, 0x30, 0x21, 0x3d, 0x24, 0xf8, 0x2e, 0xd0, + 0x17, 0x3a, 0x85, 0x94, 0x25, 0x42, 0x89, 0xff, 0x6a, 0x68, + 0xdf, 0x1f, 0x86, 0xae, 0xa5, 0xbb, 0x9a, 0x79, 0xf6, 0x69, + 0x94, 0xfe, 0xde, 0xfe, 0xce, 0x1b, 0x2e, 0xae, 0x1d, 0x91, + 0xcb, 0xb9, 0xf1, 0x2d, 0xd8, 0x00, 0x82, 0x51, 0x8e, 0xf9, + 0xfd, 0xac, 0xf1, 0x0e, 0x7f, 0xb7, 0x95, 0x85, 0x35, 0xf9, + 0xcb, 0xbe, 0x5f, 0xd3, 0x58, 0xe3, 0xa1, 0x54, 0x9e, 0x30, + 0xb1, 0x8d, 0x01, 0x97, 0x82, 0x06, 0x8e, 0x77, 0xfb, 0xce, + 0x50, 0x2f, 0xbf, 0xf1, 0xff, 0x57, 0x0a, 0x42, 0x03, 0xfd, + 0x0e, 0xba, 0x1e, 0xca, 0x85, 0xc1, 0x9b, 0xa5, 0x9d, 0x09, + 0x0e, 0xe9, 0xbb, 0xc5, 0x73, 0x47, 0x0d, 0x39, 0x3c, 0x64, + 0x06, 0x9a, 0x79, 0x3f, 0x50, 0x87, 0x9c, 0x18, 0x2d, 0x62, + 0x01, 0xfc, 0xed, 0xc1, 0x58, 0x28, 0x21, 0x94, 0x1e, 0xf9, + 0x2d, 0x96, 0x4f, 0xd0, 0xbc, 0xf1, 0xe0, 0x8a, 0xfa, 0x4d, + 0xb6, 0x78, 0x4a, 0xde, 0x17, 0x59, 0xb0, 0x22, 0xa0, 0x9a, + 0xd3, 0x70, 0xb6, 0xc2, 0xbe, 0xbc, 0x96, 0xca, 0x41, 0x5f, + 0x58, 0x4e, 0xce, 0xef, 0x64, 0x45, 0xdd, 0x3f, 0x81, 0x92, + 0xcc, 0x40, 0x79, 0xfc, 0x19, 0xe2, 0xbc, 0x77, 0x2f, 0x43, + 0xfb, 0x8e, 0xad, 0x82, 0x4a, 0x0b, 0xb1, 0xbc, 0x09, 0x8a, + 0x80, 0xc3, 0x0f, 0xef, 0xd2, 0x06, 0xd3, 0x4b, 0x0c, 0x7f, + 0xae, 0x60, 0x3f, 0x2e, 0x52, 0xb4, 0xe4, 0xc2, 0x5c, 0xa6, + 0x71, 0xc0, 0x13, 0x9c, 0xca, 0xa6, 0x0d, 0x13, 0xd7, 0xb7, + 0x14, 0x94, 0x3f, 0x0d, 0x8b, 0x06, 0x70, 0x2f, 0x15, 0x82, + 0x8d, 0x47, 0x45, 0xa6, 0x00, 0x8a, 0x14, 0x91, 0xde, 0x2f, + 0x50, 0x17, 0xe3, 0x1d, 0x34, 0x29, 0x8c, 0xe4, 0x57, 0x74, + 0x2a, 0x3a, 0x82, 0x65, 0x26, 0xf7, 0x8d, 0xcc, 0x1b, 0x8f, + 0xaf, 0xe5, 0x85, 0xe5, 0xbe, 0x85, 0xd6, 0xb7, 0x04, 0xe8, + 0xf5, 0xd4, 0x74, 0xe2, 0x54, 0x14, 0xdd, 0x58, 0xcf, 0x1f, + 0x11, 0x8a, 0x9f, 0x82, 0xa2, 0x01, 0xf9, 0xc2, 0xdf, 0x7b, + 0x84, 0xb1, 0xd8, 0x5b, 0x70, 0xbb, 0x24, 0xe7, 0xd0, 0x2a, + 0x75, 0x3d, 0x55, 0xac, 0x45, 0xe9, 0xab, 0xc6, 0x84, 0x8a, + 0xe7, 0x6d, 0x26, 0x12, 0x89, 0xb5, 0x67, 0xe8, 0x46, 0x9d, + 0x46, 0x1a, 0xfa, 0x2d, 0xc0, 0x5b, 0x60, 0x46, 0x8b, 0xb7, + 0x32, 0x03, 0xff, 0x75, 0xee, 0x9f, 0x3c, 0xdd, 0xb6, 0x35, + 0x4e, 0x82, 0xbd, 0x99, 0x73, 0x51, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x01, 0x80, 0x42, 0xee, 0xa4, 0x9f, 0xcb, + 0xbe, 0x60, 0x23, 0xb3, 0x3a, 0xc4, 0xda, 0x91, 0xee, 0x21, + 0x9d, 0x76, 0x1b, 0x8f, 0x93, 0x8b, 0xed, 0x02, 0xf6, 0x78, + 0x3d, 0x66, 0xfb, 0xe5, 0x47, 0x26, 0xe2, 0x6e, 0x49, 0x33, + 0x2e, 0xde, 0xbe, 0xca, 0x71, 0x7b, 0xef, 0x71, 0x62, 0x54, + 0xab, 0x0b, 0xba, 0x63, 0x08, 0x24, 0x47, 0xb1, 0x98, 0x1f, + 0x89, 0xfb, 0x44, 0x9f, 0x52, 0x8e, 0x89, 0xbb, 0xd5, 0x21, + 0xf1, 0x0c, 0x76, 0x2e, 0xcd, 0x12, 0x6e, 0x78, 0xcb, 0xa1, + 0xa5, 0xb8, 0x4e, 0x07, 0xab, 0x6e, 0xdf, 0x66, 0x57, 0x87, + 0xff, 0x88, 0x5f, 0xcc, 0x9c, 0x9a, 0x7b, 0x15, 0x5f, 0x2a, + 0x83, 0xdb, 0xd5, 0x9f, 0x65, 0x6a, 0x9d, 0xb4, 0x95, 0xfc, + 0xe0, 0x22, 0x00, 0x1e, 0xa2, 0x8d, 0x56, 0x5a, 0x9e, 0x0a, + 0x3b, 0x10, 0x07, 0x24, 0xec, 0x55, 0xcc, 0xaf, 0x87, 0x3b, + 0xd6, 0x8d, 0xa4, 0x86, 0x80, 0x18, 0x42, 0xdb, 0x9d, 0x24, + 0xc3, 0x97, 0x3b, 0x89, 0x5a, 0x03, 0xb3, 0x0a, 0x72, 0xd1, + 0x78, 0xf0, 0xc8, 0x80, 0xb0, 0x9d, 0x3c, 0xae, 0x5e, 0x0a, + 0x5b, 0x6e, 0x87, 0xd3, 0x3d, 0x25, 0x2e, 0x03, 0x33, 0x01, + 0xfd, 0xb1, 0xa5, 0xd9, 0x58, 0x01, 0xb9, 0xaf, 0xf6, 0x32, + 0x6a, 0x38, 0xe7, 0x39, 0x63, 0x3c, 0xfc, 0x0c, 0x41, 0x90, + 0x28, 0x40, 0x03, 0xcd, 0xfb, 0xde, 0x80, 0x74, 0x21, 0xaa, + 0xae, 0x58, 0xe9, 0x97, 0x18, 0x85, 0x58, 0x3d, 0x2b, 0xd6, + 0x61, 0xf6, 0xe8, 0xbc, 0x6d, 0x2a, 0xf3, 0xb8, 0xea, 0x8c, + 0x64, 0x44, 0xc6, 0xd3, 0x9f, 0x00, 0x7b, 0xb2, 0x52, 0x18, + 0x11, 0x04, 0x96, 0xb7, 0x05, 0xbb, 0xc2, 0x38, 0x5b, 0xa7, + 0x0a, 0x84, 0xb6, 0x4f, 0x02, 0x63, 0xa4, 0x57, 0x00, 0xe3, + 0xde, 0xe4, 0xf2, 0xb3, 0x55, 0xd9, 0x00, 0xa9, 0xd2, 0x5c, + 0x69, 0x9f, 0xe5, 0x80, 0x4f, 0x23, 0x7c, 0xd9, 0xa7, 0x77, + 0x4a, 0xbb, 0x09, 0x6d, 0x45, 0x02, 0xcf, 0x32, 0x90, 0xfd, + 0x10, 0xb6, 0xb3, 0x93, 0xd9, 0x3b, 0x1d, 0x57, 0x66, 0xb5, + 0xb3, 0xb1, 0x6e, 0x53, 0x5f, 0x04, 0x60, 0x29, 0xcd, 0xe8, + 0xb8, 0xab, 0x62, 0x82, 0x33, 0x40, 0xc7, 0xf8, 0x64, 0x60, + 0x0e, 0xab, 0x06, 0x3e, 0xa0, 0xa3, 0x62, 0x11, 0x3f, 0x67, + 0x5d, 0x24, 0x9e, 0x60, 0x29, 0xdc, 0x4c, 0xd5, 0x13, 0xee, + 0x3d, 0xb7, 0x84, 0x93, 0x27, 0xb5, 0x6a, 0xf9, 0xf0, 0xdd, + 0x50, 0xac, 0x46, 0x3c, 0xe6, 0xd5, 0xec, 0xf7, 0xb7, 0x9f, + 0x23, 0x39, 0x9c, 0x88, 0x8c, 0x5a, 0x62, 0x3f, 0x8d, 0x4a, + 0xd7, 0xeb, 0x5e, 0x1e, 0x49, 0xf8, 0xa9, 0x53, 0x11, 0x75, + 0xd0, 0x43, 0x1e, 0xc7, 0x29, 0x22, 0x80, 0x1f, 0xc5, 0x83, + 0x8d, 0x20, 0x04, 0x87, 0x7f, 0x57, 0x8c, 0xf5, 0xa1, 0x02, + 0x81, 0xc1, 0x00, 0xf7, 0xaa, 0xf5, 0xa5, 0x00, 0xdb, 0xd6, + 0x11, 0xfc, 0x07, 0x6d, 0x22, 0x24, 0x2b, 0x4b, 0xc5, 0x67, + 0x0f, 0x37, 0xa5, 0xdb, 0x8f, 0x38, 0xe2, 0x05, 0x43, 0x9a, + 0x44, 0x05, 0x3f, 0xa9, 0xac, 0x4c, 0x98, 0x3c, 0x72, 0x38, + 0xc3, 0x89, 0x33, 0x58, 0x73, 0x51, 0xcc, 0x5d, 0x2f, 0x8f, + 0x6d, 0x3f, 0xa1, 0x22, 0x9e, 0xfb, 0x9a, 0xb4, 0xb8, 0x79, + 0x95, 0xaf, 0x83, 0xcf, 0x5a, 0xb7, 0x14, 0x14, 0x0c, 0x51, + 0x8a, 0x11, 0xe6, 0xd6, 0x21, 0x1e, 0x17, 0x13, 0xd3, 0x69, + 0x7a, 0x3a, 0xd5, 0xaf, 0x3f, 0xb8, 0x25, 0x01, 0xcb, 0x2b, + 0xe6, 0xfc, 0x03, 0xd8, 0xd4, 0xf7, 0x20, 0xe0, 0x21, 0xef, + 0x1a, 0xca, 0x61, 0xeb, 0x8e, 0x96, 0x45, 0x8e, 0x5c, 0xe6, + 0x81, 0x0b, 0x2d, 0x05, 0x32, 0xf9, 0x41, 0x62, 0xb4, 0x33, + 0x98, 0x10, 0x3a, 0xcd, 0xf0, 0x7a, 0x8b, 0x1a, 0x48, 0xd7, + 0x3b, 0x01, 0xf5, 0x18, 0x65, 0x8f, 0x3c, 0xc2, 0x31, 0x3b, + 0xd3, 0xa7, 0x17, 0x5f, 0x7c, 0x0c, 0xe7, 0x25, 0x18, 0x5a, + 0x08, 0xe1, 0x09, 0x89, 0x13, 0xa7, 0xc5, 0x12, 0xab, 0x88, + 0x30, 0xcd, 0x06, 0xf9, 0xba, 0x6f, 0xca, 0x9c, 0x8a, 0xda, + 0x3e, 0x53, 0x90, 0xd7, 0x16, 0x2e, 0xfc, 0xbc, 0xad, 0xd6, + 0x3d, 0xc0, 0x66, 0x4c, 0x02, 0x3d, 0x31, 0xfd, 0x6c, 0xdb, + 0x1c, 0xdf, 0x96, 0x33, 0x23, 0x02, 0x81, 0xc1, 0x00, 0xc2, + 0x90, 0x47, 0xc4, 0xfb, 0x59, 0xf0, 0xc5, 0x14, 0x75, 0x29, + 0xfa, 0x77, 0xa1, 0x8d, 0xd4, 0x90, 0xa1, 0x0d, 0x3f, 0x16, + 0x88, 0xe3, 0x4c, 0x8f, 0x8f, 0x18, 0x8c, 0x9c, 0x8a, 0xd5, + 0xa7, 0x41, 0x99, 0xf3, 0x80, 0x8e, 0xb1, 0xb8, 0x63, 0xd8, + 0x3f, 0x95, 0xd0, 0xd0, 0x2b, 0xf5, 0xe6, 0x93, 0xe8, 0xfe, + 0xd0, 0x73, 0xd5, 0xbd, 0xb4, 0xee, 0x51, 0x19, 0x6a, 0x10, + 0xca, 0xc8, 0xba, 0xa4, 0x4d, 0x84, 0x54, 0x38, 0x17, 0xb5, + 0xd0, 0xa8, 0x75, 0x22, 0xc5, 0x1b, 0x61, 0xa6, 0x51, 0x88, + 0x63, 0xf0, 0x4f, 0xd1, 0x88, 0xd9, 0x16, 0x49, 0x30, 0xe1, + 0xa8, 0x47, 0xc9, 0x30, 0x1d, 0x5c, 0x75, 0xd8, 0x89, 0xb6, + 0x1d, 0x45, 0xd8, 0x0f, 0x94, 0x89, 0xb3, 0xe4, 0x51, 0xfa, + 0x21, 0xff, 0x6f, 0xb6, 0x30, 0x6f, 0x33, 0x24, 0xbc, 0x09, + 0x98, 0xe9, 0x20, 0x02, 0x0b, 0xde, 0xff, 0xc5, 0x06, 0xb6, + 0x28, 0xa3, 0xa1, 0x07, 0xe8, 0xe1, 0xd2, 0xc2, 0xf1, 0xd1, + 0x23, 0x6b, 0x4c, 0x3a, 0xae, 0x85, 0xec, 0xf9, 0xff, 0xa7, + 0x9b, 0x25, 0xb8, 0x95, 0x1d, 0xa8, 0x14, 0x81, 0x4f, 0x79, + 0x4f, 0xd6, 0x39, 0x5d, 0xe6, 0x5f, 0xd2, 0x34, 0x54, 0x8b, + 0x1e, 0x40, 0x4c, 0x15, 0x5a, 0x45, 0xce, 0x0c, 0xb0, 0xdf, + 0xa1, 0x17, 0xb8, 0xb0, 0x6a, 0x82, 0xa5, 0x97, 0x92, 0x70, + 0xfb, 0x02, 0x81, 0xc0, 0x77, 0x46, 0x44, 0x2b, 0x04, 0xf0, + 0xda, 0x75, 0xaa, 0xd4, 0xc0, 0xc0, 0x32, 0x7f, 0x0f, 0x6c, + 0xb0, 0x27, 0x69, 0xfb, 0x5c, 0x73, 0xeb, 0x47, 0x1e, 0x95, + 0xe2, 0x13, 0x64, 0x1b, 0xb6, 0xd1, 0x1d, 0xca, 0x2b, 0x42, + 0x2f, 0x08, 0x2c, 0x69, 0x27, 0xed, 0xd1, 0xb5, 0x04, 0x23, + 0xc5, 0x85, 0x2d, 0xa1, 0xa2, 0x94, 0xc2, 0x43, 0x4d, 0x49, + 0x92, 0x74, 0x7e, 0x24, 0x92, 0x95, 0xf3, 0x99, 0x9d, 0xd6, + 0x18, 0xe6, 0xcf, 0x9c, 0x45, 0xff, 0x89, 0x08, 0x40, 0x2a, + 0x0e, 0xa0, 0x28, 0xf9, 0x83, 0xfe, 0xc1, 0xe6, 0x40, 0xa8, + 0xe2, 0x29, 0xc9, 0xb0, 0xe8, 0x9a, 0x17, 0xb2, 0x23, 0x7e, + 0xf4, 0x32, 0x08, 0xc9, 0x83, 0xb2, 0x15, 0xb8, 0xc5, 0xc9, + 0x03, 0xd1, 0x9d, 0xda, 0x3e, 0xa8, 0xbf, 0xd5, 0xb7, 0x7d, + 0x65, 0x63, 0x94, 0x5d, 0x5d, 0x94, 0xb4, 0xcf, 0x8d, 0x07, + 0x0b, 0x70, 0x85, 0x8e, 0xce, 0x03, 0x0b, 0x2a, 0x8d, 0xb3, + 0x3c, 0x46, 0xc0, 0x2f, 0xc7, 0x72, 0x6c, 0x9c, 0x5d, 0x07, + 0x0f, 0x45, 0x3b, 0x6b, 0x66, 0x32, 0xab, 0x17, 0x83, 0xd8, + 0x4c, 0x2c, 0x84, 0x71, 0x19, 0x8f, 0xaa, 0x0a, 0xff, 0xbc, + 0xf7, 0x42, 0x10, 0xe8, 0xae, 0x4d, 0x26, 0xaf, 0xdd, 0x06, + 0x33, 0x29, 0x66, 0x21, 0x5d, 0xf5, 0xae, 0x17, 0x07, 0x1f, + 0x87, 0x9e, 0xae, 0x27, 0x1d, 0xd5, 0x02, 0x81, 0xc0, 0x56, + 0x17, 0x4f, 0x9a, 0x8a, 0xf9, 0xde, 0x3e, 0xe6, 0x71, 0x7d, + 0x94, 0xb5, 0xb0, 0xc7, 0xb8, 0x62, 0x12, 0xd1, 0x70, 0xb4, + 0x00, 0xf8, 0x4a, 0xdd, 0x4f, 0x1d, 0x36, 0xc2, 0xe1, 0xef, + 0xee, 0x25, 0x6a, 0x00, 0xc4, 0x46, 0xdf, 0xbe, 0xce, 0x77, + 0x56, 0x93, 0x6d, 0x25, 0x5f, 0xfe, 0x5b, 0xfb, 0xe0, 0xe2, + 0x37, 0xcc, 0xb9, 0xac, 0x4a, 0xce, 0x15, 0x16, 0xa0, 0xc7, + 0x33, 0x63, 0xa4, 0xaa, 0xa5, 0x1e, 0x43, 0xc1, 0xda, 0x43, + 0xfa, 0x43, 0x40, 0x29, 0x95, 0x7c, 0x2b, 0x36, 0x53, 0xe7, + 0x7d, 0x09, 0x4d, 0xd8, 0x52, 0xac, 0x74, 0x5f, 0x08, 0x81, + 0x21, 0x5c, 0x3a, 0x5a, 0xce, 0xf3, 0x25, 0xb6, 0x1e, 0x21, + 0x76, 0x4c, 0x7c, 0x71, 0x50, 0x71, 0xaa, 0x27, 0x02, 0x5b, + 0x23, 0x06, 0x0b, 0x21, 0x5b, 0xc7, 0x28, 0xa3, 0x3d, 0x8d, + 0x25, 0x9b, 0x2a, 0x2d, 0x9d, 0xa1, 0x1c, 0x1d, 0xcb, 0x7d, + 0x78, 0xf8, 0x06, 0x7e, 0x20, 0x7f, 0x24, 0x2a, 0x5c, 0xa4, + 0x04, 0xff, 0x2a, 0x68, 0xe0, 0xe6, 0xa3, 0xd8, 0x6f, 0x56, + 0x73, 0xa1, 0x3a, 0x4e, 0xc9, 0x23, 0xa1, 0x87, 0x22, 0x6a, + 0x74, 0x78, 0x3f, 0x44, 0x1c, 0x77, 0x13, 0xe5, 0x51, 0xef, + 0x89, 0x00, 0x3c, 0x6a, 0x4a, 0x5a, 0x8e, 0xf5, 0x30, 0xa2, + 0x93, 0x7e, 0x92, 0x9b, 0x85, 0x55, 0xaf, 0xfe, 0x24, 0xaf, + 0x57, 0x02, 0x81, 0xc1, 0x00, 0xa4, 0xc2, 0x6a, 0x59, 0x45, + 0xea, 0x71, 0x7d, 0x4c, 0xaf, 0xaf, 0xd6, 0x55, 0x97, 0x73, + 0xc5, 0xa1, 0x3c, 0xf6, 0x59, 0x23, 0xb6, 0x1f, 0x5e, 0x9c, + 0x96, 0x0f, 0x97, 0x66, 0x82, 0x91, 0x48, 0x36, 0x70, 0x02, + 0x67, 0xde, 0x34, 0xa6, 0x95, 0x7b, 0x51, 0x43, 0x66, 0xa4, + 0x16, 0x45, 0x59, 0x12, 0xdb, 0x35, 0x19, 0x4b, 0xbf, 0x1d, + 0xab, 0xf3, 0x3f, 0xb4, 0xb4, 0x6f, 0x66, 0xb0, 0x67, 0xc6, + 0x77, 0x2c, 0x46, 0xa8, 0x03, 0x64, 0x9a, 0x13, 0x9d, 0x40, + 0x22, 0x56, 0x76, 0x1a, 0x7c, 0x1e, 0xe2, 0xda, 0x7f, 0x09, + 0xcf, 0x10, 0xe3, 0xf2, 0xf4, 0x2a, 0x3b, 0x46, 0xc7, 0x61, + 0x9b, 0xef, 0x4a, 0x18, 0x60, 0x8c, 0x32, 0x71, 0xb9, 0xdd, + 0xac, 0xa0, 0xc6, 0x8d, 0x3f, 0xab, 0xc3, 0x21, 0x2c, 0xeb, + 0x91, 0x8f, 0xc7, 0x43, 0x0d, 0x0c, 0x67, 0x9e, 0xab, 0xe6, + 0x8d, 0xb6, 0x2d, 0x41, 0xca, 0x43, 0xd8, 0xcb, 0x30, 0xfb, + 0x3b, 0x40, 0x0d, 0x10, 0x9b, 0xb1, 0x55, 0x93, 0x73, 0x8b, + 0x60, 0xef, 0xc0, 0xee, 0xc0, 0xa6, 0x7a, 0x79, 0x90, 0xfd, + 0x4c, 0x25, 0xd4, 0x4f, 0x67, 0xbe, 0xf7, 0x86, 0x3c, 0x5d, + 0x2b, 0x7d, 0x97, 0x3d, 0xa2, 0x91, 0xa5, 0x06, 0x69, 0xf6, + 0x7a, 0xb8, 0x77, 0xe6, 0x70, 0xa9, 0xd8, 0x86, 0x4b, 0xa6, + 0xcf, 0x67, 0x1d, 0x33, 0xcf, 0xfe, 0x3e +}; + static unsigned char test4096[] = { 0x30, 0x82, 0x09, 0x29, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02, 0x01, 0x00, 0xc0, 0x71, 0xac, 0x1a, 0x13, 0x88, 0x82, 0x43, @@ -516,3 +646,1315 @@ static unsigned char test4096[] = { 0xab, 0x2e, 0xdb, 0xeb, 0x8f, 0xff, 0xdb, 0xb0, 0xc6, 0x55, 0xaf, 0xf8, 0x2a, 0x91, 0x9d, 0x50, 0x44, 0x21, 0x17, }; + +static unsigned char test7680[] = { + 0x30, 0x82, 0x11, 0x09, 0x02, 0x01, 0x00, 0x02, 0x82, 0x03, + 0xc1, 0x00, 0xe3, 0x27, 0x46, 0x99, 0xb5, 0x17, 0xab, 0xfa, + 0x65, 0x05, 0x7a, 0x06, 0x81, 0x14, 0xce, 0x43, 0x21, 0x49, + 0x0f, 0x08, 0xf1, 0x70, 0xb4, 0xc1, 0x10, 0xd1, 0x87, 0xf8, + 0x29, 0x91, 0x36, 0x66, 0x2d, 0xbe, 0x7b, 0x1d, 0xa2, 0x0b, + 0x20, 0x38, 0xd9, 0x8e, 0x78, 0x27, 0xcf, 0xb5, 0x45, 0x58, + 0x3d, 0xf4, 0xda, 0xf0, 0xdc, 0x21, 0x17, 0x52, 0xcd, 0x68, + 0xe2, 0x81, 0xac, 0x88, 0x61, 0x10, 0xbc, 0xb0, 0x7f, 0xe4, + 0xf3, 0x78, 0xb7, 0x28, 0x6c, 0x5f, 0x5c, 0xc2, 0x8d, 0x3d, + 0xb0, 0x87, 0x41, 0x15, 0x2e, 0x09, 0x5f, 0xea, 0x06, 0x7f, + 0xe9, 0x35, 0x18, 0x90, 0x50, 0xad, 0xf6, 0xb9, 0xfd, 0x33, + 0x02, 0x1a, 0x99, 0x9e, 0xa5, 0x7d, 0x2c, 0x3b, 0x24, 0xe7, + 0x31, 0x35, 0x73, 0x9a, 0xb0, 0xfe, 0x03, 0xfc, 0xc6, 0x98, + 0x78, 0xd9, 0x66, 0x95, 0xa5, 0x12, 0xbc, 0x1e, 0x82, 0xbc, + 0xf1, 0xc5, 0x31, 0xcd, 0xa6, 0xb1, 0x0c, 0x02, 0xbf, 0x7f, + 0xb7, 0xaf, 0x5f, 0xd6, 0xed, 0xf7, 0xc1, 0x59, 0x86, 0x3a, + 0x35, 0x95, 0x54, 0x21, 0x8d, 0x6a, 0xb3, 0xd1, 0x2b, 0x71, + 0xf5, 0xf1, 0x66, 0x00, 0xb1, 0x88, 0xee, 0x3b, 0xa4, 0x41, + 0x52, 0x1a, 0xf5, 0x0e, 0x32, 0xb6, 0xbf, 0x52, 0xab, 0x51, + 0x55, 0x91, 0x32, 0x4f, 0xaf, 0x91, 0xac, 0xf7, 0xff, 0x8e, + 0x3b, 0x2b, 0x61, 0xe9, 0x6d, 0x1d, 0x68, 0x80, 0x90, 0x79, + 0x34, 0x96, 0xca, 0x49, 0x43, 0x7c, 0x89, 0x4e, 0x5e, 0x31, + 0xb5, 0xce, 0x01, 0x9b, 0x09, 0xaf, 0x92, 0x06, 0x24, 0xe7, + 0x22, 0x35, 0xcc, 0xa2, 0x0b, 0xfb, 0x5b, 0x87, 0x65, 0x71, + 0xff, 0x64, 0x3e, 0xf9, 0xe8, 0x33, 0xa0, 0xc3, 0x4e, 0xb2, + 0x41, 0x98, 0x54, 0xeb, 0x13, 0x99, 0xfb, 0x32, 0x78, 0x7e, + 0xda, 0x4f, 0xd3, 0x46, 0x6a, 0xb5, 0x78, 0x81, 0x3f, 0x04, + 0x13, 0x5f, 0x67, 0xaf, 0x88, 0xa5, 0x9e, 0x0d, 0xc5, 0xf3, + 0xe7, 0x4c, 0x51, 0xf5, 0x51, 0x4a, 0xa4, 0x58, 0x64, 0xd9, + 0xa2, 0x32, 0x54, 0x36, 0xce, 0x38, 0xd8, 0xc2, 0x0e, 0x0d, + 0x60, 0x8e, 0x32, 0x7f, 0x90, 0x8a, 0xbc, 0x88, 0xbe, 0x6a, + 0xc0, 0x47, 0x0f, 0x02, 0x41, 0xff, 0x3b, 0x7e, 0xc5, 0xa6, + 0x33, 0x1d, 0x19, 0xd1, 0xd5, 0x67, 0x6c, 0xbf, 0x16, 0xb0, + 0x7e, 0x80, 0x10, 0xbf, 0x7f, 0xdd, 0xd0, 0xf4, 0xc3, 0x94, + 0x2c, 0x9a, 0x2c, 0xda, 0x69, 0x4e, 0xd6, 0x7b, 0x40, 0x4d, + 0x2a, 0x27, 0xcb, 0x5a, 0xe5, 0x2d, 0x3f, 0x7d, 0x51, 0x9d, + 0x9f, 0x70, 0xde, 0x50, 0xb1, 0xd3, 0xd2, 0x38, 0x4d, 0x1c, + 0xca, 0xc2, 0x1e, 0x80, 0xd0, 0x36, 0x82, 0x04, 0xe6, 0x17, + 0x79, 0x9f, 0x2e, 0xc9, 0xed, 0x2b, 0xd5, 0x1b, 0xfa, 0x7d, + 0x1a, 0x80, 0xb5, 0x0e, 0x2f, 0x05, 0xbe, 0x4a, 0x1b, 0xfe, + 0x0a, 0xad, 0x01, 0xde, 0x91, 0xc8, 0xf9, 0x81, 0xbe, 0xc7, + 0xaf, 0xe7, 0x87, 0xed, 0x9d, 0xb8, 0x6c, 0xad, 0x65, 0xed, + 0x5e, 0xd3, 0x67, 0x8c, 0x62, 0x3a, 0xe7, 0xfd, 0x67, 0xe0, + 0xbb, 0x57, 0xaf, 0x56, 0xeb, 0x4a, 0x58, 0x6e, 0xad, 0xf2, + 0xbe, 0xc3, 0x70, 0x29, 0xf8, 0xeb, 0x68, 0x45, 0xa0, 0xbd, + 0xcd, 0xa5, 0xb4, 0xd9, 0x01, 0xb7, 0x44, 0xeb, 0x97, 0xf3, + 0x0c, 0x56, 0xe4, 0x26, 0xd0, 0xa5, 0xb1, 0xa3, 0x49, 0x6e, + 0x88, 0xf2, 0x22, 0xe2, 0x7b, 0x58, 0x3a, 0xd9, 0x52, 0xa4, + 0xb1, 0x4c, 0x5c, 0x7c, 0xf0, 0x88, 0x7b, 0x9f, 0x06, 0xe9, + 0x32, 0x4e, 0xf2, 0x64, 0x83, 0x8b, 0xa2, 0xea, 0x1d, 0x25, + 0xf1, 0x8d, 0x16, 0x8b, 0xe0, 0xab, 0xd2, 0xe9, 0xe4, 0x6b, + 0x7d, 0x76, 0x98, 0x22, 0x53, 0x31, 0x6b, 0xcc, 0xf1, 0xe5, + 0x1d, 0xd7, 0xa5, 0xb0, 0xea, 0x6b, 0x38, 0x14, 0x0c, 0x06, + 0x10, 0x27, 0xd8, 0x33, 0xf3, 0x9a, 0xae, 0x94, 0xdd, 0x0b, + 0xb4, 0x6d, 0xe5, 0x91, 0xdd, 0xf1, 0x0f, 0x27, 0xa4, 0x94, + 0x55, 0xf0, 0xde, 0x07, 0x29, 0xe6, 0x3f, 0x26, 0x19, 0xa1, + 0xdd, 0xd1, 0x06, 0x99, 0xda, 0x54, 0x23, 0x3c, 0xf5, 0x5c, + 0x2e, 0x96, 0xa9, 0x21, 0x23, 0x25, 0x2e, 0x6f, 0xf1, 0xf9, + 0x11, 0x54, 0xe5, 0x7b, 0xb9, 0x1f, 0x11, 0xe2, 0x9e, 0x6b, + 0x61, 0x8b, 0xa3, 0x8b, 0xc1, 0x20, 0x9b, 0xfb, 0x51, 0xef, + 0xbb, 0xb9, 0xf6, 0xaf, 0x66, 0xb3, 0x2c, 0x25, 0xef, 0x76, + 0xcb, 0xbf, 0x7a, 0x93, 0x2f, 0xe1, 0x17, 0x56, 0xc1, 0x00, + 0x33, 0xb5, 0xd9, 0x91, 0x05, 0x31, 0xcc, 0x72, 0xcd, 0x4a, + 0x93, 0x9a, 0xe3, 0x21, 0x42, 0x9e, 0xb8, 0x4e, 0x6c, 0x27, + 0x93, 0xf0, 0x7f, 0x22, 0xdb, 0xe5, 0xb3, 0xa3, 0xf7, 0xe7, + 0x80, 0xbb, 0x91, 0xca, 0xf7, 0xe8, 0x52, 0xb8, 0x11, 0x64, + 0x66, 0x25, 0x94, 0xf8, 0x6f, 0x0b, 0x3b, 0xb7, 0xff, 0x80, + 0x9e, 0x36, 0xe9, 0x88, 0x2e, 0xab, 0x05, 0xbf, 0x99, 0x9f, + 0x2b, 0x4f, 0xc6, 0xb1, 0x13, 0x5b, 0x06, 0xff, 0x0a, 0x7b, + 0xbc, 0x7f, 0x07, 0xa0, 0x35, 0xc2, 0x2d, 0x44, 0x3e, 0xad, + 0x44, 0xcb, 0x47, 0x18, 0x26, 0x71, 0x7b, 0x17, 0xc9, 0x6d, + 0xb5, 0x4b, 0xcf, 0xdf, 0x14, 0x2c, 0x6c, 0xdf, 0x21, 0xce, + 0x93, 0x49, 0x34, 0x69, 0x49, 0xfd, 0x3e, 0x71, 0x5b, 0xfa, + 0x07, 0xc5, 0x7e, 0x5e, 0x54, 0x1a, 0x3c, 0xa6, 0x29, 0xb5, + 0xbf, 0x0d, 0xf1, 0xc6, 0xa4, 0x61, 0xd6, 0x17, 0x1d, 0xf0, + 0xa2, 0x78, 0x8f, 0xbc, 0x7e, 0x0c, 0xb4, 0xf0, 0x1e, 0x05, + 0xea, 0xb5, 0xad, 0x68, 0x95, 0x0b, 0x27, 0xb4, 0x29, 0x7c, + 0x70, 0x2a, 0x9a, 0x0a, 0x39, 0xd4, 0x76, 0xb7, 0x72, 0x30, + 0x5e, 0xae, 0x9c, 0x4a, 0x55, 0xc7, 0x46, 0xd7, 0x5f, 0xbe, + 0x10, 0x61, 0x25, 0x18, 0x7a, 0x9f, 0xd3, 0x05, 0x3d, 0x6f, + 0x9a, 0x1e, 0xec, 0x2b, 0x03, 0xe0, 0x49, 0x6a, 0x9c, 0xd6, + 0xdb, 0xc2, 0xa1, 0xe1, 0x0a, 0xbb, 0x31, 0x42, 0xc8, 0x43, + 0x4e, 0x7c, 0xa9, 0x7c, 0x60, 0xea, 0xbe, 0xf1, 0x8b, 0xe8, + 0xb2, 0x90, 0x83, 0x14, 0x21, 0xe4, 0xb3, 0x0d, 0x7c, 0x63, + 0x3c, 0x98, 0x55, 0xc6, 0x44, 0xa6, 0xa8, 0x1e, 0x42, 0xb7, + 0x89, 0xa8, 0xbd, 0xb8, 0x34, 0x3d, 0x09, 0x80, 0x99, 0x73, + 0x9f, 0xaf, 0x17, 0x56, 0xf2, 0x73, 0x3e, 0x1e, 0x6e, 0xe9, + 0x18, 0xa0, 0x5b, 0x69, 0xce, 0xfd, 0x3d, 0x77, 0x81, 0x95, + 0x3b, 0xf1, 0xde, 0x26, 0xe9, 0x27, 0xef, 0x92, 0x2a, 0x97, + 0xdc, 0x95, 0xa5, 0xa3, 0xb0, 0xfb, 0x96, 0x89, 0x4f, 0xe6, + 0xc1, 0x42, 0x0b, 0xfd, 0xb4, 0x6d, 0x0a, 0x9f, 0x9b, 0x31, + 0xd8, 0x21, 0x38, 0x8a, 0xee, 0xb6, 0x5c, 0x12, 0xa8, 0xb4, + 0x07, 0x79, 0x41, 0xa7, 0x7f, 0x13, 0x74, 0xad, 0x0b, 0xee, + 0x28, 0x52, 0xac, 0x2f, 0x4d, 0x30, 0x1c, 0xc5, 0xa6, 0xa5, + 0x61, 0x42, 0xbd, 0xe1, 0x4f, 0xd3, 0xec, 0x66, 0xf2, 0x63, + 0xf4, 0x93, 0xdb, 0x35, 0x2d, 0x3b, 0x71, 0x25, 0x09, 0xde, + 0xda, 0x46, 0xda, 0xe2, 0xa7, 0xa3, 0xdf, 0xcd, 0xbf, 0x58, + 0x05, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x03, + 0xc0, 0x5f, 0xd5, 0x15, 0x1b, 0x09, 0xe4, 0xa7, 0xc0, 0xa6, + 0xd8, 0x0d, 0xa8, 0x2a, 0xd3, 0x1d, 0x46, 0x03, 0x07, 0xf0, + 0x98, 0xe4, 0x4b, 0x99, 0x66, 0x8e, 0x72, 0xe7, 0xbb, 0x51, + 0xc6, 0x1a, 0xbe, 0x36, 0xf4, 0x52, 0xba, 0xa8, 0xbf, 0xaa, + 0xe3, 0x71, 0x1d, 0x83, 0x21, 0xc0, 0xa6, 0x88, 0x4f, 0xf7, + 0x2b, 0x93, 0x26, 0xe4, 0xa7, 0xed, 0x50, 0x18, 0xaa, 0xf4, + 0x4c, 0xa2, 0xfe, 0x92, 0x7c, 0xde, 0x2e, 0x54, 0x76, 0xc2, + 0x25, 0x1e, 0x98, 0xa6, 0x48, 0x01, 0x39, 0x6f, 0x1f, 0x24, + 0x97, 0x9b, 0x64, 0x95, 0x1c, 0x8d, 0x63, 0x8d, 0x44, 0x6f, + 0x9d, 0xdf, 0xf4, 0x1a, 0xa5, 0x9a, 0x1e, 0xd3, 0x6c, 0xae, + 0xa9, 0x8c, 0x3f, 0xfb, 0x2f, 0x78, 0xf6, 0xa6, 0xd6, 0x06, + 0xd3, 0xb7, 0x26, 0xff, 0x1e, 0xdb, 0x8d, 0xcc, 0x37, 0x4d, + 0x5c, 0xe2, 0xc3, 0xa5, 0x75, 0xe6, 0xf9, 0xb4, 0x4c, 0x84, + 0x6f, 0x9e, 0x58, 0x55, 0xc8, 0x01, 0xfa, 0x32, 0xd2, 0x6e, + 0x2b, 0x45, 0xf2, 0xc6, 0x48, 0xad, 0x40, 0xd8, 0xb9, 0x3c, + 0x1b, 0xf8, 0xf7, 0x82, 0xd3, 0x0e, 0x73, 0xe3, 0xb1, 0x5b, + 0x82, 0x71, 0x77, 0x3f, 0x6f, 0x36, 0x9a, 0xe0, 0xec, 0x51, + 0xf8, 0x5f, 0x84, 0x92, 0xee, 0xb8, 0x7e, 0xe7, 0x1a, 0x14, + 0x50, 0x82, 0x7a, 0x4d, 0xe6, 0xd6, 0xa3, 0x76, 0x24, 0x8a, + 0x5f, 0xfe, 0x19, 0xdd, 0xd7, 0xf7, 0x5b, 0xae, 0x18, 0x04, + 0x90, 0xcd, 0x5c, 0xe5, 0x64, 0xe8, 0x04, 0xb1, 0x06, 0xa5, + 0xdd, 0xf8, 0x9d, 0x71, 0x13, 0xaa, 0x36, 0x7f, 0x61, 0x27, + 0xf4, 0xac, 0x95, 0x7d, 0x1a, 0x99, 0x7d, 0xe0, 0xd5, 0x9c, + 0x5a, 0xad, 0x9a, 0xff, 0x54, 0xb0, 0xb1, 0x55, 0x45, 0x2d, + 0x19, 0x58, 0x52, 0x28, 0xdd, 0xe0, 0xb5, 0x65, 0x52, 0x97, + 0x45, 0xf0, 0x2b, 0x98, 0x1f, 0x61, 0x6c, 0x9d, 0xaa, 0x59, + 0x85, 0xf9, 0x97, 0x7b, 0xbd, 0xeb, 0x95, 0x81, 0xfb, 0x29, + 0x8c, 0xf0, 0x52, 0xdf, 0xed, 0xee, 0xb2, 0x00, 0x32, 0x35, + 0x14, 0xa8, 0xa4, 0xca, 0x91, 0xff, 0x18, 0xb7, 0x96, 0xfb, + 0x32, 0x62, 0xa9, 0xa0, 0xd0, 0x77, 0x43, 0xf5, 0x99, 0xd1, + 0xee, 0xe8, 0xad, 0x1a, 0x2c, 0xd4, 0xeb, 0xe1, 0xf5, 0x01, + 0x41, 0x78, 0xc0, 0x27, 0x19, 0x50, 0x2e, 0xba, 0x22, 0xd1, + 0xeb, 0xb3, 0xa5, 0x27, 0x0b, 0xec, 0xf9, 0x26, 0x7e, 0x1f, + 0xe7, 0x17, 0x9f, 0x39, 0xa8, 0x72, 0x22, 0x63, 0x79, 0x6a, + 0x9c, 0x89, 0x55, 0x9a, 0xb4, 0x61, 0x41, 0xbc, 0xaa, 0x14, + 0x37, 0x29, 0x03, 0xc0, 0x52, 0x4e, 0x31, 0x44, 0x8f, 0x2e, + 0x17, 0x81, 0x88, 0xf4, 0xce, 0xda, 0x41, 0xb8, 0xd5, 0x14, + 0x91, 0x8c, 0xca, 0xd2, 0x0d, 0x99, 0x06, 0x09, 0xc2, 0xb7, + 0xe8, 0xae, 0xfa, 0x01, 0xea, 0x99, 0x62, 0x68, 0xb6, 0xdf, + 0xc8, 0x27, 0xae, 0xbf, 0xb0, 0x9b, 0x5b, 0x1a, 0xa2, 0xe2, + 0x5a, 0x7a, 0xe5, 0x4b, 0x92, 0x1f, 0xff, 0x73, 0xae, 0x16, + 0x40, 0x78, 0x42, 0x28, 0xbb, 0x13, 0x5e, 0xbc, 0x71, 0x7a, + 0x78, 0x3e, 0xd8, 0x1b, 0xc2, 0x2c, 0xd6, 0xdc, 0xfa, 0x39, + 0x72, 0xf8, 0xa2, 0x2c, 0x8b, 0x1c, 0x5d, 0xab, 0xb8, 0x07, + 0xc7, 0xae, 0x29, 0x93, 0x68, 0xbf, 0x61, 0xe9, 0xa4, 0x37, + 0x83, 0x7d, 0x13, 0xc7, 0x18, 0xf0, 0x7d, 0xa4, 0x20, 0x47, + 0x14, 0x68, 0x95, 0x46, 0x56, 0x6d, 0xd5, 0x7b, 0xe1, 0x51, + 0x8f, 0x96, 0xc1, 0x7b, 0x35, 0x09, 0x7a, 0x89, 0x0e, 0xdf, + 0x12, 0xd5, 0xe1, 0x9c, 0x2a, 0x94, 0x95, 0x43, 0x93, 0x48, + 0xa6, 0x23, 0xe6, 0xd8, 0xf2, 0xb8, 0x0e, 0xba, 0x6d, 0x61, + 0x03, 0xaf, 0x40, 0x63, 0x2b, 0x2f, 0xee, 0x61, 0x4c, 0xc4, + 0x70, 0x3d, 0x78, 0xc1, 0x4f, 0x8e, 0x0b, 0x9b, 0x06, 0x35, + 0x6d, 0x6d, 0x83, 0x37, 0xbb, 0x39, 0x7d, 0x7f, 0x33, 0x93, + 0xc4, 0xeb, 0x8e, 0xfc, 0xda, 0xf0, 0x54, 0xfe, 0x1d, 0xc4, + 0xd3, 0x83, 0x99, 0xdf, 0x65, 0xee, 0x00, 0x7d, 0x86, 0x27, + 0xd4, 0x3a, 0x6b, 0xe6, 0x82, 0x8e, 0x58, 0x2d, 0x03, 0x38, + 0xef, 0x6c, 0x82, 0x87, 0x18, 0x3b, 0x47, 0xe7, 0xbc, 0xe1, + 0x58, 0x70, 0x4d, 0x46, 0x96, 0x34, 0x60, 0x96, 0x15, 0x09, + 0x3c, 0x84, 0x40, 0xaf, 0x80, 0x32, 0x75, 0xc7, 0x23, 0x6c, + 0xfb, 0x1d, 0x57, 0x73, 0x19, 0x09, 0xe8, 0x1a, 0x4c, 0x02, + 0x5c, 0x7e, 0x4e, 0xbe, 0x75, 0xf8, 0x73, 0xff, 0x2d, 0x54, + 0x19, 0x55, 0xf5, 0xf4, 0x1b, 0xc9, 0xbc, 0xc2, 0x19, 0xcb, + 0xb7, 0x4e, 0x6a, 0x0d, 0xff, 0xca, 0x7d, 0xd0, 0x88, 0x91, + 0x8b, 0x9b, 0x21, 0xa4, 0xa2, 0x43, 0x0d, 0xbc, 0x9e, 0x73, + 0x7d, 0x54, 0x7d, 0x95, 0xcc, 0x63, 0x5e, 0xc1, 0xb8, 0xe6, + 0x27, 0xff, 0x20, 0x07, 0xe8, 0x6e, 0x7e, 0xf2, 0x0f, 0x5a, + 0x09, 0xef, 0xe5, 0x4d, 0x80, 0x39, 0x95, 0xd5, 0xf4, 0xee, + 0x3b, 0xca, 0x7c, 0x73, 0xf8, 0x39, 0x5a, 0xc1, 0x1d, 0x7d, + 0x94, 0x72, 0x32, 0xad, 0x58, 0xe2, 0xfc, 0x71, 0x6e, 0x66, + 0xaa, 0xa1, 0x59, 0xd6, 0xac, 0xab, 0xbe, 0x8c, 0x53, 0x99, + 0xcd, 0xe8, 0x2d, 0xb5, 0xb3, 0x46, 0x58, 0x2e, 0x16, 0xd7, + 0x4d, 0x8b, 0x7d, 0x4a, 0xb1, 0x4c, 0x85, 0x91, 0x1b, 0x57, + 0x54, 0xf8, 0x14, 0x59, 0xdb, 0xc4, 0x2c, 0x9c, 0x08, 0x6d, + 0x3d, 0xd7, 0xf6, 0xa6, 0xe6, 0xb3, 0x2a, 0xe7, 0x29, 0x1c, + 0xab, 0xb4, 0xed, 0x13, 0x19, 0xf8, 0xb6, 0x60, 0x92, 0x44, + 0x53, 0xd4, 0xa9, 0x7e, 0xba, 0x21, 0xa2, 0xdc, 0x6e, 0xa5, + 0x5e, 0x53, 0x59, 0x3c, 0x52, 0x61, 0x7b, 0x5f, 0x19, 0xad, + 0xc8, 0x6d, 0x68, 0x8d, 0x7a, 0xc9, 0xd6, 0xef, 0xeb, 0x67, + 0x4f, 0xca, 0xe7, 0xf6, 0x29, 0x36, 0x97, 0xfb, 0x3e, 0x37, + 0x95, 0x85, 0x71, 0x70, 0xf6, 0x63, 0x86, 0x2a, 0x29, 0xd7, + 0x9a, 0x96, 0x76, 0xa7, 0x47, 0x98, 0x4e, 0x06, 0x31, 0xaf, + 0xf3, 0x4f, 0x2a, 0x65, 0x90, 0x6a, 0x4b, 0x8e, 0x43, 0x79, + 0xe2, 0xdd, 0xce, 0x08, 0x1c, 0x01, 0xec, 0x38, 0x41, 0xdd, + 0x19, 0xd8, 0xf3, 0x36, 0x03, 0x35, 0x03, 0xaf, 0x1c, 0x45, + 0x3c, 0xac, 0x13, 0xaa, 0x36, 0x16, 0x48, 0x77, 0xb3, 0xbe, + 0xa3, 0xb3, 0x9d, 0x7f, 0x20, 0xca, 0x74, 0x65, 0xac, 0x93, + 0xa7, 0x54, 0xad, 0xc8, 0x68, 0x0e, 0xf8, 0x44, 0x1f, 0xad, + 0x2c, 0xb7, 0x9a, 0x9a, 0x07, 0xe5, 0xcd, 0x87, 0xe0, 0x14, + 0xb5, 0xaf, 0xd3, 0xd7, 0xcf, 0x13, 0x9f, 0x3b, 0xbd, 0xfe, + 0x29, 0x0b, 0x72, 0xf5, 0x4c, 0x54, 0x94, 0xc7, 0x66, 0xec, + 0xa8, 0x41, 0x96, 0x3d, 0x17, 0xed, 0x19, 0xc0, 0x82, 0x3e, + 0x5f, 0x9a, 0x91, 0xfe, 0xd1, 0x2f, 0xb8, 0x94, 0xaa, 0x58, + 0x68, 0x95, 0x31, 0x87, 0x57, 0x9a, 0x75, 0x94, 0x4d, 0x38, + 0x7d, 0x56, 0x82, 0x81, 0x9c, 0xb9, 0x34, 0x2b, 0xe7, 0x40, + 0xd9, 0x3c, 0x77, 0x5b, 0x95, 0x51, 0x06, 0x11, 0x41, 0xe3, + 0x8b, 0xb7, 0x32, 0xeb, 0xe1, 0x05, 0x1b, 0x10, 0xa8, 0x0e, + 0xa1, 0x02, 0x82, 0x01, 0xe1, 0x00, 0xfa, 0x38, 0x34, 0xfe, + 0x55, 0x87, 0x71, 0x62, 0x47, 0x00, 0x33, 0x64, 0x67, 0x70, + 0x79, 0x76, 0xdf, 0xfe, 0xc3, 0x28, 0x38, 0xdf, 0x90, 0xd4, + 0xc0, 0xee, 0x98, 0xbf, 0x9d, 0x9b, 0x85, 0xd8, 0x61, 0x65, + 0xa5, 0x70, 0xf5, 0xd2, 0x2c, 0xbf, 0x2f, 0xb5, 0x55, 0x79, + 0x92, 0x13, 0xba, 0x4d, 0x3c, 0x39, 0xbf, 0xd5, 0x31, 0x13, + 0x7a, 0x31, 0xf4, 0x8b, 0xce, 0xf8, 0xd0, 0xd3, 0x9b, 0xe2, + 0xee, 0x31, 0xdb, 0xba, 0xcc, 0x1a, 0xba, 0x1c, 0x8d, 0xee, + 0xea, 0xcb, 0xd3, 0x5a, 0xad, 0x87, 0xd6, 0xf9, 0x15, 0x2f, + 0x6e, 0x00, 0x06, 0x74, 0x25, 0x8d, 0xff, 0xc8, 0xa6, 0x11, + 0x1c, 0xe8, 0x16, 0x1a, 0xde, 0x53, 0x05, 0xb9, 0x53, 0x55, + 0x28, 0x83, 0x3d, 0xbe, 0x61, 0x0c, 0xc4, 0x98, 0x7d, 0xf6, + 0xec, 0x36, 0xc3, 0xe5, 0xe7, 0x1d, 0x14, 0x64, 0xcb, 0x0d, + 0x62, 0x5d, 0x7a, 0xcd, 0x88, 0xfc, 0x66, 0x4e, 0xf9, 0x36, + 0x47, 0x95, 0x18, 0x3a, 0x48, 0x2a, 0xff, 0x62, 0x8f, 0x6c, + 0xe2, 0xc2, 0xe9, 0xd3, 0x6a, 0x45, 0x5c, 0xf5, 0x89, 0x53, + 0x5c, 0xbe, 0xcf, 0xad, 0x87, 0x22, 0x9c, 0x31, 0x48, 0xdb, + 0xd8, 0xe4, 0xe5, 0x38, 0xae, 0xc2, 0xb0, 0xd2, 0xba, 0xb7, + 0x30, 0x53, 0x2d, 0xb1, 0x35, 0xf1, 0x58, 0x0f, 0x8a, 0x06, + 0x51, 0x76, 0xb9, 0x2c, 0x32, 0xe0, 0xd1, 0xaa, 0x82, 0x34, + 0x69, 0x71, 0x1c, 0x5f, 0x35, 0xa8, 0x9d, 0x11, 0xac, 0x13, + 0xdb, 0x7b, 0xf6, 0x93, 0xe3, 0xb9, 0xbd, 0xd9, 0xb2, 0x86, + 0xff, 0x61, 0x88, 0x2b, 0x72, 0x5c, 0x84, 0xe1, 0x0c, 0x72, + 0xab, 0x44, 0xff, 0x23, 0x13, 0xaf, 0xd1, 0x5a, 0xd3, 0xea, + 0x73, 0xfe, 0xd5, 0xa4, 0x7d, 0x9e, 0x4e, 0xac, 0x03, 0x93, + 0x72, 0x14, 0x2d, 0x96, 0x6f, 0xee, 0xb4, 0xcd, 0x4e, 0xab, + 0xea, 0x71, 0x93, 0x81, 0xe0, 0x3d, 0xcd, 0x61, 0x96, 0x25, + 0x76, 0xbd, 0xc4, 0xb5, 0xdd, 0x7c, 0xf1, 0xb9, 0xe1, 0x2c, + 0x58, 0x1b, 0xa4, 0x46, 0x4b, 0x12, 0x57, 0x58, 0xaa, 0x3a, + 0xae, 0x89, 0xa3, 0xb3, 0xcf, 0x1f, 0x8d, 0x67, 0xdf, 0x6d, + 0x7e, 0x8e, 0xfa, 0xc5, 0x09, 0x73, 0x46, 0x56, 0x55, 0x90, + 0xeb, 0x77, 0x4e, 0x16, 0x4f, 0x68, 0x7b, 0x1f, 0x61, 0x23, + 0xec, 0xa9, 0x71, 0x30, 0x33, 0x25, 0xc7, 0x4e, 0x26, 0x2e, + 0x4e, 0x2b, 0xc2, 0x64, 0x5f, 0xf5, 0x8f, 0x7a, 0x4b, 0x1c, + 0x06, 0xb3, 0x91, 0xf6, 0x9b, 0x51, 0xb7, 0xb0, 0x64, 0x72, + 0x04, 0xe5, 0xfa, 0x14, 0x2f, 0xed, 0x61, 0x29, 0x03, 0x73, + 0x19, 0x15, 0x6e, 0x2c, 0x8b, 0x0e, 0xec, 0x4d, 0xf1, 0xe3, + 0x6f, 0x58, 0x7c, 0xc9, 0x48, 0x67, 0x3f, 0x51, 0xb5, 0xb7, + 0x26, 0x46, 0xa7, 0x25, 0x79, 0x55, 0xfe, 0x3a, 0x44, 0xb4, + 0x44, 0xfc, 0xb8, 0x14, 0x34, 0x47, 0xd7, 0xa3, 0x0e, 0x76, + 0xe7, 0x83, 0x9a, 0x02, 0xc3, 0xcf, 0x2b, 0xd9, 0x83, 0x93, + 0xd5, 0xee, 0x99, 0x74, 0x45, 0x62, 0x23, 0xa6, 0x02, 0xc9, + 0xc0, 0x10, 0x70, 0x0a, 0x99, 0x29, 0x0c, 0x79, 0x04, 0x4c, + 0x77, 0x21, 0x96, 0xf0, 0xa5, 0x17, 0x22, 0xbe, 0xab, 0x9b, + 0xd7, 0x42, 0xd3, 0xe9, 0xc0, 0x42, 0x44, 0x7d, 0x9d, 0xc9, + 0x3d, 0xf9, 0x36, 0x97, 0x1b, 0x75, 0x52, 0x8f, 0xe9, 0xb9, + 0x8c, 0xa7, 0x64, 0x19, 0x5b, 0x5d, 0x60, 0xb4, 0x42, 0x95, + 0xc9, 0xdb, 0x82, 0x03, 0xc6, 0xb0, 0x28, 0x72, 0x64, 0x03, + 0x41, 0x4d, 0x8f, 0xc6, 0xd0, 0xcd, 0x02, 0x82, 0x01, 0xe1, + 0x00, 0xe8, 0x66, 0xa7, 0xf9, 0x0f, 0x5a, 0x21, 0xfc, 0x88, + 0x4e, 0x91, 0xd5, 0x4a, 0xf0, 0xf4, 0x32, 0xe5, 0x0d, 0xf3, + 0x06, 0x95, 0xd0, 0x4e, 0x47, 0x0c, 0x04, 0x66, 0x77, 0xfd, + 0xb8, 0x93, 0x0d, 0xff, 0x8f, 0x97, 0xa0, 0x4a, 0x36, 0x37, + 0xa6, 0x5e, 0x95, 0x79, 0xc8, 0xb2, 0x21, 0x98, 0x81, 0xf1, + 0xb8, 0xf4, 0x52, 0xaf, 0x3c, 0x8c, 0x86, 0x85, 0x55, 0x56, + 0xfc, 0x90, 0xe3, 0x32, 0x50, 0x7c, 0x54, 0x07, 0x9e, 0xed, + 0xfc, 0xd4, 0xb9, 0x5c, 0x98, 0x22, 0xfb, 0x72, 0xd7, 0x83, + 0xf0, 0xd1, 0x61, 0x10, 0xbd, 0x68, 0x5d, 0x72, 0xc1, 0xce, + 0x92, 0x43, 0x77, 0x9f, 0xb8, 0x8d, 0x8e, 0xf2, 0xe3, 0x62, + 0x4a, 0x93, 0x03, 0xd3, 0xd9, 0x01, 0xa8, 0x99, 0x6f, 0xa3, + 0x4c, 0x6d, 0x7a, 0xf2, 0x9e, 0x8e, 0x6b, 0xbc, 0xe4, 0x9d, + 0x8e, 0xe7, 0x25, 0x86, 0xa4, 0xa9, 0xc2, 0xef, 0xdf, 0xbb, + 0x6e, 0x3d, 0x4b, 0x57, 0x95, 0x81, 0x6f, 0x68, 0x3f, 0x19, + 0xa8, 0xff, 0x5a, 0x08, 0x7a, 0xe4, 0x4c, 0x4e, 0xb4, 0xea, + 0xf4, 0xc8, 0x2f, 0xef, 0x8c, 0x5e, 0xcd, 0x62, 0x1c, 0x8c, + 0x93, 0x60, 0x5d, 0xa3, 0x11, 0x64, 0x0b, 0xeb, 0x6d, 0x21, + 0xbc, 0x3a, 0x5b, 0x5c, 0x0c, 0xa7, 0x8a, 0xc6, 0xa8, 0xe1, + 0x48, 0x81, 0x01, 0xb5, 0x65, 0xab, 0x2e, 0xbe, 0x38, 0x94, + 0xf7, 0xa6, 0x33, 0xc1, 0x6e, 0x0b, 0x88, 0x38, 0xe7, 0x1b, + 0x04, 0x9a, 0x10, 0x2d, 0x1d, 0x3f, 0x5f, 0x5f, 0xc8, 0xef, + 0xcd, 0xc5, 0x16, 0xdc, 0x84, 0xc0, 0x66, 0xe0, 0xa3, 0xfc, + 0xfa, 0x96, 0xc7, 0xb7, 0xec, 0x4f, 0x40, 0x0a, 0xc5, 0xbe, + 0x6d, 0x39, 0x4a, 0x7e, 0x91, 0x4f, 0xe1, 0x03, 0xd2, 0x39, + 0xbc, 0x87, 0x69, 0xa1, 0xf0, 0x6d, 0x11, 0xf5, 0xb4, 0x9d, + 0xae, 0x76, 0x6b, 0xc6, 0xbf, 0xe4, 0x47, 0xbc, 0x4d, 0x13, + 0x88, 0xa8, 0x83, 0xf5, 0xae, 0x1d, 0xfb, 0x4d, 0x4c, 0x44, + 0x03, 0xd8, 0xa4, 0x2e, 0x4d, 0xf8, 0x5f, 0x45, 0x94, 0x58, + 0xd7, 0xd9, 0x4b, 0x47, 0xd8, 0xfc, 0x35, 0x05, 0xed, 0xb4, + 0xb6, 0xc2, 0x36, 0x2e, 0xba, 0xd2, 0x7a, 0xba, 0x69, 0x34, + 0xbf, 0xf1, 0xa1, 0x5e, 0x17, 0x71, 0x89, 0xd3, 0x54, 0x57, + 0x05, 0x2b, 0x82, 0xe3, 0x0a, 0x64, 0x5c, 0x3b, 0x8c, 0x6b, + 0xc7, 0x10, 0x8a, 0xb5, 0xd3, 0xd7, 0x90, 0xeb, 0xdb, 0x1d, + 0xa0, 0xbf, 0x6b, 0xea, 0xcd, 0x31, 0x7a, 0x8d, 0x64, 0xcc, + 0x58, 0xc0, 0x07, 0xa4, 0x6e, 0x14, 0x0b, 0xf3, 0xea, 0x3e, + 0x87, 0x9f, 0x7c, 0xb8, 0x1c, 0x22, 0x26, 0x8a, 0x7d, 0x90, + 0xdd, 0x57, 0x28, 0x38, 0xcc, 0x0e, 0x71, 0x92, 0x89, 0xee, + 0x79, 0x88, 0xbc, 0x05, 0x21, 0xda, 0x42, 0x92, 0x52, 0x66, + 0xac, 0x4a, 0xe5, 0xf5, 0x6e, 0x47, 0xd5, 0xba, 0x37, 0xd3, + 0x7c, 0x89, 0xd4, 0xd8, 0x6f, 0xde, 0x63, 0x44, 0xb5, 0x88, + 0xdd, 0xb1, 0x30, 0xb4, 0x6d, 0xcd, 0xbf, 0xc8, 0x34, 0x27, + 0x59, 0x7d, 0x79, 0xdc, 0x96, 0x5b, 0x8e, 0xc0, 0x87, 0xc0, + 0x4e, 0x40, 0x07, 0x13, 0x91, 0x6b, 0x3a, 0x12, 0x03, 0x64, + 0x70, 0xaf, 0x80, 0x24, 0x1c, 0x5c, 0xfb, 0xf5, 0xc0, 0x74, + 0x5e, 0xaf, 0x06, 0x18, 0x04, 0x67, 0x4a, 0xbd, 0xac, 0xd7, + 0xca, 0xbe, 0x4e, 0xa1, 0x19, 0x48, 0x7d, 0xa6, 0x59, 0xf6, + 0x1a, 0x62, 0x50, 0x53, 0x46, 0xa4, 0x5b, 0x9c, 0x5a, 0xfd, + 0x89, 0x9d, 0xd4, 0xde, 0xf4, 0xa7, 0x3d, 0x88, 0x73, 0xa5, + 0xb9, 0x02, 0x82, 0x01, 0xe1, 0x00, 0xe7, 0x70, 0x59, 0xc3, + 0xed, 0xc4, 0x6b, 0xa1, 0xa5, 0x5e, 0x90, 0x2a, 0x8c, 0x6a, + 0xc2, 0x4e, 0xab, 0xfc, 0xee, 0xf2, 0x23, 0x38, 0xd6, 0xb3, + 0x93, 0x08, 0x9e, 0x0c, 0x8e, 0x71, 0x2d, 0xa9, 0xe8, 0xdc, + 0xa5, 0xdc, 0x07, 0xe3, 0xb1, 0x33, 0xdd, 0xa2, 0xf2, 0x3e, + 0x92, 0x58, 0xe0, 0xf7, 0x53, 0x7f, 0x6e, 0xea, 0x78, 0x8c, + 0x35, 0x78, 0x43, 0x63, 0x95, 0xbb, 0x1b, 0x1c, 0xbf, 0x91, + 0x75, 0x14, 0x74, 0xd3, 0x20, 0xba, 0x8f, 0xee, 0x9d, 0x71, + 0xa1, 0x87, 0x8a, 0x24, 0xd3, 0x61, 0x53, 0xfb, 0xec, 0x16, + 0x84, 0xbe, 0x4d, 0x39, 0xdd, 0x0a, 0xac, 0xce, 0x20, 0x9c, + 0xaf, 0x8a, 0x13, 0xf8, 0x22, 0x2f, 0xd4, 0x99, 0x88, 0x74, + 0xba, 0x16, 0x3a, 0x63, 0xff, 0x4c, 0x5a, 0x03, 0x5a, 0x6f, + 0xac, 0x29, 0x33, 0xa5, 0x50, 0xd1, 0xda, 0xed, 0x27, 0xcb, + 0x67, 0x72, 0x63, 0x85, 0xfc, 0xf0, 0xc8, 0x88, 0xbf, 0x85, + 0xef, 0x4b, 0xfe, 0xae, 0xd9, 0xd5, 0xbb, 0x86, 0xa4, 0x76, + 0xe8, 0x7f, 0xb4, 0xdb, 0xb1, 0xee, 0x1a, 0x7f, 0x99, 0xd7, + 0x9b, 0x6f, 0x7a, 0x94, 0x5c, 0xec, 0x2c, 0x60, 0x81, 0xad, + 0xa7, 0xbe, 0x80, 0x2e, 0x9f, 0xa6, 0xc0, 0xfb, 0x09, 0x6d, + 0x2b, 0xab, 0xa4, 0x15, 0xc7, 0x79, 0x46, 0x24, 0x89, 0x5c, + 0x32, 0xb9, 0x87, 0xa9, 0x54, 0x1e, 0x12, 0x90, 0x8e, 0x02, + 0x80, 0x8c, 0xf8, 0xdb, 0x2f, 0xbc, 0x98, 0x1b, 0xa2, 0x78, + 0x73, 0x89, 0x03, 0x97, 0xe3, 0x09, 0x08, 0x8b, 0x75, 0xcf, + 0xdc, 0x23, 0x90, 0x59, 0xef, 0x5b, 0x98, 0x24, 0xb8, 0xe8, + 0xcf, 0x75, 0xf0, 0x2f, 0xb7, 0xa3, 0xe6, 0x17, 0x06, 0xf0, + 0x52, 0xfe, 0x21, 0x0a, 0x16, 0x8e, 0xf8, 0xe1, 0xae, 0x25, + 0x11, 0x5d, 0x8c, 0x95, 0x1b, 0x4f, 0x45, 0xb8, 0xa8, 0xcd, + 0xe6, 0xf9, 0xca, 0xa0, 0x54, 0x93, 0x95, 0x86, 0x6f, 0xe4, + 0x93, 0x22, 0x0f, 0xf2, 0xcf, 0xbd, 0x23, 0xb0, 0xf4, 0x8f, + 0x99, 0xa7, 0x67, 0x99, 0x05, 0x13, 0x1f, 0xeb, 0x88, 0xf8, + 0xe2, 0x3b, 0xb9, 0x49, 0x35, 0x89, 0x4f, 0xb8, 0x06, 0x37, + 0x36, 0xda, 0x75, 0x25, 0x0f, 0x0a, 0xaa, 0xc2, 0x6c, 0x3e, + 0xb1, 0x2d, 0x16, 0xf3, 0x17, 0xdb, 0xe2, 0x16, 0x32, 0x39, + 0x92, 0x4b, 0x5f, 0xc0, 0x5f, 0x6e, 0xd0, 0x1c, 0x7e, 0xc0, + 0x51, 0xd9, 0xb3, 0xe2, 0x37, 0xc7, 0xe0, 0x40, 0x13, 0x7d, + 0x06, 0xcd, 0xcd, 0x72, 0xb6, 0x53, 0x2d, 0x7e, 0x60, 0x49, + 0xfe, 0x31, 0xe1, 0xd0, 0x0e, 0x4c, 0x98, 0x93, 0xe0, 0xf6, + 0xf2, 0xfa, 0x99, 0x7f, 0x65, 0xd8, 0x15, 0xc6, 0x3a, 0xb8, + 0x4d, 0x63, 0x21, 0x78, 0xe4, 0x19, 0x6b, 0xbd, 0xde, 0x40, + 0x5b, 0x8c, 0xfa, 0x49, 0x75, 0x23, 0x8f, 0x14, 0xc2, 0x3b, + 0xa3, 0x9b, 0xc5, 0x80, 0x1a, 0xa3, 0x60, 0xd7, 0x17, 0x27, + 0xf0, 0x18, 0x0f, 0xba, 0x02, 0xf7, 0x7a, 0xed, 0xa4, 0x00, + 0x77, 0xde, 0x4b, 0xdd, 0xf9, 0xd7, 0x3e, 0x75, 0xed, 0x1a, + 0x43, 0x26, 0x71, 0x1b, 0xbc, 0x72, 0xf5, 0x70, 0x72, 0x03, + 0x70, 0x25, 0x87, 0x81, 0x6a, 0x92, 0x2d, 0xb7, 0x02, 0xf0, + 0x10, 0x79, 0x65, 0x9d, 0x4e, 0x11, 0x7d, 0x5c, 0x5b, 0x37, + 0xaa, 0xb4, 0xfa, 0x43, 0x66, 0x48, 0x6c, 0x67, 0x64, 0x9e, + 0x15, 0x75, 0x36, 0xe7, 0x25, 0x55, 0x07, 0x7f, 0x74, 0x1f, + 0x2c, 0x28, 0x76, 0xe7, 0x9b, 0x3d, 0x91, 0x0b, 0xcd, 0x6a, + 0x1d, 0x5a, 0xea, 0x63, 0xd0, 0xf9, 0x02, 0x82, 0x01, 0xe0, + 0x3e, 0x31, 0xf2, 0xf4, 0x29, 0x92, 0xa2, 0x93, 0xd5, 0xda, + 0xc9, 0x16, 0x7e, 0xf6, 0xdb, 0x33, 0x9f, 0xaf, 0x4b, 0x01, + 0xd1, 0x28, 0x2d, 0x3a, 0xc0, 0x51, 0x91, 0x26, 0xbd, 0xa5, + 0x1e, 0xdd, 0xd9, 0x2e, 0x11, 0x93, 0x19, 0x29, 0x47, 0x5d, + 0x63, 0xe4, 0xb6, 0xf1, 0xea, 0x12, 0x29, 0xa1, 0x65, 0x12, + 0x6d, 0x78, 0x8f, 0x63, 0x31, 0xec, 0x72, 0x54, 0x73, 0x72, + 0x26, 0x48, 0x57, 0x57, 0xc8, 0xde, 0x28, 0x27, 0xf5, 0x62, + 0xfb, 0x7f, 0x1b, 0xf3, 0xaf, 0x31, 0x01, 0xfc, 0x01, 0x58, + 0x7a, 0x80, 0x72, 0x9d, 0x6e, 0x07, 0xcc, 0x45, 0x67, 0xc6, + 0x26, 0xfe, 0x25, 0xa5, 0x9b, 0x64, 0xcd, 0x45, 0xe3, 0x31, + 0x38, 0x05, 0x07, 0x36, 0x05, 0x46, 0x9c, 0xc1, 0x8e, 0xbf, + 0x4e, 0x71, 0x5f, 0xea, 0xe5, 0x0c, 0x9a, 0x41, 0xc8, 0x94, + 0xcc, 0xf1, 0x73, 0x06, 0x30, 0x54, 0x76, 0x23, 0xb7, 0x22, + 0x7a, 0x8e, 0xe6, 0x42, 0xa1, 0xa0, 0x32, 0x12, 0xe9, 0x08, + 0x1c, 0x46, 0x79, 0x0c, 0x82, 0x7a, 0x95, 0x79, 0xbf, 0x83, + 0x80, 0xeb, 0xab, 0x3d, 0x32, 0xc5, 0xde, 0x62, 0xeb, 0x90, + 0x29, 0x73, 0x05, 0xc8, 0x0a, 0xb1, 0x51, 0xf1, 0x23, 0xdd, + 0x1e, 0xf5, 0x02, 0x3e, 0x74, 0xbc, 0x24, 0x0c, 0x60, 0x36, + 0x2a, 0x28, 0x4d, 0xe6, 0x86, 0x98, 0x7c, 0xd9, 0xe1, 0xac, + 0x21, 0x33, 0xaa, 0xa9, 0x8b, 0xb6, 0x8a, 0x1b, 0xf7, 0x54, + 0x14, 0xf3, 0x0d, 0x4f, 0xcd, 0x7c, 0xf5, 0xc2, 0x6d, 0xc2, + 0xf0, 0xe2, 0xfc, 0x63, 0x1e, 0xa6, 0xa9, 0xa9, 0xd9, 0x73, + 0x2a, 0xd5, 0x0a, 0x38, 0xd8, 0xc0, 0xb7, 0xe1, 0x51, 0xe4, + 0x23, 0x37, 0xf7, 0x85, 0x66, 0x0e, 0x3f, 0x1a, 0x8c, 0xcf, + 0x12, 0xa2, 0x47, 0x6f, 0x73, 0x91, 0x21, 0xe3, 0x93, 0x6b, + 0x74, 0x4f, 0xc5, 0xa1, 0xe7, 0x32, 0xf7, 0x86, 0xdd, 0x1a, + 0x6e, 0x96, 0xda, 0x32, 0x1d, 0xdd, 0xfa, 0x42, 0xd5, 0xd4, + 0xfd, 0xae, 0x7a, 0xa1, 0xed, 0x3d, 0x79, 0xfe, 0x88, 0x84, + 0x43, 0xa7, 0xec, 0xf3, 0x7a, 0x13, 0xaa, 0xa1, 0x82, 0x02, + 0x83, 0x19, 0x43, 0x0a, 0x46, 0x78, 0x07, 0xd9, 0x4d, 0xff, + 0xac, 0x67, 0xd6, 0x29, 0x89, 0xfe, 0x2b, 0xab, 0x5f, 0x9a, + 0x87, 0x99, 0x80, 0xaf, 0x70, 0x4a, 0x6a, 0xb9, 0x5a, 0xc2, + 0xac, 0x7f, 0xa2, 0xc7, 0xad, 0xe2, 0x1f, 0xec, 0xc5, 0x12, + 0x17, 0x08, 0x87, 0x8f, 0x20, 0x95, 0xbe, 0xaf, 0x62, 0x2c, + 0xc2, 0x3f, 0x89, 0x56, 0xd8, 0x50, 0x96, 0x97, 0x72, 0xe2, + 0x92, 0xe1, 0x2a, 0xd8, 0x84, 0x9f, 0x31, 0xe3, 0x06, 0xd8, + 0xe5, 0x91, 0x63, 0x19, 0xe1, 0x27, 0xad, 0xe2, 0xf2, 0x0a, + 0x5e, 0x78, 0x8b, 0x1b, 0x13, 0x31, 0x4b, 0xbd, 0x77, 0xb2, + 0xd6, 0x5c, 0x92, 0x81, 0x50, 0x02, 0x37, 0xd2, 0xe6, 0xeb, + 0x66, 0x6b, 0xaa, 0xfc, 0xcd, 0x54, 0x5d, 0xb8, 0x03, 0x87, + 0xe8, 0xfa, 0xb2, 0xde, 0xcb, 0xf8, 0x6e, 0x58, 0xde, 0xcb, + 0x09, 0x54, 0x8a, 0x9f, 0x46, 0xa3, 0x7e, 0x8d, 0x15, 0xff, + 0x1b, 0x0d, 0x89, 0xc4, 0x1a, 0x21, 0x31, 0x5e, 0xed, 0x0b, + 0x67, 0x3c, 0x70, 0xed, 0x92, 0x48, 0xef, 0xec, 0xf0, 0x77, + 0xc2, 0x79, 0x6c, 0x06, 0x09, 0xaa, 0xab, 0xf6, 0x4c, 0xcd, + 0xfa, 0x7e, 0x4a, 0x88, 0xdc, 0xa8, 0x9b, 0xd3, 0x69, 0x94, + 0x88, 0x09, 0x1d, 0x30, 0x43, 0x9e, 0x2c, 0xcb, 0x01, 0x1d, + 0x4a, 0x3b, 0x04, 0xec, 0x0e, 0xb1, 0xde, 0x09, 0xad, 0x29, + 0x02, 0x82, 0x01, 0xe1, 0x00, 0x9f, 0x02, 0x13, 0x7a, 0xd0, + 0xa9, 0x8a, 0x7a, 0xa0, 0x05, 0xbb, 0x44, 0x6f, 0xaf, 0xf7, + 0xe3, 0xd4, 0x35, 0xef, 0x73, 0x39, 0xd5, 0xe0, 0xa2, 0x0f, + 0x1a, 0x25, 0xa8, 0xf7, 0xc2, 0xa5, 0xec, 0x57, 0xf8, 0x0d, + 0x2a, 0xb6, 0x64, 0x03, 0x8c, 0x22, 0x0f, 0xe7, 0x98, 0xa1, + 0x12, 0xfe, 0x24, 0xef, 0x61, 0x28, 0x9f, 0xa7, 0x22, 0x6b, + 0x6d, 0xab, 0x8d, 0x7d, 0x2a, 0x8b, 0xae, 0x8b, 0xfd, 0xcb, + 0xd5, 0x0b, 0x79, 0x1b, 0x89, 0xcb, 0x5b, 0x7a, 0x8c, 0xdc, + 0xe8, 0x8d, 0xdd, 0x35, 0x9f, 0x06, 0x69, 0x64, 0x12, 0xeb, + 0x46, 0x79, 0xdf, 0x82, 0x2c, 0x89, 0x75, 0x9e, 0x7a, 0xec, + 0xad, 0xe5, 0x88, 0x31, 0xfa, 0x86, 0x93, 0xca, 0xf1, 0x2d, + 0x9b, 0x62, 0x5a, 0xe9, 0x43, 0x09, 0xf3, 0x8c, 0xe5, 0xc7, + 0xc0, 0xce, 0x86, 0xe7, 0xdb, 0xc7, 0x4d, 0x27, 0xd5, 0xee, + 0x76, 0xce, 0x35, 0x30, 0x47, 0xef, 0x00, 0x1b, 0x69, 0x9a, + 0x3f, 0xa5, 0x2a, 0xc9, 0x07, 0xab, 0x99, 0xba, 0x2a, 0xe7, + 0xfb, 0xa9, 0x4e, 0xb9, 0xae, 0x2c, 0x50, 0xfc, 0x35, 0x49, + 0xe6, 0x97, 0x78, 0x3c, 0xb1, 0x59, 0xd7, 0x1d, 0x4e, 0x4e, + 0xea, 0xde, 0xa0, 0xd0, 0xc4, 0x1d, 0xb1, 0xd3, 0x53, 0x1e, + 0xf9, 0xbf, 0xb3, 0x6a, 0x17, 0xb4, 0xda, 0xcc, 0x27, 0x19, + 0xc6, 0x35, 0xe8, 0x28, 0xd3, 0xe3, 0x76, 0x3a, 0xdc, 0xd0, + 0x75, 0xc8, 0xb4, 0x6c, 0xbe, 0x84, 0x2a, 0x45, 0xd1, 0x43, + 0x22, 0x54, 0xd7, 0xc5, 0xd0, 0xd7, 0x73, 0x35, 0x6b, 0xa8, + 0xfa, 0xad, 0x60, 0xc0, 0x64, 0xc1, 0x58, 0x89, 0x09, 0x81, + 0x0a, 0x0b, 0xea, 0x33, 0x91, 0xb0, 0xef, 0x53, 0x50, 0x41, + 0xae, 0xd9, 0xee, 0xbe, 0x9e, 0xf0, 0x0b, 0xa0, 0x7c, 0xbf, + 0x3f, 0xc9, 0x4b, 0xe0, 0x48, 0xd8, 0x10, 0xd5, 0x2e, 0xce, + 0xf0, 0x7c, 0xd8, 0x05, 0xde, 0x09, 0x7e, 0x8c, 0x63, 0x4c, + 0xdb, 0x8b, 0x91, 0xcd, 0x7f, 0xb6, 0x6b, 0xad, 0xce, 0xb1, + 0x17, 0x6c, 0xf7, 0x08, 0x0d, 0x7c, 0xda, 0x4f, 0x0a, 0x07, + 0xd0, 0xae, 0x72, 0x3c, 0x67, 0x4a, 0x44, 0x54, 0x47, 0xce, + 0xe1, 0x17, 0x07, 0x12, 0xde, 0x52, 0xef, 0xef, 0x4c, 0x2b, + 0x42, 0x7d, 0x09, 0x80, 0x36, 0x34, 0xdc, 0x45, 0x6f, 0xb0, + 0x2d, 0xab, 0xa0, 0x0c, 0x58, 0xae, 0x35, 0xd3, 0x9b, 0x37, + 0xc1, 0x1d, 0xeb, 0xfe, 0xc3, 0x04, 0xc9, 0x1d, 0xe7, 0x3d, + 0x16, 0x64, 0xed, 0xf5, 0xe8, 0xdf, 0x99, 0xa4, 0xfb, 0xad, + 0x79, 0x88, 0xd5, 0x8c, 0x62, 0x33, 0x9e, 0x35, 0xa6, 0x7f, + 0x9d, 0xb6, 0x1a, 0x40, 0x6d, 0xc3, 0x89, 0x5d, 0x7b, 0xe2, + 0xc8, 0xd3, 0x16, 0x13, 0x07, 0x9a, 0x38, 0x22, 0x33, 0x03, + 0xac, 0x70, 0x3e, 0xce, 0x32, 0x56, 0x0b, 0x58, 0x56, 0xb8, + 0xe9, 0xd8, 0x42, 0x35, 0x6c, 0xb9, 0x02, 0xb3, 0x64, 0xeb, + 0xaa, 0x09, 0x3f, 0xac, 0x66, 0x08, 0xb4, 0x5f, 0x3e, 0xb4, + 0xec, 0x39, 0xb1, 0x99, 0xe4, 0x5d, 0x1d, 0x32, 0x14, 0xc1, + 0x48, 0x8f, 0x6c, 0x65, 0x87, 0x34, 0x50, 0xa4, 0xf4, 0x9b, + 0x5b, 0x2e, 0xb5, 0x79, 0x0d, 0x11, 0x62, 0xa4, 0x35, 0x9c, + 0x6f, 0x92, 0xd0, 0x68, 0x07, 0xdd, 0x69, 0x85, 0x48, 0xe3, + 0x5d, 0x10, 0x34, 0xaf, 0xea, 0x41, 0x72, 0x5a, 0x71, 0x00, + 0xf8, 0xe6, 0x47, 0x7f, 0xa0, 0x6f, 0x91, 0x96, 0x40, 0x00, + 0x40, 0x70, 0xfb, 0x63, 0xcf, 0xc9, 0x36, 0x04, 0x1c, 0x3b, + 0x11, 0x08, 0x29, 0x81, 0x9f +}; + +static unsigned char test15360[] = { + 0x30, 0x82, 0x21, 0xe8, 0x02, 0x01, 0x00, 0x02, 0x82, 0x07, + 0x81, 0x00, 0xad, 0x3f, 0xaa, 0xdc, 0x8c, 0x85, 0xcb, 0x60, + 0xd2, 0xf5, 0x30, 0xa1, 0x0f, 0x26, 0xec, 0xdf, 0xfc, 0x91, + 0x39, 0xbd, 0x3e, 0x8f, 0x99, 0x64, 0x1e, 0x51, 0xd2, 0x27, + 0x5e, 0x76, 0xcd, 0x86, 0x33, 0x07, 0xf9, 0xbd, 0x3b, 0x06, + 0xc3, 0x3c, 0x85, 0xcb, 0x7e, 0x91, 0x14, 0xb0, 0x0b, 0x77, + 0x22, 0x30, 0x71, 0xb8, 0xbb, 0x74, 0x30, 0x33, 0x35, 0x56, + 0x34, 0x47, 0x10, 0x8f, 0x88, 0xe2, 0x6f, 0xdc, 0x3b, 0xe9, + 0x58, 0x9d, 0x0c, 0xdc, 0x8f, 0x70, 0x41, 0x7a, 0x12, 0xd2, + 0x9a, 0x35, 0xbe, 0x0a, 0x57, 0x13, 0x0c, 0xe9, 0xbf, 0x77, + 0x54, 0x00, 0x74, 0xb7, 0x1a, 0x3e, 0xa7, 0xe9, 0xb6, 0xe7, + 0x4f, 0x1e, 0xa4, 0xc0, 0x7c, 0x4c, 0x66, 0xc5, 0xce, 0xad, + 0x96, 0x1b, 0xe2, 0x1a, 0xf1, 0x3d, 0x8b, 0x50, 0xcf, 0xe2, + 0x15, 0x21, 0x6d, 0x83, 0x95, 0x00, 0xee, 0x97, 0xc4, 0xae, + 0xc9, 0x38, 0x62, 0x6c, 0xb2, 0xe7, 0x7f, 0x15, 0x0a, 0xab, + 0x86, 0xb9, 0xd9, 0x8a, 0xf8, 0xeb, 0x88, 0x5d, 0xdc, 0x0c, + 0x1e, 0xc5, 0xe6, 0xa1, 0x7b, 0xbf, 0xf1, 0x02, 0xe3, 0xad, + 0xf8, 0xed, 0x17, 0x9f, 0x83, 0x11, 0x31, 0x3b, 0xad, 0xb4, + 0xf9, 0x8d, 0x1d, 0x56, 0x9b, 0xac, 0x68, 0x55, 0x0a, 0x74, + 0x20, 0xee, 0x57, 0xe7, 0x1c, 0x6d, 0x05, 0xa1, 0x4e, 0xa5, + 0x11, 0x99, 0xb4, 0x86, 0xdb, 0x58, 0xe7, 0xf6, 0xb6, 0x4f, + 0x92, 0x58, 0x57, 0x9b, 0x74, 0x04, 0xe5, 0xd1, 0x1d, 0x7c, + 0x4b, 0xb8, 0x1f, 0x5d, 0x0e, 0x93, 0xee, 0x44, 0x18, 0xb6, + 0x58, 0x0e, 0xa1, 0x0b, 0x8e, 0x2e, 0x99, 0x4c, 0x72, 0x91, + 0xfa, 0xfa, 0xe2, 0x22, 0x05, 0x5d, 0x2b, 0x2d, 0xd8, 0x60, + 0xd5, 0x1b, 0x08, 0x56, 0x2b, 0xb5, 0x21, 0xdb, 0x1a, 0xe6, + 0xa8, 0x39, 0xa2, 0xf4, 0x58, 0xcb, 0xd2, 0xf9, 0xce, 0xc0, + 0x1e, 0x1b, 0xf9, 0xa7, 0x37, 0xca, 0xa3, 0x77, 0x6e, 0xb1, + 0xaf, 0x33, 0xb5, 0x6d, 0x5f, 0x33, 0x2e, 0x1a, 0x34, 0xdb, + 0x42, 0xbe, 0x5f, 0xf9, 0x09, 0xb7, 0x9f, 0xd4, 0x09, 0xfb, + 0x87, 0x13, 0x3c, 0xe2, 0x27, 0xb8, 0xf3, 0x1d, 0x7e, 0x92, + 0xdd, 0x87, 0x86, 0x55, 0x69, 0x9b, 0x55, 0xcd, 0xef, 0x7a, + 0x71, 0x5d, 0x81, 0x3a, 0xd9, 0xf7, 0x7f, 0xde, 0xe0, 0x92, + 0xd9, 0x78, 0x0f, 0x1d, 0x43, 0xb1, 0x1e, 0x29, 0xc1, 0x49, + 0xb6, 0x5e, 0x85, 0x83, 0xd9, 0x04, 0xfd, 0x79, 0xd8, 0x47, + 0x03, 0x2e, 0x85, 0x19, 0xfd, 0x63, 0xe7, 0xa4, 0x8b, 0xc0, + 0x94, 0x0e, 0xb7, 0x54, 0x97, 0xd6, 0x44, 0x5d, 0x63, 0x12, + 0xff, 0xdd, 0xde, 0x2c, 0x00, 0x0e, 0xc9, 0xca, 0x7e, 0xa2, + 0x65, 0x25, 0xb0, 0x1d, 0xa9, 0x20, 0x4f, 0xdd, 0xea, 0x3a, + 0xb5, 0xe8, 0x0f, 0xf3, 0xb2, 0xb7, 0x00, 0x4a, 0xe8, 0xa4, + 0x83, 0x49, 0xbd, 0x78, 0xdf, 0xac, 0x2c, 0x37, 0x81, 0xb3, + 0xf3, 0xb7, 0x13, 0x93, 0x3e, 0xb2, 0x79, 0x55, 0xf2, 0xd8, + 0x9c, 0xf7, 0xf2, 0xf1, 0xd5, 0x6c, 0x9c, 0xff, 0xec, 0xf4, + 0xea, 0x08, 0x3c, 0x65, 0x35, 0xb7, 0x09, 0x03, 0x6d, 0x99, + 0x1d, 0x5b, 0x73, 0x06, 0x61, 0xb4, 0xf0, 0xc5, 0xdb, 0x3e, + 0xe0, 0x1d, 0xa8, 0x5b, 0x7a, 0x5b, 0x5b, 0x9c, 0x11, 0x75, + 0x83, 0x1d, 0xf4, 0x73, 0x27, 0xf3, 0x79, 0xf2, 0x82, 0xd6, + 0x28, 0x45, 0x58, 0x23, 0x6c, 0x29, 0xd3, 0x50, 0x51, 0x1b, + 0x38, 0xef, 0x89, 0x90, 0x84, 0xa2, 0x4c, 0x35, 0x7b, 0x30, + 0x5e, 0xbd, 0x1a, 0xd5, 0xdf, 0xcd, 0xcd, 0x74, 0x3f, 0x2e, + 0x01, 0xea, 0x33, 0x07, 0x74, 0xfb, 0x86, 0x75, 0x20, 0x0e, + 0x4f, 0xbf, 0x65, 0xd4, 0x15, 0x19, 0x6f, 0x8d, 0x37, 0xcd, + 0xb6, 0x6f, 0x50, 0x9d, 0x5e, 0x04, 0x81, 0x7d, 0xec, 0xd6, + 0xbb, 0x40, 0x1b, 0xe0, 0xf5, 0xd5, 0x86, 0x26, 0xc5, 0x41, + 0x84, 0x0e, 0x3e, 0x73, 0xb7, 0xa4, 0xbe, 0x2a, 0xfe, 0xd7, + 0xe4, 0x4d, 0x5c, 0x2d, 0x6a, 0x04, 0xe6, 0xdd, 0x28, 0xa0, + 0x75, 0x4c, 0xe0, 0x23, 0x2c, 0xad, 0xec, 0xaa, 0x72, 0xfd, + 0x03, 0xc0, 0x65, 0xfa, 0xc4, 0x3c, 0x25, 0x10, 0xae, 0x3f, + 0x09, 0x96, 0x4e, 0xff, 0xfe, 0xc7, 0xe4, 0x9e, 0xec, 0xb5, + 0x6e, 0xec, 0xf3, 0x7a, 0x83, 0x7a, 0x8b, 0xbb, 0x91, 0x8d, + 0xab, 0x3c, 0x4d, 0x7f, 0x34, 0x77, 0xbe, 0x0c, 0x87, 0xf2, + 0xc3, 0xd6, 0xcb, 0xcc, 0xfa, 0x1e, 0xaf, 0x21, 0x24, 0xe9, + 0xaa, 0x89, 0x61, 0x0c, 0x7a, 0x1c, 0x7d, 0x00, 0x87, 0x69, + 0x30, 0xa0, 0xb4, 0x3b, 0x96, 0x1c, 0x00, 0x14, 0x07, 0xb8, + 0x3f, 0x59, 0x62, 0x3a, 0x3f, 0xfb, 0x68, 0xb8, 0x81, 0x7d, + 0x4a, 0x9d, 0x1c, 0xa2, 0x07, 0xa3, 0xb1, 0x42, 0x7b, 0xfa, + 0x9b, 0xbc, 0x94, 0x30, 0x7e, 0xea, 0xe7, 0x40, 0x7e, 0xd4, + 0x0f, 0x33, 0x3b, 0x57, 0xda, 0x8b, 0x6d, 0x64, 0xd5, 0xe4, + 0x91, 0x83, 0xf0, 0x3d, 0xae, 0x8b, 0x91, 0xf0, 0xcd, 0xb1, + 0xa0, 0xe0, 0x0d, 0xe1, 0xbb, 0x22, 0x78, 0x1f, 0x3a, 0xe5, + 0x53, 0x28, 0xf0, 0x35, 0xae, 0x71, 0xe6, 0xfd, 0x63, 0xb2, + 0x9c, 0x3f, 0xdd, 0x95, 0x7b, 0xc4, 0xe9, 0x2f, 0xd9, 0x93, + 0x3a, 0x10, 0x42, 0x1c, 0x90, 0xab, 0xfb, 0xd3, 0x02, 0xe9, + 0x59, 0xbc, 0x53, 0x7e, 0xf3, 0xe1, 0x52, 0x15, 0xa6, 0x58, + 0x9e, 0xc1, 0xa6, 0x0e, 0x2e, 0x35, 0x07, 0x3a, 0xc3, 0x1f, + 0xaa, 0x58, 0xe7, 0xc6, 0x33, 0x6a, 0x39, 0x4b, 0x21, 0x15, + 0x3d, 0x92, 0x4e, 0x5e, 0xf9, 0x01, 0xd6, 0x0f, 0x28, 0x61, + 0x15, 0xdf, 0xed, 0x6f, 0x75, 0xc4, 0x8f, 0xcb, 0x16, 0x55, + 0x09, 0xc7, 0x24, 0xb2, 0x0c, 0x49, 0x25, 0x8d, 0x5e, 0xf1, + 0x0e, 0xe0, 0xe2, 0xc4, 0xcc, 0x1f, 0x4e, 0x60, 0x5c, 0x5e, + 0xc6, 0x7f, 0x68, 0x7f, 0xdb, 0x1a, 0x01, 0x67, 0x07, 0xb1, + 0x56, 0x93, 0xf2, 0x26, 0x81, 0xc0, 0x33, 0xb8, 0x48, 0xf9, + 0x2c, 0x5c, 0x18, 0x29, 0xed, 0xe0, 0x6c, 0xa0, 0xac, 0xd2, + 0x90, 0x4b, 0x52, 0x87, 0xbb, 0xb5, 0x05, 0xd8, 0x56, 0xc5, + 0xb8, 0x8f, 0x3f, 0x49, 0x52, 0x9a, 0xa2, 0xd0, 0x40, 0x80, + 0x5b, 0x16, 0x15, 0xbc, 0x74, 0x8e, 0x00, 0x10, 0xaf, 0xfb, + 0x6d, 0xba, 0xcb, 0xbc, 0xe6, 0x13, 0x75, 0xce, 0x27, 0xae, + 0x85, 0x57, 0x6c, 0xc0, 0x8a, 0x84, 0x6f, 0x34, 0x16, 0xd4, + 0x35, 0xd2, 0xcc, 0x55, 0x00, 0xc1, 0xd8, 0x28, 0x2c, 0x9c, + 0x84, 0x78, 0xbf, 0xf0, 0x3b, 0x0d, 0x9f, 0x81, 0xd4, 0xef, + 0x99, 0x77, 0x53, 0xd2, 0x8e, 0x43, 0x52, 0xf0, 0x32, 0x7e, + 0xba, 0xbf, 0xb6, 0x0e, 0x9d, 0x9b, 0x00, 0xd0, 0x50, 0x55, + 0x67, 0x5a, 0x2c, 0x8b, 0x9b, 0x29, 0xfb, 0x41, 0x74, 0x4c, + 0xb7, 0xd8, 0x98, 0xa2, 0xfb, 0x73, 0x07, 0x96, 0xef, 0xcd, + 0x47, 0x13, 0x1d, 0xe2, 0xb1, 0xac, 0xf3, 0xcf, 0x47, 0x98, + 0x7b, 0x6f, 0xf6, 0x32, 0x44, 0x41, 0x78, 0x09, 0x8e, 0x64, + 0x0c, 0xbf, 0xe2, 0x0f, 0x8c, 0x44, 0x2f, 0x4e, 0x55, 0xe0, + 0xc6, 0xfd, 0x05, 0x74, 0x18, 0x1a, 0xb9, 0xfa, 0xcb, 0xd3, + 0xfa, 0x69, 0x50, 0x63, 0xce, 0x2b, 0xef, 0x92, 0x0f, 0x11, + 0xd4, 0x9b, 0x53, 0x6c, 0xed, 0xc5, 0x0b, 0x7c, 0xbd, 0xa1, + 0x5d, 0xdf, 0xab, 0xcf, 0xaa, 0x83, 0x5e, 0xa8, 0xc5, 0xfe, + 0x91, 0x2b, 0x23, 0x1f, 0x39, 0x3d, 0x71, 0x74, 0xbf, 0xa2, + 0xf1, 0xda, 0x2f, 0x29, 0x02, 0x9b, 0xea, 0x48, 0x2c, 0xaf, + 0xe7, 0xa9, 0xf5, 0x68, 0xab, 0x8f, 0x18, 0xb9, 0x7b, 0x28, + 0xf0, 0x92, 0xfb, 0x07, 0xd7, 0xbd, 0x43, 0xcd, 0x7f, 0xfc, + 0xb9, 0x5f, 0x24, 0xf8, 0x48, 0x2e, 0xbe, 0x42, 0x87, 0x80, + 0x38, 0x78, 0x9e, 0x8c, 0x52, 0x6d, 0xfa, 0x2e, 0x46, 0x35, + 0x7a, 0x59, 0x88, 0xb9, 0x3e, 0xcb, 0x79, 0xb4, 0x8a, 0x9e, + 0xd5, 0xd0, 0x30, 0x8c, 0xb2, 0x0c, 0x9d, 0x8d, 0x2d, 0x64, + 0x0b, 0xf6, 0xeb, 0xf1, 0xde, 0xea, 0x74, 0xfc, 0xbc, 0x01, + 0x18, 0x48, 0x4e, 0x35, 0x02, 0x83, 0x01, 0xb2, 0x50, 0xa0, + 0x44, 0x19, 0x30, 0x00, 0x12, 0x4a, 0xa0, 0x6d, 0x6b, 0x8b, + 0xf1, 0xce, 0xda, 0x2e, 0x16, 0x35, 0x52, 0x26, 0xf9, 0xbe, + 0xb1, 0x37, 0xfc, 0x0a, 0x8b, 0x6f, 0x06, 0x11, 0x7b, 0xf7, + 0xa8, 0x40, 0xbd, 0x8d, 0x94, 0xa4, 0xa2, 0xe0, 0xb6, 0xdf, + 0x62, 0xc0, 0x6f, 0xb3, 0x5d, 0x84, 0xb9, 0xaa, 0x2f, 0xc1, + 0x3b, 0xcb, 0x20, 0xc6, 0x68, 0x69, 0x15, 0x74, 0xbc, 0xdb, + 0x43, 0x9c, 0x4a, 0xfc, 0x72, 0xc1, 0xf5, 0x87, 0x80, 0xe8, + 0x6c, 0xd5, 0xc1, 0x2e, 0x34, 0x5e, 0x96, 0x76, 0x08, 0x3e, + 0x45, 0xe4, 0xa0, 0x4a, 0x7a, 0xc1, 0x67, 0x38, 0xf2, 0x31, + 0x1f, 0x7b, 0x0f, 0x54, 0xbd, 0x0d, 0x1f, 0x9e, 0x8e, 0x99, + 0x8b, 0x58, 0xd9, 0x94, 0x87, 0xaa, 0x8b, 0x82, 0x5d, 0x5e, + 0xe8, 0x50, 0xf4, 0xf2, 0xc7, 0xe9, 0x85, 0x6b, 0xd2, 0xef, + 0x13, 0xc1, 0xed, 0x57, 0x2a, 0xc5, 0xd6, 0x5d, 0xa4, 0x3b, + 0x29, 0xba, 0xab, 0x1b, 0xaa, 0x21, 0x41, 0xe9, 0xdc, 0x47, + 0x88, 0xef, 0x0c, 0xfc, 0xb2, 0xdc, 0xf7, 0xdb, 0x55, 0x4d, + 0x70, 0xc7, 0xe2, 0x8a, 0x8a, 0xe1, 0xde, 0xcf, 0xe5, 0xca, + 0x23, 0x36, 0x29, 0xe5, 0xfc, 0x54, 0x66, 0xda, 0xe9, 0xab, + 0x58, 0x20, 0xb2, 0x8e, 0xb2, 0x7d, 0x5d, 0xb8, 0xc7, 0x6c, + 0x48, 0x53, 0x2b, 0x47, 0xe0, 0x12, 0x00, 0x0e, 0xfe, 0xa5, + 0x93, 0x34, 0xf9, 0x3e, 0xa6, 0x3f, 0x56, 0xaa, 0x43, 0x65, + 0xbb, 0x5a, 0x70, 0x3e, 0x62, 0xac, 0x3f, 0x5b, 0x90, 0x02, + 0x50, 0x5d, 0x05, 0xa8, 0xd5, 0x67, 0x1a, 0x62, 0xec, 0xd4, + 0xde, 0x29, 0x04, 0xac, 0x6d, 0x15, 0x5d, 0xa0, 0xec, 0xf2, + 0x57, 0x13, 0x0e, 0x17, 0x96, 0x0c, 0x32, 0x6a, 0xc5, 0xe0, + 0xa8, 0xff, 0x85, 0xa4, 0xa3, 0xe3, 0x0e, 0x35, 0x5d, 0xd1, + 0x28, 0x84, 0xaa, 0xc4, 0x84, 0xcd, 0x25, 0x63, 0x85, 0x82, + 0x3e, 0x12, 0x30, 0x17, 0x57, 0x45, 0xb8, 0xb4, 0x34, 0x01, + 0x3a, 0xa2, 0x77, 0x61, 0xc8, 0x3d, 0x1f, 0xc5, 0x0e, 0x4a, + 0xbb, 0xf6, 0xa0, 0x5d, 0x79, 0x4b, 0xc8, 0xf3, 0x9c, 0x87, + 0x05, 0x2f, 0xea, 0x25, 0x28, 0x91, 0x69, 0x77, 0x7c, 0xba, + 0xea, 0x4a, 0x75, 0x2e, 0x2b, 0x17, 0x83, 0x50, 0x32, 0x43, + 0x4f, 0xcd, 0xf1, 0x77, 0xb1, 0x22, 0x0a, 0x8b, 0x69, 0x58, + 0x09, 0x35, 0x07, 0x6d, 0x61, 0x4a, 0x8d, 0x18, 0x65, 0x6e, + 0x9b, 0x62, 0x07, 0xd0, 0x6a, 0x92, 0x39, 0x05, 0x80, 0x14, + 0xfa, 0x1c, 0x93, 0x84, 0x0c, 0xb5, 0x8c, 0x41, 0x91, 0x4e, + 0x48, 0xf0, 0xf2, 0xba, 0x1d, 0x73, 0x2f, 0x1e, 0xa1, 0x55, + 0xc3, 0x02, 0x8c, 0xb1, 0xf2, 0x37, 0xa6, 0x9a, 0x6b, 0xcd, + 0x45, 0x2e, 0x08, 0x90, 0x26, 0x63, 0x91, 0xff, 0x22, 0x5e, + 0xcd, 0xae, 0x9b, 0x19, 0x1e, 0x10, 0x62, 0x4e, 0x1f, 0x2d, + 0x81, 0x69, 0x4f, 0x41, 0xe5, 0x94, 0xff, 0x7e, 0xcc, 0x15, + 0x36, 0x1e, 0x29, 0x59, 0x37, 0xe7, 0x64, 0x40, 0x17, 0x1a, + 0x32, 0xba, 0x01, 0x26, 0x30, 0x80, 0x60, 0x07, 0x86, 0x6e, + 0xd4, 0xb3, 0xe2, 0x44, 0x16, 0x33, 0xf2, 0x4c, 0x84, 0x0e, + 0xb1, 0x4a, 0xc7, 0x92, 0xa6, 0xa3, 0x42, 0x36, 0x05, 0x3e, + 0x74, 0xa8, 0xb1, 0xc5, 0x63, 0x59, 0x0d, 0x1e, 0x36, 0x45, + 0x2b, 0x36, 0x5e, 0xca, 0xab, 0x97, 0x49, 0xd3, 0xab, 0xae, + 0x63, 0x0a, 0xd1, 0x03, 0x57, 0x88, 0xa4, 0xa4, 0x3c, 0xda, + 0x15, 0x49, 0x1a, 0x5d, 0xe6, 0x5e, 0xb9, 0x82, 0x23, 0xc0, + 0x83, 0x96, 0xfe, 0x38, 0x0b, 0x80, 0x0e, 0xde, 0x22, 0xeb, + 0x5d, 0xe4, 0x56, 0x32, 0xbe, 0xe0, 0xc0, 0x6e, 0x69, 0x63, + 0x27, 0x4e, 0x00, 0x58, 0x80, 0x70, 0xd9, 0xcc, 0x4e, 0xae, + 0x6c, 0x5e, 0x6a, 0x43, 0x81, 0xfd, 0x45, 0xb2, 0xa4, 0x6c, + 0xf0, 0x9c, 0x66, 0x5c, 0x7d, 0x5c, 0x78, 0x55, 0x33, 0x4b, + 0x3c, 0x3b, 0x1d, 0x18, 0x58, 0x79, 0x6a, 0x02, 0xec, 0xce, + 0x53, 0x69, 0xc0, 0x17, 0xed, 0x57, 0xaf, 0x71, 0x5b, 0x42, + 0x1b, 0x49, 0xd8, 0xe8, 0x96, 0x80, 0xb6, 0x48, 0x1b, 0x7c, + 0xf8, 0x74, 0x1c, 0xb1, 0xc4, 0x10, 0xb7, 0xf4, 0x97, 0x7e, + 0x6b, 0x8f, 0x54, 0xba, 0x37, 0xb9, 0x35, 0x9e, 0x7b, 0x17, + 0x16, 0x9b, 0x89, 0x39, 0xae, 0x4f, 0x2e, 0x18, 0x65, 0xb4, + 0x76, 0x20, 0x9a, 0x58, 0xe2, 0x57, 0x6e, 0x1c, 0x3f, 0x8e, + 0x9a, 0xbb, 0xd8, 0xfc, 0x4c, 0xd6, 0x2d, 0xc1, 0xa6, 0x46, + 0xac, 0x13, 0x1e, 0xa7, 0xf7, 0x1d, 0x28, 0x3a, 0xf4, 0xd6, + 0x48, 0xfb, 0xe5, 0xb3, 0x84, 0x94, 0x47, 0x92, 0xae, 0x9a, + 0x58, 0xc5, 0xac, 0x23, 0x1b, 0xb5, 0xcd, 0x96, 0xd2, 0x5e, + 0xb2, 0x41, 0xfc, 0x9a, 0xae, 0x19, 0xf1, 0x7b, 0x4b, 0x53, + 0x1b, 0xfa, 0xa5, 0x0c, 0x49, 0x6d, 0xff, 0xf4, 0x51, 0x88, + 0x19, 0x04, 0xd9, 0x85, 0x8e, 0xe2, 0x3a, 0x62, 0x31, 0x5c, + 0x6e, 0xe8, 0x4d, 0x04, 0x1d, 0xd8, 0xc2, 0x7b, 0x51, 0xe7, + 0x59, 0xbc, 0x85, 0x5c, 0xc4, 0xcc, 0xad, 0xcb, 0x93, 0x69, + 0x18, 0xe4, 0x71, 0x9e, 0x63, 0x33, 0x99, 0xb6, 0x3b, 0x23, + 0x11, 0x17, 0x7a, 0x3d, 0x6f, 0xb9, 0x6b, 0xf1, 0xf2, 0xa7, + 0x03, 0xfd, 0xf0, 0xcd, 0x5b, 0xb5, 0xda, 0x9a, 0xd9, 0x95, + 0x02, 0x76, 0xd8, 0x38, 0xd3, 0xbd, 0xa0, 0x4a, 0x9a, 0xab, + 0x70, 0xde, 0xc6, 0xf9, 0xa5, 0x19, 0x9c, 0xc4, 0xf9, 0x07, + 0x4d, 0xea, 0x15, 0xc2, 0x91, 0x4d, 0x54, 0xa9, 0x2c, 0xca, + 0xdf, 0xaa, 0xd1, 0xc4, 0xc0, 0x18, 0x77, 0x28, 0x2a, 0x2c, + 0xc3, 0x7c, 0x26, 0xbd, 0xd8, 0x0d, 0x51, 0xa1, 0x4d, 0xad, + 0x76, 0x76, 0xaa, 0xa9, 0x45, 0x82, 0x4f, 0x76, 0xfb, 0x1a, + 0xd3, 0x71, 0x3c, 0x55, 0xa2, 0x5c, 0xe0, 0xd6, 0xda, 0x35, + 0xbe, 0x25, 0x23, 0x26, 0x51, 0xc6, 0xb4, 0xf3, 0x3e, 0x2c, + 0x54, 0x09, 0xc7, 0x6f, 0xa5, 0x08, 0x81, 0xba, 0x75, 0xda, + 0xcb, 0x4d, 0x05, 0xdd, 0xca, 0x93, 0x48, 0x30, 0xe8, 0x4a, + 0x1f, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x07, + 0x80, 0x25, 0x2f, 0xbc, 0x49, 0xf8, 0xb3, 0xa3, 0x32, 0xd6, + 0x35, 0x20, 0xca, 0x01, 0x49, 0x96, 0xa0, 0x81, 0x42, 0xde, + 0xc4, 0xdb, 0x0f, 0xd1, 0x99, 0xe6, 0xd4, 0x23, 0x2a, 0xa6, + 0x21, 0x13, 0xfe, 0x51, 0x27, 0xce, 0x18, 0x2a, 0xfa, 0x49, + 0x9f, 0xcd, 0x0c, 0x1f, 0xcf, 0x9e, 0x44, 0x27, 0x41, 0xdc, + 0x09, 0xcf, 0xef, 0x19, 0xf5, 0x57, 0x7f, 0x36, 0x5c, 0x99, + 0x7e, 0x03, 0x74, 0xfb, 0xa9, 0xb6, 0xde, 0xeb, 0xd1, 0x2b, + 0x5f, 0x12, 0x6a, 0xa9, 0x33, 0x2c, 0x2a, 0xba, 0xad, 0x8f, + 0xc2, 0x27, 0x57, 0x6a, 0xd7, 0x40, 0xf7, 0x4f, 0x4c, 0x9a, + 0xb0, 0x3a, 0x5d, 0x2e, 0xf9, 0xf1, 0xea, 0xbd, 0x82, 0xaa, + 0xbd, 0xe6, 0x19, 0x16, 0xd5, 0x03, 0x5e, 0x43, 0xfd, 0x88, + 0x71, 0xd5, 0xb7, 0x78, 0xbe, 0x80, 0x0f, 0xc9, 0x7f, 0x3a, + 0x8f, 0xe1, 0x44, 0xd4, 0x0f, 0xce, 0x26, 0xaf, 0x65, 0xe0, + 0xf5, 0x04, 0x53, 0x56, 0x97, 0x4f, 0xf4, 0xc1, 0x44, 0x8d, + 0xf7, 0x88, 0x55, 0x47, 0x16, 0xaf, 0x3f, 0x8e, 0x42, 0xdf, + 0xbc, 0x14, 0xc3, 0xe6, 0x9f, 0x0d, 0x69, 0x54, 0x5b, 0x7c, + 0x49, 0xcf, 0xbf, 0x42, 0x4f, 0xc7, 0x64, 0x8a, 0xe5, 0x84, + 0x87, 0x20, 0x9b, 0xfd, 0x70, 0x25, 0x38, 0xd3, 0xb4, 0x97, + 0x78, 0xf1, 0x4f, 0x3f, 0x0f, 0xbb, 0x9c, 0xa3, 0x17, 0xd5, + 0x4e, 0x4b, 0xac, 0x82, 0x9a, 0x73, 0xb7, 0xc5, 0xec, 0x10, + 0x7a, 0x7b, 0xdb, 0x77, 0x2c, 0xb1, 0xf3, 0x8f, 0xc3, 0xa5, + 0x31, 0x11, 0x32, 0x55, 0x35, 0xb5, 0x77, 0xd2, 0x62, 0x19, + 0x46, 0x92, 0x94, 0xbb, 0x61, 0x0f, 0x30, 0x94, 0x8a, 0xf6, + 0xf7, 0x30, 0xe0, 0xa2, 0x8c, 0x1b, 0xff, 0x8c, 0x29, 0x44, + 0xb4, 0xb7, 0xb6, 0x5f, 0x4d, 0x52, 0xc6, 0x07, 0xe1, 0x28, + 0x8c, 0xae, 0x88, 0x8a, 0x22, 0xbd, 0xd7, 0x36, 0xe4, 0x8f, + 0xd1, 0xeb, 0x65, 0x54, 0x19, 0x5f, 0xba, 0xfb, 0xfc, 0x91, + 0xa1, 0xa4, 0xb8, 0xa4, 0x2d, 0x85, 0x20, 0xc4, 0xe5, 0xa7, + 0x4e, 0xdb, 0xa4, 0xc5, 0xcc, 0x2f, 0x37, 0x41, 0x29, 0x47, + 0x15, 0xff, 0x04, 0x80, 0x08, 0x37, 0xce, 0xc5, 0xe3, 0x5a, + 0x3f, 0x83, 0xbb, 0x03, 0x9e, 0xfe, 0xec, 0xe4, 0x11, 0x41, + 0x12, 0x13, 0xf2, 0x00, 0xe5, 0x1a, 0x02, 0x49, 0xeb, 0xdb, + 0x57, 0xe4, 0xce, 0xa0, 0x3f, 0xfd, 0x3c, 0x73, 0x2b, 0x92, + 0x44, 0x79, 0x9e, 0x12, 0x4f, 0xfa, 0xe4, 0x53, 0x62, 0xf2, + 0xb0, 0xe2, 0x8a, 0xf0, 0x93, 0xa8, 0x1d, 0xee, 0x8d, 0x58, + 0x7a, 0x4c, 0x29, 0x91, 0x29, 0xc1, 0xa4, 0xd5, 0xe6, 0x37, + 0x1b, 0x75, 0x5b, 0xb6, 0x6b, 0x76, 0x2e, 0xcb, 0xbd, 0xa9, + 0xbe, 0x4c, 0x2e, 0x21, 0xa6, 0x38, 0xde, 0x66, 0x2f, 0x51, + 0xea, 0x4c, 0xba, 0x3f, 0x4a, 0xfe, 0x7a, 0x15, 0xb3, 0x72, + 0x26, 0xba, 0xcf, 0x9e, 0x1b, 0x03, 0xa6, 0xaa, 0x65, 0x68, + 0xd3, 0x8c, 0x15, 0x17, 0xe9, 0x11, 0x18, 0x3c, 0xb6, 0xf8, + 0x02, 0x54, 0x98, 0x49, 0xfa, 0x35, 0x3c, 0xcd, 0xac, 0xc8, + 0x2b, 0x1a, 0x63, 0x93, 0x03, 0x05, 0xa1, 0x41, 0xbe, 0x12, + 0xca, 0x15, 0x47, 0x72, 0x63, 0x77, 0x26, 0xd0, 0xe7, 0x8f, + 0x0d, 0x6e, 0x9c, 0xac, 0x07, 0xbe, 0x03, 0x22, 0xd0, 0x39, + 0x63, 0x8d, 0x9b, 0xc6, 0x20, 0x81, 0xb5, 0x67, 0x15, 0xf6, + 0xb0, 0xe3, 0xb9, 0x3e, 0xb7, 0x3f, 0x8f, 0x46, 0xc9, 0x74, + 0x10, 0x1e, 0x53, 0xf1, 0xd4, 0x30, 0x4d, 0x6e, 0x72, 0xb4, + 0x73, 0x1c, 0xb6, 0x79, 0x82, 0x60, 0x2e, 0x2a, 0x7d, 0x82, + 0x95, 0xb5, 0x7c, 0x4d, 0x44, 0xcb, 0xd8, 0x8a, 0x17, 0xe8, + 0x50, 0x29, 0xd8, 0x3a, 0xeb, 0x29, 0xc1, 0x83, 0x0f, 0xd9, + 0xaf, 0xcc, 0xfa, 0xea, 0x3a, 0x47, 0x5d, 0x33, 0x1f, 0xe8, + 0x33, 0x5b, 0x88, 0x8e, 0xdb, 0xd5, 0x1e, 0xaf, 0x4a, 0x5f, + 0xc0, 0xfa, 0xf0, 0xb5, 0xa3, 0x5b, 0xda, 0x38, 0xb7, 0x38, + 0x5e, 0xce, 0x81, 0x44, 0xf7, 0x66, 0x62, 0x64, 0x1d, 0x04, + 0xf0, 0x8a, 0x4f, 0xa2, 0x80, 0x76, 0x83, 0x23, 0x89, 0x61, + 0x6b, 0xc3, 0xb7, 0xee, 0xb5, 0x06, 0x33, 0xad, 0x63, 0x04, + 0x78, 0xc9, 0xde, 0x32, 0xde, 0xcf, 0x18, 0xb9, 0xb0, 0x3b, + 0xee, 0x0a, 0x58, 0xea, 0xad, 0xbc, 0x1e, 0x77, 0xa0, 0x93, + 0xf7, 0xae, 0x9e, 0xb6, 0x31, 0x59, 0x8e, 0xb1, 0x03, 0x8f, + 0xbb, 0xa4, 0x25, 0x0c, 0x2e, 0xd7, 0xe2, 0x62, 0x5c, 0xf1, + 0x68, 0xe9, 0x76, 0xd7, 0x23, 0x14, 0x45, 0xaf, 0xcb, 0x09, + 0x50, 0x05, 0x3f, 0xa0, 0xf9, 0xc3, 0x9e, 0x89, 0x05, 0xa8, + 0x3b, 0x54, 0x55, 0x32, 0x74, 0x91, 0x46, 0xc1, 0x2c, 0x96, + 0x7e, 0x60, 0xad, 0xfa, 0xbb, 0xcd, 0x09, 0x7b, 0x39, 0x10, + 0x82, 0x8a, 0xc0, 0x5a, 0x0d, 0xab, 0xb3, 0x71, 0x45, 0xad, + 0x39, 0x8e, 0xec, 0x4d, 0x91, 0x8d, 0xda, 0x8d, 0xfa, 0xb0, + 0xad, 0x44, 0x3c, 0xc9, 0x21, 0x56, 0x22, 0xfc, 0xd3, 0xba, + 0xb7, 0x3c, 0xe3, 0x8d, 0xda, 0x59, 0x34, 0x42, 0xdd, 0x04, + 0x5b, 0x8e, 0x2b, 0xc7, 0x94, 0xd5, 0x42, 0xe0, 0x4a, 0x6f, + 0x35, 0x5a, 0x27, 0x82, 0xd8, 0x82, 0x40, 0xee, 0x0f, 0xa6, + 0xef, 0xe4, 0x70, 0xe3, 0x30, 0xb7, 0x2d, 0xd4, 0xbb, 0x27, + 0xb2, 0xbf, 0xad, 0x49, 0x45, 0xbc, 0xeb, 0xbe, 0xb7, 0xd8, + 0xe3, 0xb1, 0xf3, 0xeb, 0x41, 0x20, 0x9b, 0x21, 0x54, 0xc3, + 0xa8, 0xaf, 0x9f, 0x20, 0x5c, 0x15, 0x8e, 0x25, 0xbc, 0xbc, + 0x69, 0x91, 0xfe, 0xda, 0xad, 0xe5, 0x37, 0x7d, 0xb0, 0x51, + 0x14, 0xae, 0x8f, 0x35, 0x15, 0x0a, 0xd4, 0x49, 0xa7, 0xd9, + 0x20, 0x70, 0xa4, 0xf2, 0xf4, 0x24, 0x66, 0x52, 0xd1, 0xa5, + 0x22, 0xea, 0x29, 0xd9, 0xb2, 0x82, 0x8d, 0x36, 0x66, 0x75, + 0x6e, 0xd5, 0x8c, 0x54, 0x08, 0x21, 0xf2, 0xee, 0x78, 0xc7, + 0x1f, 0x9c, 0x63, 0x5d, 0x88, 0x56, 0xd1, 0xa0, 0x80, 0x33, + 0x60, 0x55, 0x23, 0x72, 0xd6, 0xb0, 0x1a, 0x50, 0xde, 0x25, + 0x70, 0xb5, 0x77, 0x42, 0xf8, 0x19, 0x18, 0x15, 0x8f, 0xfd, + 0x0c, 0x6a, 0x46, 0x1f, 0xbf, 0xe7, 0x60, 0x91, 0xe7, 0xbb, + 0x25, 0x63, 0x66, 0xff, 0x11, 0x97, 0xbb, 0xfd, 0x3a, 0x17, + 0x94, 0x77, 0xb4, 0xc5, 0x21, 0xba, 0x30, 0x94, 0xdd, 0xe5, + 0xeb, 0x1d, 0x01, 0xba, 0xf9, 0xb0, 0x30, 0xdb, 0x11, 0x93, + 0xb7, 0xfa, 0x79, 0xe8, 0x5e, 0xb3, 0x39, 0xf4, 0x51, 0x68, + 0x31, 0xce, 0xe9, 0x0e, 0x93, 0xde, 0xff, 0xec, 0x27, 0xbd, + 0xa6, 0x1a, 0x4c, 0xe0, 0x92, 0x5c, 0xd4, 0x07, 0xd2, 0xa1, + 0xdd, 0x12, 0x83, 0xd2, 0x9a, 0x79, 0xb3, 0x3c, 0xfb, 0x07, + 0xe3, 0x18, 0x1a, 0xa3, 0x24, 0x80, 0xb4, 0xcc, 0xf4, 0xc6, + 0xa5, 0x6c, 0x25, 0xd7, 0x99, 0x1a, 0x30, 0xf0, 0xa9, 0xfc, + 0x2e, 0x83, 0x44, 0xac, 0x64, 0x76, 0x34, 0xb0, 0xa6, 0x6f, + 0x20, 0x5a, 0x14, 0xf2, 0x07, 0xa7, 0x6f, 0x4d, 0xab, 0xf5, + 0xfc, 0x9d, 0xd6, 0x3e, 0x82, 0x48, 0x31, 0x25, 0x47, 0xc9, + 0x0e, 0x1d, 0xdb, 0x98, 0x91, 0x56, 0xf5, 0xfe, 0x66, 0x8d, + 0x48, 0xf0, 0x4c, 0x6c, 0x2c, 0x96, 0x54, 0x43, 0xec, 0x76, + 0xf2, 0xe1, 0x76, 0x68, 0xc8, 0xe1, 0xde, 0x0d, 0x8e, 0x6f, + 0xfc, 0x15, 0xd5, 0x93, 0x92, 0xfe, 0xca, 0x9b, 0x30, 0x61, + 0x03, 0x0b, 0xca, 0x99, 0x2f, 0xd3, 0x15, 0xe9, 0x66, 0x81, + 0xbd, 0x56, 0x17, 0x14, 0x4a, 0x2e, 0xf1, 0x34, 0x84, 0x55, + 0x9d, 0xc0, 0x2b, 0xa7, 0x4a, 0xee, 0xf1, 0x7c, 0x67, 0xc7, + 0xf3, 0x08, 0x1e, 0x6d, 0x6b, 0x5b, 0xcc, 0x81, 0x91, 0x5c, + 0x94, 0x1a, 0x80, 0xda, 0x3a, 0xce, 0x36, 0x05, 0xb0, 0x7a, + 0xe8, 0xd0, 0xb4, 0x57, 0x9c, 0xf9, 0xea, 0xf3, 0x26, 0x1d, + 0xcb, 0xf8, 0xdd, 0x65, 0xaf, 0xf7, 0xcd, 0xf7, 0xa1, 0x3d, + 0xfc, 0x9a, 0x3b, 0x08, 0xb9, 0xfa, 0x3c, 0x16, 0x49, 0x4a, + 0xf1, 0xba, 0x4d, 0x31, 0xdd, 0x5e, 0x4f, 0x3d, 0x66, 0x22, + 0x1b, 0x08, 0x91, 0x7d, 0xc6, 0xaf, 0x15, 0x07, 0x3c, 0xa1, + 0xf7, 0x07, 0xfd, 0x3e, 0x90, 0xbb, 0x6f, 0x7a, 0xe9, 0xe1, + 0x2f, 0xb9, 0xee, 0x91, 0x8e, 0x18, 0xcc, 0x8d, 0x1d, 0x22, + 0xa0, 0xa0, 0x28, 0x25, 0xfc, 0xd4, 0x94, 0xd3, 0xaa, 0xcf, + 0xce, 0xd0, 0x85, 0x82, 0x6f, 0x20, 0x9f, 0x55, 0x0e, 0xe5, + 0x72, 0x0d, 0x17, 0x3e, 0x34, 0xc7, 0x2c, 0x0a, 0x14, 0x45, + 0x27, 0xe2, 0xc7, 0x2f, 0x86, 0xa1, 0x55, 0x3e, 0x78, 0x03, + 0xe9, 0x78, 0x2e, 0xd3, 0x99, 0xee, 0xa0, 0x14, 0xf8, 0xe3, + 0x6c, 0xeb, 0x3f, 0x9a, 0xf3, 0x15, 0xce, 0xd5, 0x76, 0xf6, + 0x3a, 0x86, 0x30, 0x76, 0xf9, 0x88, 0x30, 0xf5, 0x4a, 0x50, + 0x58, 0x80, 0xe9, 0xd9, 0xd4, 0xb9, 0x34, 0x42, 0xa6, 0x4e, + 0x9c, 0x1a, 0x07, 0x16, 0x9e, 0xee, 0xe4, 0x88, 0x04, 0x8e, + 0xa8, 0xe7, 0xcd, 0xe8, 0x47, 0x1e, 0x54, 0x45, 0xd2, 0x65, + 0xd8, 0xee, 0x4b, 0xbd, 0xd0, 0x85, 0xaa, 0xfb, 0x06, 0x53, + 0x91, 0x7e, 0xe0, 0x59, 0x20, 0x57, 0x6a, 0xee, 0xd8, 0x9f, + 0x77, 0x7f, 0xd7, 0x40, 0x63, 0xbb, 0x21, 0x75, 0x76, 0x11, + 0x27, 0xcf, 0x05, 0xbb, 0x41, 0x30, 0x98, 0xbf, 0xdc, 0x5f, + 0xc6, 0xa4, 0x1e, 0x30, 0xa1, 0x53, 0xd4, 0x36, 0x7f, 0x2e, + 0x86, 0xd7, 0xd9, 0x95, 0x29, 0xd5, 0x46, 0x18, 0x60, 0x27, + 0xe4, 0x6f, 0xcb, 0xf4, 0xe2, 0xfe, 0xff, 0x3e, 0xff, 0x15, + 0xc6, 0xf2, 0x31, 0xf9, 0x2a, 0xc8, 0x05, 0x4e, 0x7c, 0x2e, + 0x92, 0xc8, 0x41, 0x4f, 0x9e, 0x23, 0x21, 0x4d, 0x74, 0xf8, + 0xc3, 0x44, 0x39, 0xc2, 0x69, 0x4b, 0x2e, 0x76, 0x5e, 0x44, + 0x12, 0x65, 0x31, 0x98, 0xbe, 0x0a, 0x10, 0x11, 0x12, 0x2c, + 0x67, 0x3d, 0x85, 0x2e, 0xd3, 0x97, 0x54, 0x1e, 0xb6, 0xad, + 0xd9, 0x45, 0x11, 0x53, 0x04, 0x7c, 0x3f, 0xf4, 0xc9, 0xac, + 0x82, 0x1b, 0x84, 0xf4, 0x20, 0x6b, 0xf1, 0xf5, 0x72, 0x04, + 0x24, 0xc1, 0xd3, 0x42, 0x43, 0x52, 0x9d, 0x2d, 0xd3, 0x89, + 0x8e, 0xd8, 0x28, 0xb9, 0xa2, 0xb4, 0xed, 0xbc, 0x76, 0x87, + 0x55, 0x67, 0x39, 0xd9, 0xb7, 0x20, 0x6a, 0xec, 0xec, 0xb8, + 0x14, 0x51, 0x91, 0xb9, 0x96, 0x0f, 0x7a, 0x3a, 0x12, 0xde, + 0x14, 0x3b, 0x83, 0xcf, 0x41, 0x5b, 0x5d, 0xff, 0x33, 0x68, + 0xdb, 0x53, 0x64, 0x93, 0xb1, 0xc3, 0x8a, 0x46, 0xa8, 0x44, + 0x9c, 0x14, 0x12, 0x6c, 0x92, 0x6f, 0xae, 0xc3, 0x45, 0xb2, + 0xa1, 0x67, 0x81, 0x3c, 0x22, 0x47, 0xfd, 0xa4, 0x7a, 0x79, + 0xa8, 0x0a, 0xfb, 0x7a, 0x91, 0x6e, 0xe9, 0x53, 0xec, 0x98, + 0x82, 0x57, 0xad, 0x05, 0x38, 0x55, 0xc1, 0xce, 0x3a, 0x04, + 0x4d, 0x12, 0x72, 0x37, 0x4a, 0x36, 0x54, 0x3f, 0x67, 0x8a, + 0xee, 0xd9, 0xf3, 0x80, 0xd5, 0xd7, 0xb8, 0xfc, 0x6e, 0x4f, + 0x60, 0x2b, 0x5a, 0xa4, 0xc5, 0x05, 0xdb, 0xe5, 0x09, 0xe3, + 0xeb, 0xa2, 0x51, 0x33, 0x30, 0x96, 0x46, 0x01, 0x26, 0x8f, + 0x38, 0xc9, 0x97, 0x32, 0x2d, 0xb4, 0x59, 0x15, 0x15, 0x38, + 0x66, 0x66, 0xfe, 0xcb, 0xee, 0xc1, 0xf6, 0x4e, 0xb7, 0xdf, + 0x7b, 0x63, 0xe6, 0x3f, 0xe0, 0x1c, 0x97, 0xed, 0x86, 0xf3, + 0xd2, 0xad, 0x42, 0x29, 0x20, 0x28, 0xa6, 0x59, 0x58, 0x7d, + 0x8f, 0x5c, 0x43, 0x07, 0xd1, 0x7e, 0x83, 0xba, 0x9c, 0x1b, + 0xfe, 0x17, 0x9e, 0xc8, 0x09, 0x63, 0x9a, 0x2d, 0x61, 0x33, + 0x51, 0x46, 0x01, 0xa8, 0xe9, 0x43, 0x1e, 0x4e, 0xfe, 0x61, + 0x1a, 0x28, 0x11, 0x65, 0x70, 0x43, 0x9f, 0xfc, 0x21, 0x1d, + 0x76, 0x7b, 0x40, 0x08, 0x18, 0xd3, 0xe8, 0xc2, 0xe3, 0x8c, + 0xe7, 0x27, 0xc2, 0xec, 0xb0, 0x08, 0x3e, 0x6b, 0x8f, 0x77, + 0x6d, 0x9e, 0xa6, 0xab, 0xce, 0x9a, 0xf8, 0x8f, 0x77, 0xb3, + 0xf4, 0xe8, 0x8b, 0xe7, 0xd9, 0xa1, 0x95, 0x40, 0x6b, 0xca, + 0x21, 0x98, 0xff, 0xdc, 0xdc, 0x96, 0xc3, 0x08, 0x81, 0x72, + 0x9a, 0xdd, 0xe2, 0xcf, 0x95, 0x99, 0xa6, 0xa3, 0x5e, 0x9e, + 0x25, 0x60, 0xa3, 0xc3, 0x39, 0xf7, 0x54, 0x6c, 0xf2, 0x75, + 0xa9, 0x38, 0x12, 0x38, 0x4d, 0x42, 0xe8, 0xec, 0x13, 0x25, + 0xa0, 0xf8, 0x04, 0xb8, 0xf6, 0x66, 0x0b, 0x56, 0xe1, 0xfb, + 0x26, 0x03, 0xe6, 0xa5, 0xf1, 0x4d, 0x7f, 0xa5, 0x9d, 0x58, + 0x71, 0xd8, 0xc7, 0x6a, 0xbe, 0xdc, 0x90, 0x89, 0xb1, 0x36, + 0xb4, 0xb6, 0xb4, 0xbb, 0xaf, 0x6e, 0x43, 0x10, 0xa6, 0xea, + 0xee, 0x12, 0xcb, 0x08, 0x2c, 0x4e, 0x66, 0xf0, 0x1f, 0xf4, + 0xbf, 0xd3, 0xeb, 0x63, 0x48, 0xd0, 0xbe, 0x8a, 0xed, 0x24, + 0xdb, 0x0f, 0x23, 0x1d, 0x2e, 0x30, 0x97, 0x0f, 0xd8, 0xc6, + 0x3b, 0x04, 0x2f, 0x33, 0x78, 0x20, 0x6e, 0xb1, 0x33, 0x03, + 0x27, 0xac, 0x0a, 0x37, 0x15, 0x31, 0xef, 0x4d, 0x43, 0xcc, + 0xa0, 0x49, 0x80, 0xe3, 0x8c, 0xc0, 0xf3, 0xf7, 0x2d, 0x37, + 0x1d, 0xd3, 0x90, 0x5f, 0xad, 0x31, 0xb5, 0x95, 0x17, 0x69, + 0x4b, 0xec, 0x84, 0x9d, 0x2b, 0x8d, 0xdd, 0x9b, 0x58, 0x04, + 0xba, 0x28, 0x0e, 0x28, 0xc1, 0x54, 0x6c, 0xb0, 0x25, 0x0c, + 0x4f, 0x98, 0x47, 0xf7, 0x93, 0xc2, 0xae, 0x2f, 0x6d, 0x29, + 0x9c, 0x3d, 0xe3, 0xb5, 0xe3, 0x28, 0x43, 0x14, 0xe6, 0x92, + 0x4c, 0x79, 0x90, 0x59, 0x75, 0x77, 0x56, 0x43, 0xda, 0xac, + 0xa9, 0x42, 0xd7, 0xca, 0x95, 0x73, 0x26, 0x54, 0x1f, 0x3a, + 0x8a, 0x37, 0x64, 0xd7, 0xcf, 0xe1, 0x31, 0xf7, 0x40, 0x59, + 0xfd, 0xff, 0xea, 0x72, 0xfd, 0xc4, 0xde, 0xe3, 0x4d, 0x8a, + 0xf5, 0x80, 0xc0, 0x61, 0x21, 0xbd, 0xbd, 0x8e, 0x42, 0xd5, + 0x4c, 0xe4, 0xf4, 0x78, 0x31, 0xca, 0xf1, 0xec, 0x7c, 0x7b, + 0x85, 0x6a, 0x05, 0x54, 0xbe, 0x38, 0x54, 0x2f, 0x1f, 0xda, + 0x9f, 0x98, 0xe2, 0x79, 0xd7, 0x42, 0xca, 0xba, 0x85, 0x21, + 0xe2, 0xcb, 0x2b, 0xae, 0x4a, 0x4e, 0x35, 0xfb, 0xcf, 0x3d, + 0xc5, 0xae, 0x27, 0x30, 0xa9, 0x45, 0xe6, 0x3b, 0x43, 0x3e, + 0x35, 0xe3, 0xf2, 0x0d, 0x53, 0x32, 0x2b, 0xf6, 0xe6, 0xc7, + 0xd5, 0x02, 0x82, 0x03, 0xc1, 0x00, 0xd4, 0x04, 0x9b, 0xef, + 0x5d, 0x58, 0xb0, 0xa3, 0xaa, 0xd2, 0xab, 0x53, 0x65, 0x99, + 0x03, 0x49, 0x48, 0x4d, 0xf5, 0xdf, 0x5d, 0x16, 0x14, 0x11, + 0x60, 0x45, 0x1b, 0xff, 0x4a, 0x60, 0x2b, 0x37, 0x63, 0xf6, + 0xa7, 0x8a, 0xa8, 0xff, 0x08, 0x97, 0x08, 0xfc, 0xbb, 0xb3, + 0x20, 0xa3, 0xcd, 0xd9, 0x58, 0xdb, 0x16, 0x1b, 0x88, 0x02, + 0x1e, 0x0f, 0x43, 0x9b, 0x16, 0x7e, 0xbe, 0xb1, 0x9c, 0x13, + 0x10, 0xdc, 0xa1, 0x56, 0xff, 0xa3, 0xff, 0x5e, 0x69, 0x30, + 0xee, 0x7e, 0x76, 0x5f, 0x84, 0x94, 0xeb, 0x8f, 0x58, 0xf8, + 0xcf, 0xbb, 0x99, 0x6e, 0xf0, 0xd8, 0x32, 0xf6, 0xce, 0x48, + 0x6f, 0x7c, 0xc8, 0x8f, 0xd3, 0x86, 0x22, 0x49, 0x9f, 0xde, + 0x11, 0x05, 0xa4, 0xdc, 0x92, 0xfb, 0x0f, 0xfa, 0x09, 0x4d, + 0x17, 0x1a, 0xe2, 0x76, 0x67, 0x40, 0xa9, 0x5b, 0x1b, 0x54, + 0x66, 0x48, 0xf7, 0xc3, 0x59, 0xd4, 0xcf, 0x55, 0xd0, 0x7f, + 0x3b, 0xb0, 0xa2, 0xd8, 0xec, 0xb7, 0x88, 0xe7, 0xb0, 0x30, + 0x72, 0x42, 0x65, 0xe2, 0x91, 0xa7, 0x9b, 0xf6, 0x07, 0x45, + 0x52, 0x51, 0xaa, 0xbe, 0x32, 0x35, 0xe4, 0x88, 0x23, 0xe7, + 0xcb, 0x3c, 0x1c, 0xfb, 0x0b, 0x96, 0xd5, 0xb3, 0x92, 0x86, + 0x79, 0x5b, 0x47, 0x93, 0xd6, 0xbd, 0xc7, 0x21, 0x17, 0xd0, + 0xc9, 0xc7, 0x69, 0x84, 0x80, 0x98, 0xaf, 0x2c, 0x63, 0xd1, + 0xef, 0x6e, 0xca, 0x84, 0x30, 0x32, 0x83, 0x2d, 0x49, 0xbb, + 0x1f, 0x2a, 0xfe, 0x40, 0x7c, 0x03, 0xd4, 0x45, 0xdc, 0xfe, + 0x94, 0xf9, 0xe4, 0x36, 0x47, 0xfa, 0x7e, 0x2e, 0x93, 0x03, + 0xf8, 0x15, 0xf9, 0xce, 0xc3, 0x5b, 0x76, 0x10, 0xec, 0x89, + 0x8c, 0xce, 0x25, 0xa5, 0x77, 0x9a, 0xc5, 0x1e, 0xdd, 0x07, + 0x1b, 0x5b, 0xac, 0x6f, 0xdb, 0x94, 0x85, 0xdf, 0x02, 0x22, + 0xd1, 0xa9, 0x01, 0x8e, 0x63, 0xa1, 0xee, 0x94, 0x9c, 0xdb, + 0xb4, 0x1a, 0x43, 0xe1, 0x1f, 0x4e, 0x2f, 0x68, 0x50, 0x0c, + 0x2f, 0x5b, 0xc5, 0x1b, 0xe1, 0x8d, 0x4b, 0xe0, 0x63, 0x8d, + 0x7a, 0x30, 0xbe, 0xb7, 0x2e, 0x02, 0xc6, 0x02, 0xac, 0xa8, + 0xb8, 0x65, 0xc6, 0x28, 0xee, 0xe4, 0xec, 0x99, 0xa1, 0x9a, + 0xfd, 0x1f, 0xb5, 0x85, 0x7a, 0x94, 0x16, 0xe2, 0xe7, 0x74, + 0x06, 0x54, 0x1b, 0xd0, 0xaf, 0x58, 0x4e, 0x50, 0x7e, 0xd6, + 0xe4, 0x31, 0xd2, 0x0c, 0xd7, 0x9d, 0xe2, 0x00, 0x30, 0xbe, + 0x26, 0x30, 0x48, 0x99, 0x98, 0x58, 0x54, 0x5a, 0xc4, 0x0a, + 0x6c, 0xa1, 0x06, 0xe9, 0x38, 0xe6, 0x79, 0x39, 0x00, 0x9e, + 0xb6, 0xe3, 0xf7, 0x01, 0xcf, 0x2f, 0x82, 0x5e, 0xc3, 0x21, + 0x1b, 0x79, 0x93, 0xb5, 0xe4, 0x39, 0x9d, 0x32, 0x9d, 0x72, + 0xa4, 0xa8, 0xc9, 0x90, 0xce, 0xaf, 0xc0, 0x00, 0xad, 0x20, + 0x87, 0x26, 0xc7, 0xd3, 0x5f, 0x2e, 0xf0, 0x5e, 0xf8, 0x8b, + 0x85, 0xa3, 0xc6, 0x66, 0xd8, 0x2f, 0x86, 0xfe, 0x7d, 0x8d, + 0x22, 0xa5, 0x6d, 0x68, 0x3e, 0x87, 0x6e, 0xf7, 0xf1, 0xf0, + 0x07, 0xc4, 0xe3, 0xf1, 0x84, 0xc4, 0x93, 0x42, 0x06, 0x20, + 0x80, 0x64, 0xb3, 0x52, 0x5c, 0xa5, 0xcf, 0xee, 0xfe, 0xa4, + 0x09, 0x41, 0xbe, 0xaa, 0x78, 0x52, 0x76, 0x3f, 0xf7, 0xe8, + 0xa1, 0x6b, 0x0a, 0xbc, 0x22, 0xbe, 0xdf, 0x72, 0x7b, 0xea, + 0x90, 0x43, 0xee, 0xc2, 0x0b, 0x26, 0xdc, 0x02, 0x26, 0xa7, + 0x50, 0x04, 0x7a, 0x06, 0x91, 0xae, 0x93, 0xd5, 0xd2, 0xc9, + 0xa1, 0xe1, 0xfc, 0xb9, 0x8c, 0x94, 0xca, 0xa8, 0x1c, 0x2c, + 0x57, 0x97, 0x3e, 0x50, 0xed, 0x93, 0x45, 0x7a, 0x2c, 0x59, + 0x7b, 0x34, 0x8f, 0xcd, 0xd6, 0x17, 0x93, 0xd8, 0xde, 0xe8, + 0xb0, 0x9e, 0x27, 0x15, 0xc5, 0xbb, 0xa5, 0xbb, 0xc2, 0x30, + 0x9b, 0xc7, 0x27, 0x02, 0x18, 0xd8, 0xdb, 0xa4, 0x84, 0x37, + 0x64, 0xf7, 0xf7, 0xf1, 0xc8, 0x86, 0x4c, 0x64, 0x97, 0x08, + 0xe9, 0x4e, 0x0e, 0xb6, 0x92, 0xe9, 0x4c, 0x7b, 0x7f, 0xe1, + 0xcc, 0xa0, 0x71, 0xa7, 0x34, 0x48, 0x46, 0xbb, 0x37, 0xce, + 0xb0, 0x4d, 0x39, 0xa8, 0x0e, 0xab, 0xf6, 0x2f, 0x7c, 0x88, + 0xae, 0xcf, 0x90, 0xc6, 0x01, 0xd3, 0x5b, 0x37, 0xe9, 0xb1, + 0x28, 0x42, 0x14, 0xbf, 0x59, 0x35, 0x04, 0xab, 0x46, 0x6e, + 0xa8, 0x29, 0xe2, 0x7a, 0x77, 0x0e, 0x07, 0x67, 0xe4, 0x2b, + 0x03, 0xd2, 0x02, 0x36, 0x16, 0xd7, 0x81, 0x5d, 0x38, 0x9c, + 0x68, 0x9c, 0xf5, 0x9e, 0x49, 0x7d, 0x99, 0xfd, 0xcd, 0x1d, + 0xd2, 0xdf, 0x3c, 0x36, 0x19, 0x85, 0xaa, 0xb1, 0x30, 0x7a, + 0x21, 0xb1, 0x83, 0x16, 0xcf, 0xd1, 0x75, 0xa5, 0x9d, 0xd7, + 0xc1, 0x60, 0xa8, 0xdb, 0x1e, 0xb9, 0x3e, 0x9c, 0x12, 0x42, + 0xe8, 0x47, 0x49, 0x18, 0x9f, 0x5c, 0x12, 0xd1, 0x69, 0xd5, + 0x7d, 0xa8, 0x3c, 0xda, 0x35, 0x8a, 0x6c, 0x63, 0xb8, 0x62, + 0x8a, 0x61, 0xfa, 0xf2, 0x61, 0x11, 0x1e, 0xb6, 0xf3, 0x5c, + 0x62, 0x9d, 0xa7, 0x62, 0x0c, 0x87, 0x93, 0xe2, 0x23, 0x6c, + 0x3d, 0xa9, 0x2c, 0x4b, 0xd5, 0x7f, 0xfe, 0x72, 0x27, 0x36, + 0x06, 0xcb, 0x65, 0x38, 0xef, 0x13, 0x57, 0x6a, 0xc9, 0xc6, + 0x4f, 0x51, 0xd0, 0x90, 0x06, 0xa0, 0x23, 0x65, 0x95, 0xce, + 0x16, 0x8f, 0x8d, 0xb2, 0xf9, 0x7f, 0x3c, 0x2c, 0x30, 0x5a, + 0x38, 0xf1, 0x62, 0x79, 0x4b, 0xe5, 0xd7, 0x0a, 0x3f, 0x83, + 0x5f, 0x46, 0x26, 0x97, 0xb7, 0x08, 0x8c, 0x5b, 0xb8, 0x02, + 0x28, 0xf2, 0x4d, 0xdf, 0x93, 0x97, 0xc5, 0x94, 0x4b, 0x0e, + 0x42, 0xc3, 0x35, 0x91, 0x6b, 0x69, 0x61, 0x76, 0x7f, 0x94, + 0xcf, 0x0b, 0x81, 0x33, 0xff, 0xf3, 0x0c, 0xc7, 0x01, 0x94, + 0x94, 0xa9, 0xed, 0xcd, 0x4b, 0xc8, 0xcb, 0x91, 0xf9, 0x7a, + 0x47, 0xcd, 0x79, 0x3c, 0xa6, 0xde, 0x52, 0xd2, 0x47, 0x5c, + 0x10, 0x62, 0xbb, 0xe5, 0x32, 0xde, 0x83, 0xcf, 0xa8, 0x52, + 0xb3, 0xe7, 0xf9, 0xec, 0x17, 0x34, 0xbf, 0x33, 0x5d, 0xb2, + 0x4e, 0x56, 0xf7, 0x29, 0xd9, 0x5c, 0x1b, 0x83, 0x01, 0xbb, + 0xb9, 0x2b, 0x95, 0x52, 0x08, 0xab, 0xa4, 0x51, 0x03, 0xa1, + 0xfb, 0x6a, 0x50, 0xcd, 0xa8, 0x9d, 0x95, 0x6f, 0x7e, 0xb1, + 0x80, 0x1e, 0x9d, 0x81, 0x01, 0x26, 0x41, 0x78, 0x36, 0x3c, + 0x8a, 0x44, 0xf4, 0x98, 0x88, 0x1c, 0x5d, 0x06, 0xd3, 0xd2, + 0xb2, 0x58, 0x7d, 0xa1, 0x45, 0x1b, 0xbf, 0x8c, 0xf6, 0x6a, + 0xfa, 0xfd, 0x08, 0x29, 0x3e, 0x91, 0x57, 0xf1, 0x3d, 0x20, + 0xed, 0x49, 0x6e, 0x9c, 0x46, 0xd5, 0x08, 0x8d, 0x9b, 0xf8, + 0xef, 0xa3, 0x3a, 0x98, 0xcb, 0xb4, 0xcb, 0x5b, 0x30, 0x25, + 0x20, 0xcc, 0x04, 0xa1, 0xeb, 0xeb, 0xee, 0x1b, 0x36, 0x85, + 0xc1, 0x93, 0x16, 0x5a, 0x31, 0xdf, 0xd6, 0x0e, 0x73, 0x9e, + 0x63, 0x6e, 0x96, 0x90, 0x54, 0xd2, 0xc2, 0x53, 0x69, 0x93, + 0xd5, 0x54, 0xca, 0xd8, 0x84, 0xf7, 0x8f, 0x9a, 0xd1, 0x80, + 0x0d, 0x57, 0xa8, 0x26, 0xbe, 0x45, 0x64, 0xd5, 0x2b, 0xbb, + 0x45, 0xb5, 0x08, 0xb9, 0x37, 0x57, 0x02, 0x82, 0x03, 0xc1, + 0x00, 0xd1, 0x30, 0x2e, 0xb7, 0x9b, 0xe7, 0x5d, 0x13, 0x74, + 0x1f, 0x52, 0xf2, 0x02, 0x18, 0xe9, 0x07, 0x87, 0x9e, 0xed, + 0xde, 0x83, 0x92, 0xcf, 0x73, 0x61, 0x21, 0xc4, 0x62, 0x30, + 0x6c, 0xa2, 0x36, 0xbd, 0xe2, 0xc5, 0x19, 0xf6, 0xdf, 0x51, + 0x7b, 0xca, 0xd4, 0xe4, 0x51, 0x83, 0x49, 0x27, 0xdd, 0xbd, + 0xb0, 0x10, 0x79, 0x39, 0xdd, 0x0e, 0x3d, 0x65, 0xad, 0x6d, + 0xa3, 0x95, 0x52, 0x85, 0xdb, 0x18, 0x94, 0x60, 0xaa, 0xc0, + 0xc8, 0x8b, 0xdb, 0xfe, 0xf9, 0xf0, 0x86, 0xf9, 0x33, 0x8a, + 0xd7, 0xbe, 0x8d, 0x43, 0x83, 0x4d, 0xe4, 0x17, 0x2b, 0x46, + 0x54, 0x44, 0x1b, 0xbe, 0x52, 0x64, 0x47, 0x02, 0x6c, 0x4a, + 0x64, 0xb4, 0x3f, 0x21, 0x2f, 0xbb, 0xe3, 0x72, 0x7c, 0x26, + 0x14, 0xdf, 0x80, 0x50, 0xd4, 0x94, 0xe9, 0xc6, 0x7d, 0x71, + 0xd8, 0xaf, 0xfb, 0x74, 0x36, 0x33, 0xbe, 0x58, 0x63, 0xad, + 0xcb, 0xdf, 0xc0, 0x73, 0x9e, 0x19, 0xb0, 0x65, 0xe1, 0xd1, + 0x10, 0x44, 0xf1, 0xf0, 0x08, 0xa3, 0x09, 0x25, 0xeb, 0xd5, + 0xcb, 0xdd, 0x98, 0xdd, 0xbc, 0x09, 0x2c, 0xef, 0xc1, 0x8d, + 0x43, 0x15, 0x41, 0xc2, 0xa1, 0x84, 0x37, 0x70, 0x5a, 0xd5, + 0xf5, 0xb2, 0x6a, 0x1f, 0xbb, 0xcc, 0x30, 0xb9, 0xd9, 0xc7, + 0x36, 0x21, 0xf3, 0x69, 0x3e, 0x91, 0x38, 0x4d, 0xa5, 0xc4, + 0xf7, 0x84, 0x90, 0x34, 0x0e, 0x47, 0x7e, 0x26, 0xf2, 0x98, + 0x25, 0x26, 0xda, 0xf0, 0x4e, 0x55, 0xea, 0x4d, 0x9b, 0x8a, + 0x4a, 0xe1, 0x1f, 0xa0, 0x07, 0x90, 0x9e, 0x59, 0x64, 0xae, + 0xd9, 0xd6, 0x7e, 0x72, 0xa1, 0xc4, 0xea, 0x7d, 0xbd, 0x1f, + 0x7d, 0x2b, 0xd9, 0x2c, 0xdc, 0x8b, 0xc0, 0xda, 0x52, 0x0c, + 0xd1, 0xd0, 0x56, 0xb7, 0x93, 0xc7, 0x26, 0x79, 0x71, 0xd0, + 0x0d, 0xae, 0xaa, 0xa7, 0xe4, 0xc1, 0x59, 0x27, 0x68, 0x97, + 0x9a, 0xff, 0x3d, 0x36, 0x07, 0x55, 0x77, 0x07, 0x97, 0x69, + 0xf3, 0x99, 0x91, 0x3f, 0x63, 0xfd, 0x70, 0x8c, 0xa1, 0xeb, + 0xc5, 0x21, 0xa3, 0xfe, 0x99, 0x96, 0x11, 0x37, 0xb9, 0xe6, + 0x93, 0xf8, 0xd0, 0xb1, 0xa3, 0x57, 0x7a, 0xa8, 0x63, 0xdd, + 0x09, 0x56, 0xb0, 0x3b, 0xa6, 0x59, 0xc7, 0x89, 0x54, 0x16, + 0xe9, 0x2d, 0x78, 0x7d, 0xaf, 0x4e, 0x0a, 0x5b, 0x62, 0x3b, + 0x0b, 0xcb, 0x24, 0x89, 0x4e, 0x1c, 0x3d, 0xe1, 0xbd, 0x5a, + 0x3e, 0xc5, 0xfd, 0x15, 0x3d, 0x08, 0x38, 0x33, 0x5e, 0x37, + 0x4c, 0xe3, 0xe3, 0xe9, 0xc4, 0x1d, 0x2b, 0xd4, 0x58, 0x25, + 0x58, 0x23, 0x8e, 0xc6, 0x83, 0x9a, 0xf3, 0x9a, 0x78, 0xe9, + 0xa7, 0xca, 0xd7, 0xdd, 0x89, 0x20, 0x6e, 0x02, 0xea, 0x6b, + 0x37, 0x74, 0xda, 0xa0, 0xc2, 0x5a, 0x2b, 0x80, 0x1c, 0x28, + 0x91, 0x0d, 0x50, 0x64, 0xf0, 0x12, 0xe7, 0xc4, 0x7e, 0xdd, + 0x28, 0x3b, 0x26, 0x9a, 0xf4, 0x39, 0x56, 0xa4, 0x72, 0x4d, + 0xcb, 0x67, 0x3c, 0x68, 0xb2, 0x6f, 0xf0, 0xd0, 0x15, 0x90, + 0xc8, 0x08, 0xbb, 0x0b, 0x08, 0x6b, 0x8a, 0xde, 0x41, 0x57, + 0xbc, 0x63, 0x0e, 0x00, 0x8d, 0xf8, 0xdd, 0x93, 0xce, 0x58, + 0x7b, 0xa8, 0xb9, 0x64, 0x26, 0x06, 0xe7, 0x71, 0x23, 0x0f, + 0x41, 0xf1, 0xb7, 0xae, 0x59, 0x2e, 0xd0, 0x73, 0xc5, 0xd9, + 0xdc, 0x0e, 0x1c, 0x02, 0x58, 0x69, 0xb3, 0x15, 0x6d, 0x96, + 0x2b, 0xdb, 0x7b, 0x3b, 0x6c, 0x38, 0x32, 0x6b, 0xd8, 0x08, + 0xb2, 0xbd, 0xa7, 0x49, 0x43, 0xeb, 0x90, 0x42, 0x70, 0xc5, + 0xba, 0xcd, 0x4a, 0x44, 0x8f, 0x83, 0x0d, 0x17, 0x51, 0x5a, + 0x95, 0xa2, 0x57, 0x9a, 0x16, 0x19, 0x91, 0xbb, 0x90, 0x5c, + 0x2a, 0x16, 0xe8, 0x26, 0x10, 0x3c, 0xb7, 0x10, 0x5c, 0xf8, + 0xc5, 0x15, 0x2b, 0x70, 0x75, 0x69, 0xba, 0x7b, 0x3d, 0x0b, + 0x57, 0xac, 0x39, 0x12, 0x2e, 0xd6, 0xd9, 0x13, 0x74, 0x8e, + 0xa8, 0x0b, 0x17, 0xe1, 0x03, 0x7a, 0xba, 0x1d, 0x07, 0x91, + 0x8c, 0x2a, 0x3a, 0x8d, 0xe0, 0x2a, 0x94, 0xd4, 0x16, 0x35, + 0x64, 0x8b, 0x92, 0x2c, 0x2f, 0xa4, 0x18, 0xfe, 0x3f, 0x02, + 0x19, 0x8c, 0xb9, 0xeb, 0xaf, 0x01, 0x06, 0xa8, 0x37, 0x7f, + 0xe2, 0x44, 0x10, 0xce, 0xeb, 0x8d, 0xd0, 0x73, 0xc4, 0x1e, + 0x3d, 0x2c, 0xaf, 0x77, 0xb2, 0xef, 0xe5, 0x95, 0x8b, 0xdf, + 0x02, 0xfc, 0x93, 0xb8, 0xa9, 0x27, 0x88, 0x1d, 0x1d, 0x82, + 0x9f, 0xb6, 0xe4, 0x12, 0x05, 0x79, 0xb6, 0x1c, 0x41, 0x0d, + 0xc1, 0x53, 0x49, 0x8f, 0x3d, 0xc9, 0xad, 0x84, 0xcb, 0x0b, + 0x88, 0x7e, 0xfe, 0x73, 0x59, 0x21, 0x64, 0xc5, 0x50, 0x53, + 0xdc, 0x98, 0xc6, 0x43, 0xb8, 0xf5, 0xc3, 0xa1, 0xf5, 0xb2, + 0xd8, 0x86, 0xe9, 0xae, 0x98, 0xf9, 0x3b, 0x99, 0xc0, 0xe7, + 0xd7, 0x4a, 0xed, 0xac, 0x89, 0x84, 0xb0, 0x8e, 0xd3, 0xab, + 0xec, 0x03, 0x02, 0x12, 0x4b, 0x44, 0x17, 0x4d, 0x98, 0x26, + 0x1e, 0x51, 0xc5, 0xbb, 0xcd, 0xdc, 0x50, 0xab, 0x83, 0x37, + 0x49, 0x90, 0x1e, 0x34, 0xad, 0x81, 0x22, 0x6c, 0xe4, 0xdd, + 0x19, 0x01, 0x09, 0x25, 0x2d, 0x9e, 0x52, 0x90, 0x72, 0xa1, + 0x68, 0x3d, 0x0c, 0x49, 0x99, 0x19, 0x75, 0x5a, 0xca, 0x08, + 0x69, 0xa1, 0xd2, 0x88, 0x8c, 0xea, 0xcf, 0x9c, 0xbc, 0x23, + 0xad, 0x3f, 0xb9, 0xfc, 0xb9, 0x30, 0x0d, 0xd6, 0xd9, 0x65, + 0x0c, 0x7e, 0x99, 0x68, 0x35, 0x26, 0x07, 0xd1, 0x55, 0xbf, + 0x8e, 0xde, 0xe7, 0xe7, 0x01, 0xcb, 0xca, 0x0a, 0x39, 0x2e, + 0xcc, 0x19, 0xec, 0x77, 0xf3, 0xab, 0xb2, 0xe6, 0x0e, 0x54, + 0x06, 0x01, 0x50, 0x77, 0xd3, 0x61, 0x36, 0x05, 0x90, 0xe4, + 0xd8, 0xc4, 0x1d, 0xf5, 0xc7, 0xfa, 0x65, 0xf0, 0x46, 0x6a, + 0x5f, 0xa7, 0xc3, 0x8c, 0x6f, 0x04, 0x7f, 0xcf, 0x97, 0xb9, + 0x68, 0x92, 0x31, 0x09, 0x02, 0x9f, 0x22, 0xc9, 0xf8, 0xe6, + 0x7e, 0xa8, 0x95, 0x5b, 0x6b, 0xfe, 0x9c, 0x4e, 0x63, 0x2d, + 0x8c, 0x1a, 0x4c, 0x8b, 0x14, 0x79, 0x08, 0xd5, 0x96, 0x76, + 0xd1, 0xb4, 0x2f, 0xae, 0x5d, 0x91, 0x88, 0x7c, 0xdd, 0xd2, + 0x06, 0x86, 0xcf, 0x0a, 0x83, 0x6f, 0xda, 0xca, 0x71, 0x7c, + 0xe7, 0xe5, 0x34, 0xa8, 0x9a, 0x53, 0x8d, 0xa5, 0xaa, 0x5d, + 0xb5, 0x17, 0x81, 0x34, 0x6f, 0xbe, 0xbb, 0xb6, 0x58, 0x22, + 0x90, 0x80, 0xf6, 0x9c, 0x1c, 0xb0, 0x79, 0x8f, 0x92, 0x5b, + 0x7d, 0x1c, 0x71, 0x5f, 0xb4, 0x87, 0x36, 0xbe, 0x81, 0x8d, + 0x4a, 0xfc, 0x28, 0x72, 0x81, 0xaf, 0x5f, 0xbd, 0x5f, 0x99, + 0xe3, 0xc9, 0x37, 0xb0, 0x6e, 0xad, 0x70, 0x96, 0xfa, 0xe3, + 0x99, 0xf7, 0x08, 0x14, 0x21, 0x21, 0xb7, 0x1a, 0xaa, 0xe8, + 0x07, 0xb6, 0xfd, 0xa3, 0x7a, 0x2d, 0x93, 0x64, 0x8f, 0x89, + 0x2c, 0x71, 0x49, 0x71, 0xb8, 0x45, 0xca, 0xe0, 0x7c, 0x00, + 0x8d, 0xbd, 0xb8, 0x1c, 0x3a, 0x94, 0xa2, 0xa7, 0x6d, 0x0a, + 0x2e, 0x84, 0xaf, 0xbd, 0xab, 0x05, 0x95, 0x64, 0x8b, 0x05, + 0xc8, 0xc9, 0x4e, 0xea, 0xb5, 0x96, 0x4a, 0x47, 0xdd, 0xf2, + 0xcb, 0x02, 0x82, 0x03, 0xc0, 0x59, 0xb3, 0xd9, 0x85, 0xdc, + 0xa8, 0xb9, 0x93, 0x85, 0xa2, 0xbc, 0x79, 0xfc, 0x72, 0x50, + 0xc1, 0xa0, 0xa5, 0xdb, 0x71, 0x35, 0xa1, 0x31, 0xbc, 0x68, + 0x4e, 0xd5, 0x19, 0x9e, 0x0e, 0x32, 0x3a, 0xad, 0x40, 0x9e, + 0x82, 0x3c, 0x1e, 0x2b, 0x34, 0x3b, 0xc9, 0x32, 0x61, 0x07, + 0x5e, 0x46, 0xa9, 0xbe, 0xbe, 0x73, 0x0c, 0x12, 0xef, 0x52, + 0x68, 0x82, 0xe2, 0x0b, 0x12, 0x74, 0xfc, 0x10, 0x5c, 0xc0, + 0xb5, 0x98, 0x4d, 0x86, 0xbb, 0x8c, 0x40, 0x15, 0xa1, 0x6e, + 0x46, 0x73, 0x2e, 0xd6, 0x99, 0x6b, 0x50, 0xab, 0x04, 0x1a, + 0x5f, 0xf4, 0xfa, 0xcb, 0x4b, 0xad, 0xc4, 0x5e, 0x62, 0xa7, + 0x48, 0xd4, 0x52, 0x85, 0xdc, 0x2a, 0x85, 0x9b, 0xee, 0x08, + 0xa5, 0xaa, 0xaa, 0xe8, 0x44, 0xf0, 0xed, 0x89, 0x21, 0xe4, + 0xb4, 0xab, 0x3c, 0x0d, 0x53, 0x7e, 0x53, 0xdd, 0xac, 0x47, + 0xda, 0x77, 0x79, 0x5f, 0x78, 0x7a, 0x80, 0x84, 0x46, 0x50, + 0xaa, 0xdb, 0x3b, 0x8c, 0x6b, 0xda, 0xb0, 0xac, 0x0a, 0xd3, + 0x4c, 0xe4, 0x6e, 0x87, 0xd1, 0xb2, 0x5a, 0xd5, 0x98, 0xae, + 0xcb, 0x7e, 0xc2, 0x19, 0xdc, 0x53, 0x64, 0x86, 0x4c, 0x7b, + 0xe0, 0x63, 0x22, 0x94, 0x34, 0xad, 0x15, 0xdc, 0xd8, 0xa8, + 0x5f, 0xc6, 0x58, 0xf6, 0x72, 0x34, 0xdd, 0xfb, 0x85, 0x8a, + 0xd9, 0xa3, 0xfb, 0x3b, 0xad, 0x5d, 0xf0, 0x1a, 0x0b, 0xa8, + 0x91, 0xe7, 0x7d, 0x26, 0x27, 0x38, 0xf8, 0xe0, 0x49, 0x1b, + 0x56, 0xc5, 0x5b, 0xe3, 0x1c, 0x7b, 0xa3, 0x53, 0x6d, 0x22, + 0xfa, 0xd7, 0x63, 0x5f, 0xf0, 0xcb, 0x92, 0x49, 0x01, 0x54, + 0xe5, 0x77, 0x5b, 0xd3, 0xab, 0xce, 0xb8, 0x3a, 0x5b, 0xb8, + 0x07, 0x40, 0x46, 0x51, 0xe4, 0x59, 0xa2, 0x45, 0x41, 0xcc, + 0x81, 0x6c, 0xe3, 0xa6, 0xb3, 0xa0, 0x30, 0x4a, 0x67, 0x10, + 0xed, 0xc0, 0x8a, 0xcd, 0xfc, 0xa5, 0x44, 0x9b, 0x59, 0x19, + 0x4a, 0x43, 0x8d, 0xec, 0x00, 0xd8, 0x6d, 0xf9, 0xf0, 0x2d, + 0xd9, 0x55, 0xfc, 0x05, 0xe2, 0x12, 0x48, 0x4d, 0xd6, 0x7d, + 0xec, 0x41, 0xc4, 0x9e, 0xe2, 0xed, 0x84, 0x14, 0x29, 0x0e, + 0x5b, 0x81, 0x0b, 0xb0, 0x87, 0x8a, 0xd3, 0x35, 0x5c, 0xad, + 0xdb, 0xcc, 0xa1, 0x3c, 0xcb, 0x8b, 0x23, 0x55, 0x69, 0xf1, + 0x83, 0x84, 0x81, 0x36, 0xae, 0xd5, 0xf3, 0x98, 0xb6, 0xb2, + 0xb5, 0xa1, 0x79, 0x6d, 0x80, 0x8f, 0x2e, 0x25, 0x71, 0x4e, + 0x16, 0xff, 0xa0, 0x7c, 0xa4, 0x62, 0x8c, 0x44, 0x85, 0x64, + 0x90, 0x7c, 0xac, 0x10, 0x36, 0xf2, 0xf2, 0xfb, 0x20, 0x2b, + 0xa1, 0x27, 0xd0, 0xcc, 0x27, 0xfd, 0xb0, 0xba, 0x3e, 0x37, + 0xb1, 0xa8, 0x9d, 0x3c, 0x82, 0x63, 0xd0, 0x16, 0x6d, 0x7a, + 0xdd, 0x2e, 0xea, 0xe5, 0x87, 0xd6, 0x64, 0x72, 0xdb, 0x60, + 0x53, 0x38, 0x18, 0x66, 0x1d, 0x25, 0xf6, 0x08, 0x92, 0x7f, + 0x68, 0x5b, 0x79, 0x07, 0xde, 0x93, 0xee, 0xf8, 0x8f, 0xce, + 0x28, 0xcf, 0xb1, 0x5b, 0x43, 0x51, 0xdf, 0xf5, 0xac, 0xe8, + 0x9c, 0x95, 0x14, 0x8a, 0x67, 0xe1, 0x25, 0xfe, 0x11, 0xa2, + 0x40, 0xf8, 0xdd, 0xcf, 0xf5, 0x17, 0x94, 0xb6, 0x88, 0x10, + 0xa2, 0x90, 0x58, 0xef, 0xaf, 0x73, 0xf8, 0x7c, 0x9b, 0x20, + 0x30, 0x79, 0xca, 0x3f, 0xa9, 0x22, 0x40, 0xfd, 0xcc, 0xb0, + 0x5d, 0x0d, 0x97, 0x6b, 0xc0, 0x75, 0x35, 0x33, 0xc5, 0x76, + 0x45, 0x6e, 0x9b, 0x78, 0xe7, 0xb4, 0x04, 0xb3, 0xba, 0x3b, + 0x93, 0xb1, 0xa9, 0x8f, 0xa1, 0x24, 0x5d, 0x1c, 0x0e, 0x66, + 0xc0, 0xc6, 0xcc, 0xd6, 0xb7, 0x88, 0x9d, 0xb8, 0x45, 0xe3, + 0xaa, 0xc9, 0x6c, 0xfd, 0x37, 0xdc, 0x85, 0xd5, 0x49, 0xfd, + 0xef, 0xeb, 0xf9, 0x7a, 0x3f, 0x7a, 0x4f, 0x86, 0x49, 0xaa, + 0x9f, 0x08, 0x12, 0x0b, 0x11, 0x35, 0x5c, 0xd5, 0xd3, 0xda, + 0x14, 0x50, 0x03, 0x2c, 0x24, 0x26, 0x0e, 0x29, 0x18, 0xcc, + 0x1d, 0x0a, 0x7c, 0x94, 0x8b, 0xc0, 0xa0, 0x3f, 0xea, 0xf8, + 0xf8, 0xa9, 0x1d, 0x65, 0x31, 0x6f, 0x3b, 0xa6, 0xd0, 0xfc, + 0x26, 0xb0, 0x4e, 0x3a, 0x66, 0xe7, 0x32, 0x10, 0x2e, 0x84, + 0x47, 0xad, 0xa9, 0x18, 0xfc, 0xa3, 0x8b, 0x74, 0x84, 0x4f, + 0xd4, 0x25, 0x93, 0x0f, 0xdb, 0x2e, 0xae, 0x88, 0x8e, 0x28, + 0xf8, 0x0f, 0xaa, 0x60, 0xd4, 0xbe, 0xad, 0x66, 0x0c, 0x0d, + 0x01, 0xbd, 0x8d, 0xc4, 0xfc, 0x48, 0xef, 0x78, 0x14, 0x34, + 0xee, 0xb3, 0xbc, 0xd4, 0xbb, 0x1f, 0x7c, 0x12, 0x5c, 0x9b, + 0xeb, 0x77, 0x3e, 0x2c, 0x6e, 0x31, 0x59, 0xe6, 0x78, 0xc5, + 0xe8, 0xa4, 0xdd, 0xf1, 0xef, 0x5d, 0x27, 0x45, 0x31, 0x13, + 0xd0, 0x21, 0xa1, 0x13, 0xce, 0xac, 0x7e, 0xbb, 0xfb, 0x32, + 0xeb, 0x76, 0x31, 0xc4, 0xba, 0xdf, 0xfb, 0x5a, 0x1b, 0xc9, + 0x9e, 0x74, 0xa0, 0x9e, 0x26, 0x82, 0xd5, 0x6e, 0x1d, 0xc3, + 0x0e, 0xd1, 0x6d, 0xdb, 0x43, 0xb3, 0x0b, 0x14, 0xcb, 0xf1, + 0xad, 0x62, 0x34, 0x49, 0xb8, 0xd3, 0x08, 0xca, 0x93, 0xf1, + 0x42, 0xb2, 0x4b, 0x23, 0x79, 0x93, 0xde, 0x18, 0x58, 0xf3, + 0x66, 0xfa, 0xdc, 0xab, 0xca, 0x33, 0x22, 0x2b, 0x5c, 0x8c, + 0x12, 0xc1, 0x7b, 0x2e, 0x52, 0x72, 0xa7, 0x78, 0x4a, 0x49, + 0xa1, 0x53, 0x02, 0x76, 0x2d, 0x2e, 0xf8, 0x43, 0x3c, 0xe8, + 0xfa, 0xb7, 0xff, 0x39, 0xed, 0x74, 0x9e, 0x11, 0x61, 0x33, + 0xde, 0x2a, 0x55, 0xe6, 0x4a, 0xe7, 0x97, 0xa6, 0xb2, 0xc3, + 0x40, 0x41, 0x52, 0x66, 0xcf, 0xbf, 0xf8, 0x8e, 0x08, 0xea, + 0x96, 0x4d, 0x03, 0xc9, 0xbe, 0x3c, 0x4e, 0x36, 0x8c, 0x6f, + 0x4d, 0x1e, 0xcd, 0x31, 0x6d, 0x53, 0xea, 0x9e, 0xf0, 0x8e, + 0x35, 0x97, 0x37, 0x54, 0xe9, 0x0f, 0xb8, 0x23, 0x25, 0x69, + 0x5b, 0xb5, 0xff, 0xc3, 0x5a, 0x2d, 0x10, 0x6a, 0xc0, 0xb8, + 0xee, 0x0d, 0x31, 0x5b, 0xe4, 0x69, 0x40, 0x62, 0xa7, 0x1b, + 0x16, 0xfa, 0xd6, 0xb8, 0xba, 0xc8, 0x6a, 0xa3, 0x29, 0xdd, + 0x9b, 0x4d, 0xd7, 0x96, 0xef, 0x31, 0x74, 0xac, 0x37, 0x10, + 0x91, 0x30, 0x0c, 0x15, 0x3f, 0x09, 0xb6, 0x7d, 0x22, 0xfb, + 0x8c, 0x6f, 0xc3, 0x93, 0xa3, 0x98, 0xa6, 0x23, 0xa4, 0x55, + 0xe0, 0x9e, 0x23, 0x06, 0xa9, 0x78, 0xe9, 0xb3, 0x88, 0xc9, + 0xb7, 0x83, 0x05, 0x46, 0x11, 0x3a, 0x0a, 0xb9, 0x74, 0x5b, + 0xa0, 0xb5, 0x06, 0x96, 0x86, 0xb6, 0xf4, 0x9d, 0x0d, 0x86, + 0x43, 0xa8, 0x40, 0x4b, 0x08, 0x93, 0x7c, 0xad, 0xb0, 0x50, + 0xb4, 0xd0, 0xe7, 0xad, 0xd0, 0x54, 0x5e, 0x15, 0xaf, 0xad, + 0x34, 0x12, 0x86, 0xb3, 0x29, 0x3b, 0x20, 0xc9, 0xad, 0xeb, + 0xc2, 0x65, 0xf3, 0x5c, 0x2d, 0xe5, 0xff, 0xfd, 0x81, 0x79, + 0xf5, 0x11, 0x6f, 0xf7, 0xca, 0x0c, 0x76, 0xf0, 0xd4, 0x02, + 0x9d, 0xb7, 0x76, 0x39, 0x6d, 0x32, 0x6a, 0xb8, 0x30, 0xa4, + 0x01, 0xcc, 0x10, 0xef, 0xb1, 0x0e, 0x41, 0x22, 0x82, 0x5b, + 0x22, 0xcb, 0x32, 0x19, 0x2e, 0xa3, 0x0a, 0xce, 0x05, 0xdd, + 0xe8, 0x4a, 0x58, 0x92, 0xe1, 0x02, 0x82, 0x03, 0xc0, 0x22, + 0x0f, 0x95, 0x5b, 0xc2, 0x1f, 0xde, 0xf0, 0xde, 0xf4, 0x86, + 0xbd, 0xef, 0x07, 0x7d, 0x52, 0x03, 0x8c, 0x26, 0x31, 0x17, + 0xfd, 0x5c, 0x97, 0xed, 0xd5, 0xe0, 0xb3, 0x18, 0x2d, 0x68, + 0x10, 0x3f, 0xc4, 0xdf, 0xd1, 0x05, 0x78, 0x81, 0x3d, 0x05, + 0xde, 0xba, 0x3a, 0x67, 0x85, 0x0e, 0xdf, 0xb5, 0x16, 0x28, + 0xe8, 0x84, 0x3a, 0x71, 0x2a, 0x20, 0x17, 0x28, 0x05, 0xfd, + 0xb7, 0x4d, 0x22, 0x4a, 0x93, 0x46, 0x56, 0x27, 0x43, 0xc0, + 0x3a, 0x16, 0xff, 0x3d, 0x61, 0xcc, 0xcb, 0xce, 0xac, 0xa8, + 0x53, 0x3a, 0x0d, 0xf4, 0x2d, 0xd2, 0x73, 0xf2, 0x64, 0xa0, + 0x1e, 0x60, 0x53, 0xec, 0x0d, 0xff, 0xe0, 0x00, 0x10, 0xfb, + 0xa4, 0x57, 0xd3, 0xfc, 0xe4, 0xe0, 0xec, 0x44, 0x0b, 0x1c, + 0x05, 0x39, 0xa4, 0x13, 0x87, 0x29, 0x11, 0x9d, 0xea, 0xe9, + 0x64, 0xa9, 0x1c, 0x76, 0x3a, 0x65, 0x0b, 0xfd, 0xed, 0x77, + 0x46, 0x4f, 0xcd, 0x0b, 0x63, 0xc4, 0x83, 0x0b, 0x56, 0x79, + 0xd3, 0x67, 0x01, 0x11, 0x02, 0xd9, 0x50, 0xd8, 0x23, 0xf4, + 0xb6, 0x02, 0x4c, 0xae, 0xb5, 0xc9, 0x68, 0x1b, 0x87, 0x33, + 0xbb, 0xdc, 0x64, 0x0e, 0x32, 0x34, 0xb2, 0x25, 0xaa, 0x76, + 0xdd, 0x7e, 0xc3, 0x46, 0x51, 0x1c, 0xc1, 0xd0, 0x05, 0x09, + 0x6c, 0x27, 0xd3, 0xcf, 0x33, 0x7a, 0xb9, 0x26, 0x24, 0x23, + 0x4a, 0x93, 0x9f, 0x4b, 0x96, 0xc7, 0xe2, 0xb2, 0x51, 0x42, + 0x4d, 0x5d, 0xd9, 0x73, 0x75, 0xce, 0x23, 0x28, 0x56, 0x5e, + 0xe7, 0x96, 0x58, 0x04, 0xfd, 0x33, 0x93, 0x08, 0x41, 0x62, + 0x02, 0x7e, 0xc9, 0xc6, 0x55, 0x64, 0x19, 0xda, 0x39, 0xb8, + 0x5d, 0x09, 0x47, 0xf3, 0xdd, 0x77, 0xee, 0xea, 0x35, 0x73, + 0x95, 0xdb, 0x18, 0x4d, 0xd1, 0xfe, 0xee, 0x40, 0x31, 0x2a, + 0x22, 0x91, 0x69, 0xd6, 0xed, 0x9c, 0x54, 0x14, 0x73, 0x61, + 0x61, 0xe7, 0x1d, 0x34, 0x96, 0x47, 0xff, 0x28, 0x7a, 0x48, + 0xa3, 0xf4, 0xcd, 0x64, 0x23, 0xe2, 0x52, 0x2f, 0x20, 0x8f, + 0x04, 0xb3, 0xdc, 0xf0, 0x29, 0x67, 0x88, 0x76, 0x79, 0xdb, + 0x86, 0xa7, 0x95, 0xf0, 0x15, 0x81, 0xbb, 0x98, 0xee, 0xff, + 0x55, 0x7c, 0xb0, 0xee, 0x67, 0x65, 0xfd, 0xf2, 0x29, 0x0f, + 0x85, 0x51, 0xf9, 0xac, 0x5c, 0x55, 0x5a, 0xde, 0x40, 0x62, + 0x58, 0x55, 0x9f, 0x09, 0x4c, 0x2e, 0x28, 0x75, 0xbc, 0x48, + 0xe2, 0x97, 0x85, 0xb3, 0x83, 0xeb, 0x21, 0x49, 0x21, 0xd4, + 0xed, 0x74, 0x4f, 0xc1, 0x6c, 0x34, 0x8c, 0x11, 0xb0, 0x93, + 0x41, 0x99, 0x23, 0x2e, 0xa4, 0xc1, 0x9f, 0x34, 0x74, 0x64, + 0xbb, 0xd7, 0x4f, 0x8f, 0x9f, 0x3a, 0x0c, 0x4f, 0x5e, 0xdd, + 0x41, 0x07, 0xf1, 0xfd, 0x5a, 0x9d, 0xe6, 0x77, 0xd8, 0x7e, + 0x71, 0x7b, 0xad, 0xf7, 0x76, 0x13, 0x71, 0x90, 0xb3, 0x0f, + 0x46, 0x8e, 0xee, 0x7b, 0x33, 0x97, 0x5d, 0x21, 0x3b, 0xa0, + 0x58, 0x9e, 0xb7, 0x87, 0x30, 0x8f, 0xc1, 0x23, 0x2c, 0xde, + 0xf7, 0x0d, 0xa9, 0xd6, 0x50, 0xeb, 0x35, 0x7a, 0x82, 0xab, + 0x22, 0x49, 0x86, 0xd4, 0x61, 0xc7, 0xc2, 0x4e, 0x77, 0xfc, + 0x16, 0x0b, 0xaf, 0x81, 0x6a, 0x47, 0xea, 0xac, 0x7e, 0x51, + 0x4c, 0x56, 0x30, 0x21, 0x46, 0x41, 0xc3, 0x92, 0x60, 0x99, + 0x4f, 0x88, 0x36, 0x3b, 0x27, 0xb4, 0xb2, 0x7e, 0x44, 0x2f, + 0xdd, 0x95, 0xe4, 0x5e, 0x16, 0x1f, 0xa7, 0x32, 0x6b, 0x60, + 0x24, 0x0f, 0xf2, 0xe6, 0x35, 0x3c, 0x0c, 0x3e, 0xb5, 0xd6, + 0xdd, 0x63, 0xe2, 0x76, 0x35, 0x38, 0x79, 0xbf, 0xa5, 0x23, + 0xa4, 0xdd, 0xeb, 0x01, 0x48, 0xd0, 0x60, 0x86, 0x11, 0x38, + 0x5f, 0x9e, 0x6b, 0x00, 0x67, 0xd2, 0x5b, 0x41, 0x0a, 0x5e, + 0x13, 0x0f, 0xa1, 0x9e, 0x90, 0x85, 0xa6, 0x7f, 0xe5, 0x4b, + 0x9e, 0x93, 0x4e, 0x5b, 0x1f, 0x47, 0x62, 0xb0, 0x23, 0xbe, + 0x82, 0xa9, 0xd9, 0xb6, 0x2e, 0xfd, 0xb1, 0x10, 0xca, 0xe0, + 0xc9, 0x5d, 0xf6, 0x85, 0x18, 0x6c, 0x9c, 0x1d, 0x1f, 0x7c, + 0xf6, 0x55, 0x09, 0x80, 0xcf, 0xac, 0xfe, 0x37, 0x6a, 0x4f, + 0x96, 0xaa, 0x40, 0x79, 0x8b, 0x4a, 0xf2, 0x96, 0x79, 0x12, + 0x1a, 0x26, 0x87, 0x06, 0x35, 0x4d, 0xd4, 0x3e, 0x14, 0x39, + 0xe5, 0x6c, 0x39, 0x0f, 0x84, 0xb3, 0x5f, 0xed, 0xf4, 0xff, + 0x89, 0x52, 0x05, 0x00, 0xf1, 0xd1, 0xc3, 0xcf, 0x54, 0x10, + 0x24, 0x7c, 0xa6, 0xb5, 0x95, 0xa8, 0x6e, 0x13, 0x3e, 0x4a, + 0x40, 0x6c, 0xf9, 0x63, 0x90, 0x44, 0x52, 0x07, 0x53, 0xb7, + 0x51, 0xd9, 0x18, 0x47, 0x2e, 0xb0, 0x4e, 0x0f, 0x09, 0x99, + 0x3a, 0x97, 0x26, 0x53, 0xa6, 0x02, 0x06, 0x0e, 0x93, 0xe1, + 0x0b, 0xc5, 0xa9, 0x14, 0xd3, 0xd6, 0x8a, 0x29, 0x75, 0xcd, + 0xb6, 0x7b, 0x64, 0x7c, 0xdd, 0x7e, 0xb4, 0x0a, 0x87, 0x48, + 0x4a, 0x1b, 0x0e, 0x74, 0x4c, 0xd3, 0x0e, 0x96, 0x0e, 0x53, + 0xc4, 0x3d, 0x7b, 0x1c, 0x87, 0x6a, 0x15, 0xd8, 0x77, 0xba, + 0xe6, 0xa0, 0x2f, 0x2c, 0x1a, 0x9d, 0xde, 0x79, 0xfd, 0xab, + 0x44, 0x80, 0xf0, 0x37, 0x9a, 0x3b, 0xf8, 0xde, 0x3d, 0x29, + 0xcb, 0x89, 0x64, 0x4b, 0x57, 0xe7, 0x6b, 0x84, 0x09, 0x27, + 0x17, 0x2f, 0xb2, 0xba, 0x3d, 0x09, 0xc9, 0x3c, 0x89, 0xe6, + 0x19, 0x73, 0x83, 0xf7, 0xc6, 0x19, 0x18, 0x96, 0xb2, 0x7d, + 0x1e, 0x9f, 0x70, 0x1f, 0xfc, 0x1f, 0xe2, 0xb5, 0x69, 0x1e, + 0xf4, 0x65, 0x91, 0xce, 0x4b, 0xdc, 0x74, 0x49, 0x21, 0x64, + 0x8b, 0x33, 0x50, 0xd2, 0xc1, 0x33, 0x62, 0x5b, 0xde, 0x0a, + 0x72, 0xbe, 0xc0, 0x05, 0x51, 0x15, 0x80, 0xed, 0x32, 0x3a, + 0x64, 0xa2, 0x73, 0x68, 0x5b, 0x16, 0xcf, 0x70, 0x5c, 0x98, + 0xe5, 0x67, 0x45, 0x60, 0x57, 0x2b, 0x47, 0x0a, 0x22, 0x73, + 0xc3, 0x56, 0x33, 0x3e, 0x14, 0x1d, 0x0c, 0xd1, 0x03, 0x08, + 0x92, 0x21, 0x2b, 0xa9, 0x6e, 0x6b, 0xf9, 0x0c, 0x1e, 0x86, + 0xdd, 0xb5, 0xbb, 0xa4, 0xa5, 0x82, 0x99, 0x98, 0x49, 0x36, + 0xec, 0x98, 0x98, 0x95, 0xac, 0xc2, 0xa0, 0x1f, 0xa5, 0x7e, + 0x67, 0xd1, 0xcf, 0x6a, 0xf4, 0x16, 0x08, 0x7a, 0x8d, 0x0b, + 0xae, 0x12, 0x51, 0xe6, 0x8e, 0xe6, 0xcd, 0xa1, 0xaa, 0x6d, + 0xe4, 0x54, 0xd4, 0x69, 0x1b, 0x09, 0x6a, 0xba, 0x5e, 0x0b, + 0x11, 0x9c, 0x83, 0xb3, 0x5c, 0x67, 0xbb, 0x2d, 0xf8, 0x66, + 0x1c, 0x33, 0xb8, 0x22, 0x58, 0x10, 0x96, 0xe9, 0x99, 0xaf, + 0x0b, 0x2a, 0xf1, 0xe0, 0xcb, 0x56, 0xfb, 0x6d, 0x04, 0x40, + 0xec, 0x37, 0x67, 0x1e, 0x08, 0x7a, 0x1c, 0xe9, 0xd8, 0x54, + 0xf7, 0xd4, 0xc7, 0x3c, 0x45, 0x23, 0x2b, 0x76, 0xd2, 0x62, + 0xc2, 0x53, 0xce, 0xfe, 0x02, 0xc4, 0xd9, 0xf6, 0x3c, 0xed, + 0x49, 0x47, 0x21, 0xf9, 0x03, 0x3a, 0xa0, 0x16, 0x3a, 0xfe, + 0x0c, 0x2f, 0x54, 0x7e, 0x85, 0x29, 0x7b, 0xc0, 0xaf, 0xa8, + 0x5d, 0x31, 0x25, 0xda, 0xa7, 0xe3, 0x92, 0x1b, 0x64, 0x01, + 0x1b, 0x3f, 0x6e, 0x47, 0xc5, 0x5a, 0x84, 0x52, 0x17, 0x02, + 0x82, 0x03, 0xc1, 0x00, 0x81, 0x99, 0x2e, 0x72, 0x41, 0x6e, + 0x86, 0xeb, 0x6f, 0x42, 0xd1, 0x38, 0x6e, 0xaa, 0x1a, 0xd5, + 0x0a, 0xad, 0x51, 0xb1, 0xce, 0xd6, 0x35, 0xbe, 0x34, 0xd8, + 0xc1, 0xe4, 0x5f, 0xdf, 0x2e, 0xe4, 0x90, 0xf2, 0x61, 0x21, + 0x46, 0xc6, 0xfe, 0xab, 0x0f, 0x6c, 0x97, 0x78, 0xcd, 0x55, + 0x86, 0x83, 0x61, 0x99, 0x49, 0x14, 0x86, 0xc6, 0x86, 0xf1, + 0x41, 0x66, 0xc9, 0x39, 0x52, 0x99, 0x49, 0x07, 0xd6, 0x9d, + 0xb7, 0x40, 0x34, 0x5f, 0xe7, 0x3a, 0xfa, 0x95, 0xeb, 0xa1, + 0x03, 0xb7, 0x52, 0x71, 0x93, 0x30, 0x0b, 0x51, 0x58, 0x82, + 0x07, 0x2f, 0x44, 0xa9, 0x4f, 0x9b, 0x1b, 0xf3, 0xd6, 0x21, + 0x3d, 0x68, 0xef, 0x3f, 0xaf, 0xc2, 0x6f, 0xa0, 0xd5, 0x2b, + 0xb8, 0x73, 0x84, 0x67, 0x36, 0x8b, 0xa4, 0x25, 0xe0, 0x86, + 0xd9, 0x14, 0x5c, 0x6c, 0xd8, 0x61, 0xe1, 0x0a, 0x6c, 0xaf, + 0xbb, 0x9c, 0xf6, 0x74, 0xca, 0x5a, 0x04, 0xac, 0x85, 0xc1, + 0x1b, 0x4d, 0xf2, 0x07, 0xb6, 0x1e, 0x97, 0x7b, 0x75, 0xdf, + 0x9b, 0x8a, 0x31, 0xc6, 0x90, 0xd5, 0x8d, 0x39, 0xc2, 0x54, + 0xf4, 0xe2, 0x83, 0x57, 0x12, 0x19, 0xf5, 0xb2, 0xd2, 0x53, + 0x81, 0x6d, 0xf0, 0x09, 0xc9, 0x80, 0x8b, 0x07, 0x7c, 0x59, + 0xcd, 0x78, 0x00, 0xd6, 0x44, 0x7f, 0xe4, 0xdb, 0x77, 0x02, + 0x00, 0x25, 0x79, 0x91, 0xc9, 0xde, 0xd0, 0xed, 0x3f, 0xfc, + 0x37, 0x36, 0xea, 0xf0, 0x56, 0x50, 0xe7, 0x38, 0xca, 0xe1, + 0x67, 0x12, 0x96, 0x55, 0x3e, 0xff, 0x97, 0xe5, 0xa7, 0x03, + 0x5b, 0x72, 0x80, 0xd6, 0xa5, 0x23, 0x39, 0x78, 0x07, 0xc8, + 0x83, 0x19, 0x74, 0xfb, 0x79, 0xc2, 0x9e, 0xbd, 0xf9, 0xaf, + 0x09, 0x0f, 0xbd, 0x3d, 0x34, 0xe8, 0x44, 0x89, 0xb1, 0xf1, + 0x2b, 0xa5, 0xff, 0x22, 0xc9, 0x47, 0xe2, 0x31, 0xb5, 0x6b, + 0x8a, 0x65, 0x5f, 0x81, 0x5f, 0x89, 0xb0, 0x03, 0x5d, 0x53, + 0x0e, 0xdd, 0xfb, 0xe5, 0x70, 0xaa, 0xd2, 0x37, 0x4d, 0xa1, + 0x7c, 0xf2, 0xe4, 0x7f, 0xf1, 0x4a, 0xaf, 0x12, 0xd1, 0x83, + 0xdc, 0xb2, 0x9e, 0xc1, 0x95, 0x3d, 0x04, 0x9f, 0xa3, 0xad, + 0xcc, 0x78, 0x14, 0x9a, 0xf9, 0x58, 0x39, 0x08, 0x15, 0xda, + 0x1b, 0x94, 0x50, 0x2d, 0x44, 0xc0, 0x23, 0x1c, 0x36, 0x5f, + 0x16, 0x08, 0xa3, 0xdf, 0x9e, 0x4f, 0xbb, 0x07, 0xcd, 0xe3, + 0x8c, 0xbf, 0xf1, 0xc3, 0x3e, 0x98, 0xf8, 0x49, 0x79, 0x58, + 0xc9, 0x0f, 0x47, 0xc0, 0xab, 0x2f, 0x21, 0x63, 0xf6, 0xe6, + 0xfe, 0x8a, 0xea, 0xbc, 0x32, 0x63, 0xca, 0x75, 0xf8, 0xa4, + 0x1b, 0x6c, 0xfe, 0x9a, 0x6e, 0x68, 0x1f, 0x48, 0x59, 0xfb, + 0x34, 0x43, 0x10, 0xd5, 0x0d, 0x80, 0x54, 0xcb, 0x67, 0x21, + 0xc7, 0x13, 0x85, 0x38, 0x0c, 0xf9, 0x40, 0x2e, 0x2e, 0x4a, + 0x05, 0x9e, 0x51, 0xae, 0xdd, 0xba, 0x23, 0x83, 0x66, 0x2a, + 0xbf, 0x7f, 0xca, 0x9c, 0x6c, 0x2d, 0x6b, 0x7d, 0x68, 0x52, + 0x81, 0x56, 0x2f, 0xea, 0xf9, 0xe7, 0xf1, 0x55, 0x16, 0xfc, + 0x29, 0xe2, 0xa5, 0x1e, 0x0a, 0x06, 0xe0, 0x85, 0x4e, 0xa6, + 0x5d, 0x20, 0x9d, 0x2b, 0xa2, 0xad, 0xaa, 0xd6, 0x9b, 0xd2, + 0x98, 0x29, 0x45, 0x5c, 0x55, 0xc0, 0x91, 0xa2, 0x65, 0xcd, + 0xac, 0xc6, 0x1a, 0x53, 0xa1, 0x46, 0x13, 0xf9, 0xfe, 0x1a, + 0xf6, 0xdf, 0xa5, 0x1a, 0x58, 0x7c, 0x81, 0x2e, 0x46, 0x46, + 0xf7, 0x2f, 0xd6, 0xaa, 0x21, 0xb0, 0x0e, 0x7e, 0xac, 0xb8, + 0xc6, 0x76, 0x62, 0x82, 0x3b, 0x0a, 0x36, 0xbe, 0x97, 0x16, + 0xd5, 0x79, 0x55, 0x15, 0x64, 0x2a, 0xbe, 0x19, 0x4e, 0x93, + 0x3b, 0x44, 0x7c, 0xe2, 0xfc, 0x18, 0x4e, 0x83, 0x37, 0xfb, + 0x26, 0x78, 0x6d, 0x24, 0x6b, 0x48, 0x21, 0x67, 0xde, 0xf5, + 0x00, 0x22, 0x9a, 0xec, 0x40, 0x16, 0x96, 0x8a, 0x3f, 0xd5, + 0xa6, 0x5e, 0x03, 0x84, 0xbb, 0x15, 0x4d, 0x55, 0x71, 0x00, + 0x90, 0xc2, 0x96, 0x25, 0x01, 0xab, 0xe6, 0x47, 0x44, 0x6f, + 0xf9, 0x53, 0x80, 0x2b, 0xa8, 0x83, 0xc8, 0x14, 0x77, 0x13, + 0x00, 0x66, 0xee, 0x7e, 0x7a, 0xa0, 0x28, 0x65, 0xf3, 0x31, + 0xb6, 0xac, 0xd7, 0x87, 0x84, 0x29, 0xed, 0x5b, 0xcd, 0x74, + 0xc0, 0x89, 0x51, 0x11, 0x9a, 0xd5, 0x7b, 0xe0, 0x9c, 0xd0, + 0x8d, 0x72, 0xe3, 0x77, 0xda, 0x0a, 0xc2, 0xdc, 0x6f, 0xad, + 0x49, 0x03, 0xfa, 0xe6, 0x7e, 0xa6, 0x24, 0x32, 0xe6, 0x8f, + 0xd9, 0x70, 0xfa, 0x59, 0x70, 0xa9, 0xa3, 0x08, 0x7d, 0x89, + 0xc4, 0x96, 0x61, 0xc2, 0xf5, 0xe5, 0xb5, 0x3b, 0x0d, 0xec, + 0xb8, 0x9c, 0xee, 0x09, 0x77, 0x27, 0xbd, 0x35, 0x66, 0x90, + 0x9e, 0x46, 0xf7, 0xbd, 0xa6, 0xc5, 0x31, 0xd4, 0x6a, 0x52, + 0x17, 0x5d, 0x0a, 0x0e, 0x2c, 0x34, 0x7a, 0x6a, 0x21, 0xac, + 0x42, 0xf0, 0x31, 0xde, 0x48, 0xe0, 0x27, 0xd0, 0x79, 0xc9, + 0x06, 0x94, 0x7b, 0x51, 0x4b, 0x5b, 0x02, 0x6a, 0x19, 0xba, + 0x71, 0x45, 0x9c, 0xdf, 0xe6, 0x30, 0x9e, 0xaa, 0xad, 0xa1, + 0x87, 0xf6, 0x37, 0xde, 0xa2, 0x97, 0x68, 0x20, 0x2d, 0x5a, + 0xdc, 0xdd, 0x91, 0x63, 0x5f, 0x79, 0xda, 0x99, 0x20, 0x3a, + 0x4b, 0xe5, 0x43, 0x0e, 0x12, 0x70, 0x57, 0x91, 0xfa, 0xee, + 0xc4, 0xb6, 0xb6, 0xb1, 0xf1, 0x06, 0xbd, 0xcf, 0x8d, 0x2a, + 0x05, 0xc0, 0x07, 0x23, 0x84, 0x85, 0xef, 0x9c, 0xbb, 0x6f, + 0x5f, 0x4a, 0x9a, 0x27, 0x9f, 0x9f, 0x32, 0x97, 0xe8, 0x24, + 0xb9, 0x64, 0x2c, 0x39, 0xff, 0x2f, 0x4b, 0xc4, 0x7e, 0x65, + 0xfe, 0xbb, 0x5c, 0xa0, 0xb2, 0x6e, 0xc4, 0xb6, 0x93, 0x2b, + 0x51, 0x9e, 0x2e, 0x1f, 0xd8, 0xcf, 0x60, 0xe0, 0x75, 0x15, + 0xf9, 0xa0, 0x67, 0x99, 0x88, 0x2b, 0x76, 0xce, 0x41, 0x42, + 0x10, 0x29, 0x89, 0xbf, 0xca, 0xb7, 0x61, 0x08, 0x94, 0xee, + 0xa0, 0xb3, 0x3a, 0x09, 0xc5, 0x6f, 0x04, 0xf9, 0x1b, 0xb5, + 0x64, 0x99, 0x08, 0xe4, 0xcc, 0xce, 0xdf, 0x71, 0x65, 0x8a, + 0x6d, 0x62, 0xde, 0x76, 0x1d, 0x6d, 0x6b, 0x78, 0x22, 0x32, + 0x63, 0xdd, 0x53, 0x7d, 0xec, 0xed, 0x9d, 0x82, 0xa9, 0x2c, + 0x5c, 0x8a, 0x17, 0xdd, 0x85, 0xf9, 0xd2, 0xac, 0x6e, 0x98, + 0x60, 0x2e, 0x08, 0xd4, 0x06, 0x76, 0xf4, 0x97, 0xca, 0xb1, + 0x72, 0x50, 0x5b, 0x83, 0xea, 0xbb, 0x39, 0x0f, 0x18, 0xb3, + 0xb8, 0x03, 0xee, 0x7c, 0x84, 0xa9, 0x69, 0xcd, 0x1d, 0xbd, + 0xe2, 0xb7, 0xce, 0xe2, 0x6f, 0x03, 0x49, 0x52, 0x67, 0xa0, + 0x1b, 0x23, 0x43, 0x92, 0x2c, 0x7c, 0x3b, 0x65, 0xe8, 0x61, + 0x99, 0xde, 0xb5, 0xf1, 0x63, 0x73, 0x92, 0x6c, 0x70, 0x8b, + 0x83, 0x10, 0xb4, 0x06, 0x2c, 0x99, 0x12, 0x73, 0xec, 0x87, + 0x92, 0x09, 0x67, 0x96, 0xd6, 0x9c, 0x9f, 0x35, 0x48, 0x48, + 0x3b, 0x44, 0x00, 0x73, 0x1c, 0x59, 0xeb, 0x81, 0x7b, 0xd1, + 0xda, 0x76, 0xcf, 0xc2, 0x4d, 0xf1, 0xa2, 0x5b, 0x2f, 0x5f, + 0x91, 0x29, 0x6e, 0x08, 0x37, 0xd6, 0xaa, 0xd2, 0xf8, 0x4f, + 0x5e, 0x00, 0x16, 0x52 +}; diff --git a/apps/timeouts.h b/apps/timeouts.h index f423010c0c73..e023b0aa4920 100644 --- a/apps/timeouts.h +++ b/apps/timeouts.h @@ -1,60 +1,10 @@ -/* apps/timeouts.h */ /* - * DTLS implementation written by Nagendra Modadugu - * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. - */ -/* ==================================================================== - * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #ifndef INCLUDED_TIMEOUTS_H diff --git a/apps/ts.c b/apps/ts.c index 341a42bb1224..930c1daaab6d 100644 --- a/apps/ts.c +++ b/apps/ts.c @@ -1,371 +1,327 @@ -/* apps/ts.c */ /* - * Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL project - * 2002. - */ -/* ==================================================================== - * Copyright (c) 2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "apps.h" -#include <openssl/bio.h> -#include <openssl/err.h> -#include <openssl/pem.h> -#include <openssl/rand.h> -#include <openssl/ts.h> -#include <openssl/bn.h> +#include <openssl/opensslconf.h> +#ifdef OPENSSL_NO_TS +NON_EMPTY_TRANSLATION_UNIT +#else +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# include "apps.h" +# include "progs.h" +# include <openssl/bio.h> +# include <openssl/err.h> +# include <openssl/pem.h> +# include <openssl/rand.h> +# include <openssl/ts.h> +# include <openssl/bn.h> -#undef PROG -#define PROG ts_main +/* Request nonce length, in bits (must be a multiple of 8). */ +# define NONCE_LENGTH 64 -/* Length of the nonce of the request in bits (must be a multiple of 8). */ -#define NONCE_LENGTH 64 +/* Name of config entry that defines the OID file. */ +# define ENV_OID_FILE "oid_file" -/* Macro definitions for the configuration file. */ -#define ENV_OID_FILE "oid_file" - -/* Local function declarations. */ +/* Is |EXACTLY_ONE| of three pointers set? */ +# define EXACTLY_ONE(a, b, c) \ + (( a && !b && !c) || \ + ( b && !a && !c) || \ + ( c && !a && !b)) static ASN1_OBJECT *txt2obj(const char *oid); static CONF *load_config_file(const char *configfile); /* Query related functions. */ -static int query_command(const char *data, char *digest, +static int query_command(const char *data, const char *digest, const EVP_MD *md, const char *policy, int no_nonce, int cert, const char *in, const char *out, int text); -static BIO *BIO_open_with_default(const char *file, const char *mode, - FILE *default_fp); -static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md, +static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md, const char *policy, int no_nonce, int cert); -static int create_digest(BIO *input, char *digest, +static int create_digest(BIO *input, const char *digest, const EVP_MD *md, unsigned char **md_value); static ASN1_INTEGER *create_nonce(int bits); /* Reply related functions. */ -static int reply_command(CONF *conf, char *section, char *engine, - char *queryfile, char *passin, char *inkey, - char *signer, char *chain, const char *policy, - char *in, int token_in, char *out, int token_out, - int text); +static int reply_command(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, const char *inkey, + const EVP_MD *md, const char *signer, const char *chain, + const char *policy, const char *in, int token_in, + const char *out, int token_out, int text); static TS_RESP *read_PKCS7(BIO *in_bio); -static TS_RESP *create_response(CONF *conf, const char *section, char *engine, - char *queryfile, char *passin, char *inkey, - char *signer, char *chain, - const char *policy); -static ASN1_INTEGER *MS_CALLBACK serial_cb(TS_RESP_CTX *ctx, void *data); +static TS_RESP *create_response(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, + const char *inkey, const EVP_MD *md, const char *signer, + const char *chain, const char *policy); +static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data); static ASN1_INTEGER *next_serial(const char *serialfile); static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial); /* Verify related functions. */ -static int verify_command(char *data, char *digest, char *queryfile, - char *in, int token_in, - char *ca_path, char *ca_file, char *untrusted); -static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, - char *queryfile, - char *ca_path, char *ca_file, - char *untrusted); -static X509_STORE *create_cert_store(char *ca_path, char *ca_file); -static int MS_CALLBACK verify_cb(int ok, X509_STORE_CTX *ctx); +static int verify_command(const char *data, const char *digest, const char *queryfile, + const char *in, int token_in, + const char *CApath, const char *CAfile, const char *untrusted, + X509_VERIFY_PARAM *vpm); +static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, + const char *queryfile, + const char *CApath, const char *CAfile, + const char *untrusted, + X509_VERIFY_PARAM *vpm); +static X509_STORE *create_cert_store(const char *CApath, const char *CAfile, + X509_VERIFY_PARAM *vpm); +static int verify_cb(int ok, X509_STORE_CTX *ctx); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA, + OPT_DIGEST, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT, + OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT, + OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER, + OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED, + OPT_MD, OPT_V_ENUM, OPT_R_ENUM +} OPTION_CHOICE; -/* Main function definition. */ -int MAIN(int, char **); +const OPTIONS ts_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"config", OPT_CONFIG, '<', "Configuration file"}, + {"section", OPT_SECTION, 's', "Section to use within config file"}, + {"query", OPT_QUERY, '-', "Generate a TS query"}, + {"data", OPT_DATA, '<', "File to hash"}, + {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"}, + OPT_R_OPTIONS, + {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"}, + {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"}, + {"cert", OPT_CERT, '-', "Put cert request into query"}, + {"in", OPT_IN, '<', "Input file"}, + {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"}, + {"text", OPT_TEXT, '-', "Output text (not DER)"}, + {"reply", OPT_REPLY, '-', "Generate a TS reply"}, + {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"inkey", OPT_INKEY, 's', "File with private key for reply"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, + {"chain", OPT_CHAIN, '<', "File with signer CA chain"}, + {"verify", OPT_VERIFY, '-', "Verify a TS response"}, + {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"}, + {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"}, + {"untrusted", OPT_UNTRUSTED, '<', "File with untrusted certs"}, + {"", OPT_MD, '-', "Any supported digest"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {OPT_HELP_STR, 1, '-', "\nOptions specific to 'ts -verify': \n"}, + OPT_V_OPTIONS, + {OPT_HELP_STR, 1, '-', "\n"}, + {NULL} +}; -int MAIN(int argc, char **argv) +/* + * This command is so complex, special help is needed. + */ +static char* opt_helplist[] = { + "Typical uses:", + "ts -query [-rand file...] [-config file] [-data file]", + " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]", + " [-in file] [-out file] [-text]", + " or", + "ts -reply [-config file] [-section tsa_section]", + " [-queryfile file] [-passin password]", + " [-signer tsa_cert.pem] [-inkey private_key.pem]", + " [-chain certs_file.pem] [-tspolicy oid]", + " [-in file] [-token_in] [-out file] [-token_out]", +# ifndef OPENSSL_NO_ENGINE + " [-text] [-engine id]", +# else + " [-text]", +# endif + " or", + "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem", + " [-data file] [-digest hexstring]", + " [-queryfile file] -in file [-token_in]", + " [[options specific to 'ts -verify']]", + NULL, +}; + +int ts_main(int argc, char **argv) { - int ret = 1; - char *configfile = NULL; - char *section = NULL; CONF *conf = NULL; - enum mode { - CMD_NONE, CMD_QUERY, CMD_REPLY, CMD_VERIFY - } mode = CMD_NONE; - char *data = NULL; - char *digest = NULL; + const char *CAfile = NULL, *untrusted = NULL, *prog; + const char *configfile = default_config_file, *engine = NULL; + const char *section = NULL; + char **helpp; + char *password = NULL; + char *data = NULL, *digest = NULL, *policy = NULL; + char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL; + char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL; const EVP_MD *md = NULL; - char *rnd = NULL; - char *policy = NULL; - int no_nonce = 0; - int cert = 0; - char *in = NULL; - char *out = NULL; - int text = 0; - char *queryfile = NULL; - char *passin = NULL; /* Password source. */ - char *password = NULL; /* Password itself. */ - char *inkey = NULL; - char *signer = NULL; - char *chain = NULL; - char *ca_path = NULL; - char *ca_file = NULL; - char *untrusted = NULL; - char *engine = NULL; + OPTION_CHOICE o, mode = OPT_ERR; + int ret = 1, no_nonce = 0, cert = 0, text = 0; + int vpmtouched = 0; + X509_VERIFY_PARAM *vpm = NULL; /* Input is ContentInfo instead of TimeStampResp. */ int token_in = 0; /* Output is ContentInfo instead of TimeStampResp. */ int token_out = 0; - int free_bio_err = 0; - - ERR_load_crypto_strings(); - apps_startup(); - if (bio_err == NULL && (bio_err = BIO_new(BIO_s_file())) != NULL) { - free_bio_err = 1; - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - } - - if (!load_config(bio_err, NULL)) - goto cleanup; + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + goto end; - for (argc--, argv++; argc > 0; argc--, argv++) { - if (strcmp(*argv, "-config") == 0) { - if (argc-- < 1) - goto usage; - configfile = *++argv; - } else if (strcmp(*argv, "-section") == 0) { - if (argc-- < 1) - goto usage; - section = *++argv; - } else if (strcmp(*argv, "-query") == 0) { - if (mode != CMD_NONE) - goto usage; - mode = CMD_QUERY; - } else if (strcmp(*argv, "-data") == 0) { - if (argc-- < 1) - goto usage; - data = *++argv; - } else if (strcmp(*argv, "-digest") == 0) { - if (argc-- < 1) - goto usage; - digest = *++argv; - } else if (strcmp(*argv, "-rand") == 0) { - if (argc-- < 1) - goto usage; - rnd = *++argv; - } else if (strcmp(*argv, "-policy") == 0) { - if (argc-- < 1) - goto usage; - policy = *++argv; - } else if (strcmp(*argv, "-no_nonce") == 0) { + prog = opt_init(argc, argv, ts_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ts_options); + for (helpp = opt_helplist; *helpp; ++helpp) + BIO_printf(bio_err, "%s\n", *helpp); + ret = 0; + goto end; + case OPT_CONFIG: + configfile = opt_arg(); + break; + case OPT_SECTION: + section = opt_arg(); + break; + case OPT_QUERY: + case OPT_REPLY: + case OPT_VERIFY: + if (mode != OPT_ERR) + goto opthelp; + mode = o; + break; + case OPT_DATA: + data = opt_arg(); + break; + case OPT_DIGEST: + digest = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_TSPOLICY: + policy = opt_arg(); + break; + case OPT_NO_NONCE: no_nonce = 1; - } else if (strcmp(*argv, "-cert") == 0) { + break; + case OPT_CERT: cert = 1; - } else if (strcmp(*argv, "-in") == 0) { - if (argc-- < 1) - goto usage; - in = *++argv; - } else if (strcmp(*argv, "-token_in") == 0) { + break; + case OPT_IN: + in = opt_arg(); + break; + case OPT_TOKEN_IN: token_in = 1; - } else if (strcmp(*argv, "-out") == 0) { - if (argc-- < 1) - goto usage; - out = *++argv; - } else if (strcmp(*argv, "-token_out") == 0) { + break; + case OPT_OUT: + out = opt_arg(); + break; + case OPT_TOKEN_OUT: token_out = 1; - } else if (strcmp(*argv, "-text") == 0) { + break; + case OPT_TEXT: text = 1; - } else if (strcmp(*argv, "-reply") == 0) { - if (mode != CMD_NONE) - goto usage; - mode = CMD_REPLY; - } else if (strcmp(*argv, "-queryfile") == 0) { - if (argc-- < 1) - goto usage; - queryfile = *++argv; - } else if (strcmp(*argv, "-passin") == 0) { - if (argc-- < 1) - goto usage; - passin = *++argv; - } else if (strcmp(*argv, "-inkey") == 0) { - if (argc-- < 1) - goto usage; - inkey = *++argv; - } else if (strcmp(*argv, "-signer") == 0) { - if (argc-- < 1) - goto usage; - signer = *++argv; - } else if (strcmp(*argv, "-chain") == 0) { - if (argc-- < 1) - goto usage; - chain = *++argv; - } else if (strcmp(*argv, "-verify") == 0) { - if (mode != CMD_NONE) - goto usage; - mode = CMD_VERIFY; - } else if (strcmp(*argv, "-CApath") == 0) { - if (argc-- < 1) - goto usage; - ca_path = *++argv; - } else if (strcmp(*argv, "-CAfile") == 0) { - if (argc-- < 1) - goto usage; - ca_file = *++argv; - } else if (strcmp(*argv, "-untrusted") == 0) { - if (argc-- < 1) - goto usage; - untrusted = *++argv; - } else if (strcmp(*argv, "-engine") == 0) { - if (argc-- < 1) - goto usage; - engine = *++argv; - } else if ((md = EVP_get_digestbyname(*argv + 1)) != NULL) { - /* empty. */ - } else - goto usage; - } - - /* Seed the random number generator if it is going to be used. */ - if (mode == CMD_QUERY && !no_nonce) { - if (!app_RAND_load_file(NULL, bio_err, 1) && rnd == NULL) - BIO_printf(bio_err, "warning, not much extra random " - "data, consider using the -rand option\n"); - if (rnd != NULL) - BIO_printf(bio_err, "%ld semi-random bytes loaded\n", - app_RAND_load_files(rnd)); + break; + case OPT_QUERYFILE: + queryfile = opt_arg(); + break; + case OPT_PASSIN: + passin = opt_arg(); + break; + case OPT_INKEY: + inkey = opt_arg(); + break; + case OPT_SIGNER: + signer = opt_arg(); + break; + case OPT_CHAIN: + chain = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_UNTRUSTED: + untrusted = opt_arg(); + break; + case OPT_ENGINE: + engine = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &md)) + goto opthelp; + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + } } + if (mode == OPT_ERR || opt_num_rest() != 0) + goto opthelp; - /* Get the password if required. */ - if (mode == CMD_REPLY && passin && - !app_passwd(bio_err, passin, NULL, &password, NULL)) { + if (mode == OPT_REPLY && passin && + !app_passwd(passin, NULL, &password, NULL)) { BIO_printf(bio_err, "Error getting password.\n"); - goto cleanup; + goto end; } - /* - * Check consistency of parameters and execute the appropriate function. - */ - switch (mode) { - case CMD_NONE: - goto usage; - case CMD_QUERY: - /* - * Data file and message imprint cannot be specified at the same - * time. - */ - ret = data != NULL && digest != NULL; - if (ret) - goto usage; - /* Load the config file for possible policy OIDs. */ - conf = load_config_file(configfile); + conf = load_config_file(configfile); + if (configfile != default_config_file && !app_load_modules(conf)) + goto end; + + /* Check parameter consistency and execute the appropriate function. */ + if (mode == OPT_QUERY) { + if (vpmtouched) + goto opthelp; + if ((data != NULL) && (digest != NULL)) + goto opthelp; ret = !query_command(data, digest, md, policy, no_nonce, cert, in, out, text); - break; - case CMD_REPLY: - conf = load_config_file(configfile); + } else if (mode == OPT_REPLY) { + if (vpmtouched) + goto opthelp; + if ((in != NULL) && (queryfile != NULL)) + goto opthelp; if (in == NULL) { - ret = !(queryfile != NULL && conf != NULL && !token_in); - if (ret) - goto usage; - } else { - /* 'in' and 'queryfile' are exclusive. */ - ret = !(queryfile == NULL); - if (ret) - goto usage; + if ((conf == NULL) || (token_in != 0)) + goto opthelp; } - ret = !reply_command(conf, section, engine, queryfile, - password, inkey, signer, chain, policy, + password, inkey, md, signer, chain, policy, in, token_in, out, token_out, text); - break; - case CMD_VERIFY: - ret = !(((queryfile && !data && !digest) - || (!queryfile && data && !digest) - || (!queryfile && !data && digest)) - && in != NULL); - if (ret) - goto usage; + } else if (mode == OPT_VERIFY) { + if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest)) + goto opthelp; ret = !verify_command(data, digest, queryfile, in, token_in, - ca_path, ca_file, untrusted); + CApath, CAfile, untrusted, + vpmtouched ? vpm : NULL); + } else { + goto opthelp; } - goto cleanup; - - usage: - BIO_printf(bio_err, "usage:\n" - "ts -query [-rand file%cfile%c...] [-config configfile] " - "[-data file_to_hash] [-digest digest_bytes]" - "[-md2|-md4|-md5|-sha|-sha1|-mdc2|-ripemd160] " - "[-policy object_id] [-no_nonce] [-cert] " - "[-in request.tsq] [-out request.tsq] [-text]\n", - LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); - BIO_printf(bio_err, "or\n" - "ts -reply [-config configfile] [-section tsa_section] " - "[-queryfile request.tsq] [-passin password] " - "[-signer tsa_cert.pem] [-inkey private_key.pem] " - "[-chain certs_file.pem] [-policy object_id] " - "[-in response.tsr] [-token_in] " - "[-out response.tsr] [-token_out] [-text] [-engine id]\n"); - BIO_printf(bio_err, "or\n" - "ts -verify [-data file_to_hash] [-digest digest_bytes] " - "[-queryfile request.tsq] " - "-in response.tsr [-token_in] " - "-CApath ca_path -CAfile ca_file.pem " - "-untrusted cert_file.pem\n"); - cleanup: - /* Clean up. */ - app_RAND_write_file(NULL, bio_err); + end: + X509_VERIFY_PARAM_free(vpm); NCONF_free(conf); OPENSSL_free(password); - OBJ_cleanup(); - if (free_bio_err) { - BIO_free_all(bio_err); - bio_err = NULL; - } - - OPENSSL_EXIT(ret); + return ret; } /* @@ -376,7 +332,7 @@ static ASN1_OBJECT *txt2obj(const char *oid) { ASN1_OBJECT *oid_obj = NULL; - if (!(oid_obj = OBJ_txt2obj(oid, 0))) + if ((oid_obj = OBJ_txt2obj(oid, 0)) == NULL) BIO_printf(bio_err, "cannot convert %s to OID\n", oid); return oid_obj; @@ -384,24 +340,7 @@ static ASN1_OBJECT *txt2obj(const char *oid) static CONF *load_config_file(const char *configfile) { - CONF *conf = NULL; - long errorline = -1; - - if (!configfile) - configfile = getenv("OPENSSL_CONF"); - if (!configfile) - configfile = getenv("SSLEAY_CONF"); - - if (configfile && - (!(conf = NCONF_new(NULL)) || - NCONF_load(conf, configfile, &errorline) <= 0)) { - if (errorline <= 0) - BIO_printf(bio_err, "error loading the config file " - "'%s'\n", configfile); - else - BIO_printf(bio_err, "error on line %ld of config file " - "'%s'\n", errorline, configfile); - } + CONF *conf = app_load_config(configfile); if (conf != NULL) { const char *p; @@ -418,7 +357,7 @@ static CONF *load_config_file(const char *configfile) } } else ERR_clear_error(); - if (!add_oid_section(bio_err, conf)) + if (!add_oid_section(conf)) ERR_print_errors(bio_err); } return conf; @@ -427,8 +366,7 @@ static CONF *load_config_file(const char *configfile) /* * Query-related method definitions. */ - -static int query_command(const char *data, char *digest, const EVP_MD *md, +static int query_command(const char *data, const char *digest, const EVP_MD *md, const char *policy, int no_nonce, int cert, const char *in, const char *out, int text) { @@ -438,33 +376,28 @@ static int query_command(const char *data, char *digest, const EVP_MD *md, BIO *data_bio = NULL; BIO *out_bio = NULL; - /* Build query object either from file or from scratch. */ + /* Build query object. */ if (in != NULL) { - if ((in_bio = BIO_new_file(in, "rb")) == NULL) + if ((in_bio = bio_open_default(in, 'r', FORMAT_ASN1)) == NULL) goto end; query = d2i_TS_REQ_bio(in_bio, NULL); } else { - /* - * Open the file if no explicit digest bytes were specified. - */ - if (!digest && !(data_bio = BIO_open_with_default(data, "rb", stdin))) + if (digest == NULL + && (data_bio = bio_open_default(data, 'r', FORMAT_ASN1)) == NULL) goto end; - /* Creating the query object. */ query = create_query(data_bio, digest, md, policy, no_nonce, cert); - /* Saving the random number generator state. */ } if (query == NULL) goto end; - /* Write query either in ASN.1 or in text format. */ - if ((out_bio = BIO_open_with_default(out, "wb", stdout)) == NULL) - goto end; if (text) { - /* Text output. */ + if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL) + goto end; if (!TS_REQ_print_bio(out_bio, query)) goto end; } else { - /* ASN.1 output. */ + if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL) + goto end; if (!i2d_TS_REQ_bio(out_bio, query)) goto end; } @@ -473,24 +406,14 @@ static int query_command(const char *data, char *digest, const EVP_MD *md, end: ERR_print_errors(bio_err); - - /* Clean up. */ BIO_free_all(in_bio); BIO_free_all(data_bio); BIO_free_all(out_bio); TS_REQ_free(query); - return ret; } -static BIO *BIO_open_with_default(const char *file, const char *mode, - FILE *default_fp) -{ - return file == NULL ? BIO_new_fp(default_fp, BIO_NOCLOSE) - : BIO_new_file(file, mode); -} - -static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md, +static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md, const char *policy, int no_nonce, int cert) { int ret = 0; @@ -502,55 +425,39 @@ static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md, ASN1_OBJECT *policy_obj = NULL; ASN1_INTEGER *nonce_asn1 = NULL; - /* Setting default message digest. */ - if (!md && !(md = EVP_get_digestbyname("sha1"))) + if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL) goto err; - - /* Creating request object. */ - if (!(ts_req = TS_REQ_new())) + if ((ts_req = TS_REQ_new()) == NULL) goto err; - - /* Setting version. */ if (!TS_REQ_set_version(ts_req, 1)) goto err; - - /* Creating and adding MSG_IMPRINT object. */ - if (!(msg_imprint = TS_MSG_IMPRINT_new())) + if ((msg_imprint = TS_MSG_IMPRINT_new()) == NULL) goto err; - - /* Adding algorithm. */ - if (!(algo = X509_ALGOR_new())) + if ((algo = X509_ALGOR_new()) == NULL) goto err; - if (!(algo->algorithm = OBJ_nid2obj(EVP_MD_type(md)))) + if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL) goto err; - if (!(algo->parameter = ASN1_TYPE_new())) + if ((algo->parameter = ASN1_TYPE_new()) == NULL) goto err; algo->parameter->type = V_ASN1_NULL; if (!TS_MSG_IMPRINT_set_algo(msg_imprint, algo)) goto err; - - /* Adding message digest. */ if ((len = create_digest(data_bio, digest, md, &data)) == 0) goto err; if (!TS_MSG_IMPRINT_set_msg(msg_imprint, data, len)) goto err; - if (!TS_REQ_set_msg_imprint(ts_req, msg_imprint)) goto err; - - /* Setting policy if requested. */ - if (policy && !(policy_obj = txt2obj(policy))) + if (policy && (policy_obj = txt2obj(policy)) == NULL) goto err; if (policy_obj && !TS_REQ_set_policy_id(ts_req, policy_obj)) goto err; /* Setting nonce if requested. */ - if (!no_nonce && !(nonce_asn1 = create_nonce(NONCE_LENGTH))) + if (!no_nonce && (nonce_asn1 = create_nonce(NONCE_LENGTH)) == NULL) goto err; if (nonce_asn1 && !TS_REQ_set_nonce(ts_req, nonce_asn1)) goto err; - - /* Setting certificate request flag if requested. */ if (!TS_REQ_set_cert_req(ts_req, cert)) goto err; @@ -560,6 +467,7 @@ static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md, TS_REQ_free(ts_req); ts_req = NULL; BIO_printf(bio_err, "could not create query\n"); + ERR_print_errors(bio_err); } TS_MSG_IMPRINT_free(msg_imprint); X509_ALGOR_free(algo); @@ -569,45 +477,49 @@ static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md, return ts_req; } -static int create_digest(BIO *input, char *digest, const EVP_MD *md, +static int create_digest(BIO *input, const char *digest, const EVP_MD *md, unsigned char **md_value) { int md_value_len; + int rv = 0; + EVP_MD_CTX *md_ctx = NULL; md_value_len = EVP_MD_size(md); if (md_value_len < 0) - goto err; - if (input) { - /* Digest must be computed from an input file. */ - EVP_MD_CTX md_ctx; + return 0; + + if (input != NULL) { unsigned char buffer[4096]; int length; - *md_value = OPENSSL_malloc(md_value_len); - if (*md_value == 0) + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) + return 0; + *md_value = app_malloc(md_value_len, "digest buffer"); + if (!EVP_DigestInit(md_ctx, md)) goto err; - - EVP_DigestInit(&md_ctx, md); while ((length = BIO_read(input, buffer, sizeof(buffer))) > 0) { - EVP_DigestUpdate(&md_ctx, buffer, length); + if (!EVP_DigestUpdate(md_ctx, buffer, length)) + goto err; } - EVP_DigestFinal(&md_ctx, *md_value, NULL); + if (!EVP_DigestFinal(md_ctx, *md_value, NULL)) + goto err; + md_value_len = EVP_MD_size(md); } else { - /* Digest bytes are specified with digest. */ long digest_len; - *md_value = string_to_hex(digest, &digest_len); + *md_value = OPENSSL_hexstr2buf(digest, &digest_len); if (!*md_value || md_value_len != digest_len) { OPENSSL_free(*md_value); *md_value = NULL; BIO_printf(bio_err, "bad digest, %d bytes " "must be specified\n", md_value_len); - goto err; + return 0; } } - - return md_value_len; + rv = md_value_len; err: - return 0; + EVP_MD_CTX_free(md_ctx); + return rv; } static ASN1_INTEGER *create_nonce(int bits) @@ -617,24 +529,22 @@ static ASN1_INTEGER *create_nonce(int bits) int len = (bits - 1) / 8 + 1; int i; - /* Generating random byte sequence. */ if (len > (int)sizeof(buf)) goto err; if (RAND_bytes(buf, len) <= 0) goto err; /* Find the first non-zero byte and creating ASN1_INTEGER object. */ - for (i = 0; i < len && !buf[i]; ++i) ; - if (!(nonce = ASN1_INTEGER_new())) + for (i = 0; i < len && !buf[i]; ++i) + continue; + if ((nonce = ASN1_INTEGER_new()) == NULL) goto err; OPENSSL_free(nonce->data); - /* Allocate at least one byte. */ nonce->length = len - i; - if (!(nonce->data = OPENSSL_malloc(nonce->length + 1))) - goto err; + nonce->data = app_malloc(nonce->length + 1, "nonce buffer"); memcpy(nonce->data, buf + i, nonce->length); - return nonce; + err: BIO_printf(bio_err, "could not create nonce\n"); ASN1_INTEGER_free(nonce); @@ -645,11 +555,11 @@ static ASN1_INTEGER *create_nonce(int bits) * Reply-related method definitions. */ -static int reply_command(CONF *conf, char *section, char *engine, - char *queryfile, char *passin, char *inkey, - char *signer, char *chain, const char *policy, - char *in, int token_in, - char *out, int token_out, int text) +static int reply_command(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, const char *inkey, + const EVP_MD *md, const char *signer, const char *chain, + const char *policy, const char *in, int token_in, + const char *out, int token_out, int text) { int ret = 0; TS_RESP *response = NULL; @@ -659,24 +569,18 @@ static int reply_command(CONF *conf, char *section, char *engine, BIO *signer_bio = NULL; BIO *out_bio = NULL; - /* Build response object either from response or query. */ if (in != NULL) { if ((in_bio = BIO_new_file(in, "rb")) == NULL) goto end; if (token_in) { - /* - * We have a ContentInfo (PKCS7) object, add 'granted' status - * info around it. - */ response = read_PKCS7(in_bio); } else { - /* We have a ready-made TS_RESP object. */ response = d2i_TS_RESP_bio(in_bio, NULL); } } else { response = create_response(conf, section, engine, queryfile, - passin, inkey, signer, chain, policy); - if (response) + passin, inkey, md, signer, chain, policy); + if (response != NULL) BIO_printf(bio_err, "Response has been generated.\n"); else BIO_printf(bio_err, "Response is not generated.\n"); @@ -684,11 +588,10 @@ static int reply_command(CONF *conf, char *section, char *engine, if (response == NULL) goto end; - /* Write response either in ASN.1 or text format. */ - if ((out_bio = BIO_open_with_default(out, "wb", stdout)) == NULL) - goto end; + /* Write response. */ if (text) { - /* Text output. */ + if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL) + goto end; if (token_out) { TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response); if (!TS_TST_INFO_print_bio(out_bio, tst_info)) @@ -698,7 +601,8 @@ static int reply_command(CONF *conf, char *section, char *engine, goto end; } } else { - /* ASN.1 DER output. */ + if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL) + goto end; if (token_out) { PKCS7 *token = TS_RESP_get_token(response); if (!i2d_PKCS7_bio(out_bio, token)) @@ -713,15 +617,12 @@ static int reply_command(CONF *conf, char *section, char *engine, end: ERR_print_errors(bio_err); - - /* Clean up. */ BIO_free_all(in_bio); BIO_free_all(query_bio); BIO_free_all(inkey_bio); BIO_free_all(signer_bio); BIO_free_all(out_bio); TS_RESP_free(response); - return ret; } @@ -734,30 +635,23 @@ static TS_RESP *read_PKCS7(BIO *in_bio) TS_RESP *resp = NULL; TS_STATUS_INFO *si = NULL; - /* Read PKCS7 object and extract the signed time stamp info. */ - if (!(token = d2i_PKCS7_bio(in_bio, NULL))) + if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL) goto end; - if (!(tst_info = PKCS7_to_TS_TST_INFO(token))) + if ((tst_info = PKCS7_to_TS_TST_INFO(token)) == NULL) goto end; - - /* Creating response object. */ - if (!(resp = TS_RESP_new())) + if ((resp = TS_RESP_new()) == NULL) goto end; - - /* Create granted status info. */ - if (!(si = TS_STATUS_INFO_new())) + if ((si = TS_STATUS_INFO_new()) == NULL) goto end; - if (!(ASN1_INTEGER_set(si->status, TS_STATUS_GRANTED))) + if (!TS_STATUS_INFO_set_status(si, TS_STATUS_GRANTED)) goto end; if (!TS_RESP_set_status_info(resp, si)) goto end; - - /* Setting encapsulated token. */ TS_RESP_set_tst_info(resp, token, tst_info); token = NULL; /* Ownership is lost. */ tst_info = NULL; /* Ownership is lost. */ - ret = 1; + end: PKCS7_free(token); TS_TST_INFO_free(tst_info); @@ -769,84 +663,64 @@ static TS_RESP *read_PKCS7(BIO *in_bio) return resp; } -static TS_RESP *create_response(CONF *conf, const char *section, char *engine, - char *queryfile, char *passin, char *inkey, - char *signer, char *chain, const char *policy) +static TS_RESP *create_response(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, + const char *inkey, const EVP_MD *md, const char *signer, + const char *chain, const char *policy) { int ret = 0; TS_RESP *response = NULL; BIO *query_bio = NULL; TS_RESP_CTX *resp_ctx = NULL; - if (!(query_bio = BIO_new_file(queryfile, "rb"))) + if ((query_bio = BIO_new_file(queryfile, "rb")) == NULL) goto end; - - /* Getting TSA configuration section. */ - if (!(section = TS_CONF_get_tsa_section(conf, section))) + if ((section = TS_CONF_get_tsa_section(conf, section)) == NULL) goto end; - - /* Setting up response generation context. */ - if (!(resp_ctx = TS_RESP_CTX_new())) + if ((resp_ctx = TS_RESP_CTX_new()) == NULL) goto end; - - /* Setting serial number provider callback. */ if (!TS_CONF_set_serial(conf, section, serial_cb, resp_ctx)) goto end; -#ifndef OPENSSL_NO_ENGINE - /* Setting default OpenSSL engine. */ +# ifndef OPENSSL_NO_ENGINE if (!TS_CONF_set_crypto_device(conf, section, engine)) goto end; -#endif - - /* Setting TSA signer certificate. */ +# endif if (!TS_CONF_set_signer_cert(conf, section, signer, resp_ctx)) goto end; - - /* Setting TSA signer certificate chain. */ if (!TS_CONF_set_certs(conf, section, chain, resp_ctx)) goto end; - - /* Setting TSA signer private key. */ if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx)) goto end; - /* Setting default policy OID. */ + if (md) { + if (!TS_RESP_CTX_set_signer_digest(resp_ctx, md)) + goto end; + } else if (!TS_CONF_set_signer_digest(conf, section, NULL, resp_ctx)) { + goto end; + } + + if (!TS_CONF_set_ess_cert_id_digest(conf, section, resp_ctx)) + goto end; if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx)) goto end; - - /* Setting acceptable policy OIDs. */ if (!TS_CONF_set_policies(conf, section, resp_ctx)) goto end; - - /* Setting the acceptable one-way hash algorithms. */ if (!TS_CONF_set_digests(conf, section, resp_ctx)) goto end; - - /* Setting guaranteed time stamp accuracy. */ if (!TS_CONF_set_accuracy(conf, section, resp_ctx)) goto end; - - /* Setting the precision of the time. */ if (!TS_CONF_set_clock_precision_digits(conf, section, resp_ctx)) goto end; - - /* Setting the ordering flaf if requested. */ if (!TS_CONF_set_ordering(conf, section, resp_ctx)) goto end; - - /* Setting the TSA name required flag if requested. */ if (!TS_CONF_set_tsa_name(conf, section, resp_ctx)) goto end; - - /* Setting the ESS cert id chain flag if requested. */ if (!TS_CONF_set_ess_cert_id_chain(conf, section, resp_ctx)) goto end; - - /* Creating the response. */ - if (!(response = TS_RESP_create_response(resp_ctx, query_bio))) + if ((response = TS_RESP_create_response(resp_ctx, query_bio)) == NULL) goto end; - ret = 1; + end: if (!ret) { TS_RESP_free(response); @@ -854,22 +728,22 @@ static TS_RESP *create_response(CONF *conf, const char *section, char *engine, } TS_RESP_CTX_free(resp_ctx); BIO_free_all(query_bio); - return response; } -static ASN1_INTEGER *MS_CALLBACK serial_cb(TS_RESP_CTX *ctx, void *data) +static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data) { const char *serial_file = (const char *)data; ASN1_INTEGER *serial = next_serial(serial_file); - if (!serial) { + if (serial == NULL) { TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, "Error during serial number " "generation."); TS_RESP_CTX_add_failure_info(ctx, TS_INFO_ADD_INFO_NOT_AVAILABLE); - } else + } else { save_ts_serial(serial_file, serial); + } return serial; } @@ -881,10 +755,10 @@ static ASN1_INTEGER *next_serial(const char *serialfile) ASN1_INTEGER *serial = NULL; BIGNUM *bn = NULL; - if (!(serial = ASN1_INTEGER_new())) + if ((serial = ASN1_INTEGER_new()) == NULL) goto err; - if (!(in = BIO_new_file(serialfile, "r"))) { + if ((in = BIO_new_file(serialfile, "r")) == NULL) { ERR_clear_error(); BIO_printf(bio_err, "Warning: could not open file %s for " "reading, using serial number: 1\n", serialfile); @@ -897,16 +771,17 @@ static ASN1_INTEGER *next_serial(const char *serialfile) serialfile); goto err; } - if (!(bn = ASN1_INTEGER_to_BN(serial, NULL))) + if ((bn = ASN1_INTEGER_to_BN(serial, NULL)) == NULL) goto err; ASN1_INTEGER_free(serial); serial = NULL; if (!BN_add_word(bn, 1)) goto err; - if (!(serial = BN_to_ASN1_INTEGER(bn, NULL))) + if ((serial = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) goto err; } ret = 1; + err: if (!ret) { ASN1_INTEGER_free(serial); @@ -922,7 +797,7 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial) int ret = 0; BIO *out = NULL; - if (!(out = BIO_new_file(serialfile, "w"))) + if ((out = BIO_new_file(serialfile, "w")) == NULL) goto err; if (i2a_ASN1_INTEGER(out, serial) <= 0) goto err; @@ -937,13 +812,15 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial) return ret; } + /* * Verify-related method definitions. */ -static int verify_command(char *data, char *digest, char *queryfile, - char *in, int token_in, - char *ca_path, char *ca_file, char *untrusted) +static int verify_command(const char *data, const char *digest, const char *queryfile, + const char *in, int token_in, + const char *CApath, const char *CAfile, const char *untrusted, + X509_VERIFY_PARAM *vpm) { BIO *in_bio = NULL; PKCS7 *token = NULL; @@ -951,25 +828,24 @@ static int verify_command(char *data, char *digest, char *queryfile, TS_VERIFY_CTX *verify_ctx = NULL; int ret = 0; - /* Decode the token (PKCS7) or response (TS_RESP) files. */ - if (!(in_bio = BIO_new_file(in, "rb"))) + if ((in_bio = BIO_new_file(in, "rb")) == NULL) goto end; if (token_in) { - if (!(token = d2i_PKCS7_bio(in_bio, NULL))) + if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL) goto end; } else { - if (!(response = d2i_TS_RESP_bio(in_bio, NULL))) + if ((response = d2i_TS_RESP_bio(in_bio, NULL)) == NULL) goto end; } - if (!(verify_ctx = create_verify_ctx(data, digest, queryfile, - ca_path, ca_file, untrusted))) + if ((verify_ctx = create_verify_ctx(data, digest, queryfile, + CApath, CAfile, untrusted, + vpm)) == NULL) goto end; - /* Checking the token or response against the request. */ - ret = token_in ? - TS_RESP_verify_token(verify_ctx, token) : - TS_RESP_verify_response(verify_ctx, response); + ret = token_in + ? TS_RESP_verify_token(verify_ctx, token) + : TS_RESP_verify_response(verify_ctx, response); end: printf("Verification: "); @@ -977,11 +853,9 @@ static int verify_command(char *data, char *digest, char *queryfile, printf("OK\n"); else { printf("FAILED\n"); - /* Print errors, if there are any. */ ERR_print_errors(bio_err); } - /* Clean up. */ BIO_free_all(in_bio); PKCS7_free(token); TS_RESP_free(response); @@ -989,60 +863,67 @@ static int verify_command(char *data, char *digest, char *queryfile, return ret; } -static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, - char *queryfile, - char *ca_path, char *ca_file, - char *untrusted) +static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, + const char *queryfile, + const char *CApath, const char *CAfile, + const char *untrusted, + X509_VERIFY_PARAM *vpm) { TS_VERIFY_CTX *ctx = NULL; BIO *input = NULL; TS_REQ *request = NULL; int ret = 0; + int f = 0; if (data != NULL || digest != NULL) { - if (!(ctx = TS_VERIFY_CTX_new())) + if ((ctx = TS_VERIFY_CTX_new()) == NULL) goto err; - ctx->flags = TS_VFY_VERSION | TS_VFY_SIGNER; + f = TS_VFY_VERSION | TS_VFY_SIGNER; if (data != NULL) { - ctx->flags |= TS_VFY_DATA; - if (!(ctx->data = BIO_new_file(data, "rb"))) + BIO *out = NULL; + + f |= TS_VFY_DATA; + if ((out = BIO_new_file(data, "rb")) == NULL) goto err; + if (TS_VERIFY_CTX_set_data(ctx, out) == NULL) { + BIO_free_all(out); + goto err; + } } else if (digest != NULL) { long imprint_len; - ctx->flags |= TS_VFY_IMPRINT; - if (!(ctx->imprint = string_to_hex(digest, &imprint_len))) { + unsigned char *hexstr = OPENSSL_hexstr2buf(digest, &imprint_len); + f |= TS_VFY_IMPRINT; + if (TS_VERIFY_CTX_set_imprint(ctx, hexstr, imprint_len) == NULL) { BIO_printf(bio_err, "invalid digest string\n"); goto err; } - ctx->imprint_len = imprint_len; } } else if (queryfile != NULL) { - /* - * The request has just to be read, decoded and converted to a verify - * context object. - */ - if (!(input = BIO_new_file(queryfile, "rb"))) + if ((input = BIO_new_file(queryfile, "rb")) == NULL) goto err; - if (!(request = d2i_TS_REQ_bio(input, NULL))) + if ((request = d2i_TS_REQ_bio(input, NULL)) == NULL) goto err; - if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL))) + if ((ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL)) == NULL) goto err; - } else + } else { return NULL; + } /* Add the signature verification flag and arguments. */ - ctx->flags |= TS_VFY_SIGNATURE; + TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE); /* Initialising the X509_STORE object. */ - if (!(ctx->store = create_cert_store(ca_path, ca_file))) + if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile, vpm)) + == NULL) goto err; /* Loading untrusted certificates. */ - if (untrusted && !(ctx->certs = TS_CONF_load_certs(untrusted))) + if (untrusted + && TS_VERIFY_CTS_set_certs(ctx, TS_CONF_load_certs(untrusted)) == NULL) goto err; - ret = 1; + err: if (!ret) { TS_VERIFY_CTX_free(ctx); @@ -1053,67 +934,53 @@ static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, return ctx; } -static X509_STORE *create_cert_store(char *ca_path, char *ca_file) +static X509_STORE *create_cert_store(const char *CApath, const char *CAfile, + X509_VERIFY_PARAM *vpm) { X509_STORE *cert_ctx = NULL; X509_LOOKUP *lookup = NULL; int i; - /* Creating the X509_STORE object. */ cert_ctx = X509_STORE_new(); - - /* Setting the callback for certificate chain verification. */ X509_STORE_set_verify_cb(cert_ctx, verify_cb); - - /* Adding a trusted certificate directory source. */ - if (ca_path) { + if (CApath != NULL) { lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) { BIO_printf(bio_err, "memory allocation failure\n"); goto err; } - i = X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM); + i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); if (!i) { - BIO_printf(bio_err, "Error loading directory %s\n", ca_path); + BIO_printf(bio_err, "Error loading directory %s\n", CApath); goto err; } } - /* Adding a trusted certificate file source. */ - if (ca_file) { + if (CAfile != NULL) { lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); if (lookup == NULL) { BIO_printf(bio_err, "memory allocation failure\n"); goto err; } - i = X509_LOOKUP_load_file(lookup, ca_file, X509_FILETYPE_PEM); + i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); if (!i) { - BIO_printf(bio_err, "Error loading file %s\n", ca_file); + BIO_printf(bio_err, "Error loading file %s\n", CAfile); goto err; } } + if (vpm != NULL) + X509_STORE_set1_param(cert_ctx, vpm); + return cert_ctx; + err: X509_STORE_free(cert_ctx); return NULL; } -static int MS_CALLBACK verify_cb(int ok, X509_STORE_CTX *ctx) +static int verify_cb(int ok, X509_STORE_CTX *ctx) { - /*- - char buf[256]; - - if (!ok) - { - X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), - buf, sizeof(buf)); - printf("%s\n", buf); - printf("error %d at %d depth lookup: %s\n", - ctx->error, ctx->error_depth, - X509_verify_cert_error_string(ctx->error)); - } - */ - return ok; } +#endif /* ndef OPENSSL_NO_TS */ diff --git a/apps/tsget b/apps/tsget.in index 0fca99f4385a..bec365e28ce5 100644 --- a/apps/tsget +++ b/apps/tsget.in @@ -1,7 +1,11 @@ -#!/usr/bin/perl -w -# Written by Zoltan Glozik <zglozik@stones.com>. -# Copyright (c) 2002 The OpenTSA Project. All rights reserved. -$::version = '$Id: tsget,v 1.1.2.2 2009/09/07 17:57:02 steve Exp $'; +#!{- $config{HASHBANGPERL} -} +# Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2002 The OpenTSA Project. All rights reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html use strict; use IO::Handle; @@ -42,7 +46,8 @@ sub create_curl { # Error-handling related options. $curl->setopt(CURLOPT_VERBOSE, 1) if $options{d}; $curl->setopt(CURLOPT_FAILONERROR, 1); - $curl->setopt(CURLOPT_USERAGENT, "OpenTSA tsget.pl/" . (split / /, $::version)[2]); + $curl->setopt(CURLOPT_USERAGENT, + "OpenTSA tsget.pl/openssl-{- $config{version} -}"); # Options for POST method. $curl->setopt(CURLOPT_UPLOAD, 1); diff --git a/apps/verify.c b/apps/verify.c index c4bd1975764c..38377a57e4a9 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -1,331 +1,301 @@ -/* apps/verify.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/x509.h> #include <openssl/x509v3.h> #include <openssl/pem.h> -#undef PROG -#define PROG verify_main - -static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx); -static int check(X509_STORE *ctx, char *file, +static int cb(int ok, X509_STORE_CTX *ctx); +static int check(X509_STORE *ctx, const char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, - STACK_OF(X509_CRL) *crls, ENGINE *e); + STACK_OF(X509_CRL) *crls, int show_chain); static int v_verbose = 0, vflags = 0; -int MAIN(int, char **); +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, + OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN, + OPT_V_ENUM, OPT_NAMEOPT, + OPT_VERBOSE +} OPTION_CHOICE; + +const OPTIONS verify_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"verbose", OPT_VERBOSE, '-', + "Print extra information about the operations being performed."}, + {"CApath", OPT_CAPATH, '/', "A directory of trusted certificates"}, + {"CAfile", OPT_CAFILE, '<', "A file of trusted certificates"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"untrusted", OPT_UNTRUSTED, '<', "A file of untrusted certificates"}, + {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"}, + {"CRLfile", OPT_CRLFILE, '<', + "File containing one or more CRL's (in PEM format) to load"}, + {"crl_download", OPT_CRL_DOWNLOAD, '-', + "Attempt to download CRL information for this certificate"}, + {"show_chain", OPT_SHOW_CHAIN, '-', + "Display information about the certificate chain"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + OPT_V_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; -int MAIN(int argc, char **argv) +int verify_main(int argc, char **argv) { ENGINE *e = NULL; - int i, ret = 1, badarg = 0; - char *CApath = NULL, *CAfile = NULL; - char *untfile = NULL, *trustfile = NULL, *crlfile = NULL; STACK_OF(X509) *untrusted = NULL, *trusted = NULL; STACK_OF(X509_CRL) *crls = NULL; - X509_STORE *cert_ctx = NULL; - X509_LOOKUP *lookup = NULL; + X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; - int crl_download = 0; - char *engine = NULL; + const char *prog, *CApath = NULL, *CAfile = NULL; + int noCApath = 0, noCAfile = 0; + int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1; + OPTION_CHOICE o; - cert_ctx = X509_STORE_new(); - if (cert_ctx == NULL) + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) goto end; - X509_STORE_set_verify_cb(cert_ctx, cb); - ERR_load_crypto_strings(); - - apps_startup(); - - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - if (!load_config(bio_err, NULL)) - goto end; + prog = opt_init(argc, argv, verify_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(verify_options); + BIO_printf(bio_err, "Recognized usages:\n"); + for (i = 0; i < X509_PURPOSE_get_count(); i++) { + X509_PURPOSE *ptmp; + ptmp = X509_PURPOSE_get0(i); + BIO_printf(bio_err, "\t%-10s\t%s\n", + X509_PURPOSE_get0_sname(ptmp), + X509_PURPOSE_get0_name(ptmp)); + } - argc--; - argv++; - for (;;) { - if (argc >= 1) { - if (strcmp(*argv, "-CApath") == 0) { - if (argc-- < 1) - goto usage; - CApath = *(++argv); - } else if (strcmp(*argv, "-CAfile") == 0) { - if (argc-- < 1) - goto usage; - CAfile = *(++argv); - } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { - if (badarg) - goto usage; - continue; - } else if (strcmp(*argv, "-untrusted") == 0) { - if (argc-- < 1) - goto usage; - untfile = *(++argv); - } else if (strcmp(*argv, "-trusted") == 0) { - if (argc-- < 1) - goto usage; - trustfile = *(++argv); - } else if (strcmp(*argv, "-CRLfile") == 0) { - if (argc-- < 1) - goto usage; - crlfile = *(++argv); - } else if (strcmp(*argv, "-crl_download") == 0) - crl_download = 1; -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto usage; - engine = *(++argv); + BIO_printf(bio_err, "Recognized verify names:\n"); + for (i = 0; i < X509_VERIFY_PARAM_get_count(); i++) { + const X509_VERIFY_PARAM *vptmp; + vptmp = X509_VERIFY_PARAM_get0(i); + BIO_printf(bio_err, "\t%-10s\n", + X509_VERIFY_PARAM_get0_name(vptmp)); } -#endif - else if (strcmp(*argv, "-help") == 0) - goto usage; - else if (strcmp(*argv, "-verbose") == 0) - v_verbose = 1; - else if (argv[0][0] == '-') - goto usage; - else - break; - argc--; - argv++; - } else + ret = 0; + goto end; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_UNTRUSTED: + /* Zero or more times */ + if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL, + "untrusted certificates")) + goto end; + break; + case OPT_TRUSTED: + /* Zero or more times */ + noCAfile = 1; + noCApath = 1; + if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL, + "trusted certificates")) + goto end; + break; + case OPT_CRLFILE: + /* Zero or more times */ + if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL, + "other CRLs")) + goto end; + break; + case OPT_CRL_DOWNLOAD: + crl_download = 1; + break; + case OPT_ENGINE: + if ((e = setup_engine(opt_arg(), 0)) == NULL) { + /* Failure message already displayed */ + goto end; + } + break; + case OPT_SHOW_CHAIN: + show_chain = 1; + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_VERBOSE: + v_verbose = 1; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + if (trusted != NULL && (CAfile || CApath)) { + BIO_printf(bio_err, + "%s: Cannot use -trusted with -CAfile or -CApath\n", + prog); + goto end; } - e = setup_engine(bio_err, engine, 0); - - if (vpm) - X509_STORE_set1_param(cert_ctx, vpm); - - lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); - if (lookup == NULL) - abort(); - if (CAfile) { - i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); - if (!i) { - BIO_printf(bio_err, "Error loading file %s\n", CAfile); - ERR_print_errors(bio_err); - goto end; - } - } else - X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + goto end; + X509_STORE_set_verify_cb(store, cb); - lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); - if (lookup == NULL) - abort(); - if (CApath) { - i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); - if (!i) { - BIO_printf(bio_err, "Error loading directory %s\n", CApath); - ERR_print_errors(bio_err); - goto end; - } - } else - X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + if (vpmtouched) + X509_STORE_set1_param(store, vpm); ERR_clear_error(); - if (untfile) { - untrusted = load_certs(bio_err, untfile, FORMAT_PEM, - NULL, e, "untrusted certificates"); - if (!untrusted) - goto end; - } - - if (trustfile) { - trusted = load_certs(bio_err, trustfile, FORMAT_PEM, - NULL, e, "trusted certificates"); - if (!trusted) - goto end; - } - - if (crlfile) { - crls = load_crls(bio_err, crlfile, FORMAT_PEM, NULL, e, "other CRLs"); - if (!crls) - goto end; - } + if (crl_download) + store_setup_crl_download(store); ret = 0; - - if (crl_download) - store_setup_crl_download(cert_ctx); if (argc < 1) { - if (1 != check(cert_ctx, NULL, untrusted, trusted, crls, e)) + if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1) ret = -1; } else { for (i = 0; i < argc; i++) - if (1 != check(cert_ctx, argv[i], untrusted, trusted, crls, e)) + if (check(store, argv[i], untrusted, trusted, crls, + show_chain) != 1) ret = -1; } - usage: - if (ret == 1) { - BIO_printf(bio_err, - "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]"); - BIO_printf(bio_err, " [-no_alt_chains] [-attime timestamp]"); -#ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, " [-engine e]"); -#endif - BIO_printf(bio_err, " cert1 cert2 ...\n"); - - BIO_printf(bio_err, "recognized usages:\n"); - for (i = 0; i < X509_PURPOSE_get_count(); i++) { - X509_PURPOSE *ptmp; - ptmp = X509_PURPOSE_get0(i); - BIO_printf(bio_err, "\t%-10s\t%s\n", - X509_PURPOSE_get0_sname(ptmp), - X509_PURPOSE_get0_name(ptmp)); - } - } end: - if (vpm) - X509_VERIFY_PARAM_free(vpm); - if (cert_ctx != NULL) - X509_STORE_free(cert_ctx); + X509_VERIFY_PARAM_free(vpm); + X509_STORE_free(store); sk_X509_pop_free(untrusted, X509_free); sk_X509_pop_free(trusted, X509_free); sk_X509_CRL_pop_free(crls, X509_CRL_free); release_engine(e); - apps_shutdown(); - OPENSSL_EXIT(ret < 0 ? 2 : ret); + return (ret < 0 ? 2 : ret); } -static int check(X509_STORE *ctx, char *file, +static int check(X509_STORE *ctx, const char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, - STACK_OF(X509_CRL) *crls, ENGINE *e) + STACK_OF(X509_CRL) *crls, int show_chain) { X509 *x = NULL; int i = 0, ret = 0; X509_STORE_CTX *csc; + STACK_OF(X509) *chain = NULL; + int num_untrusted; - x = load_cert(bio_err, file, FORMAT_PEM, NULL, e, "certificate file"); + x = load_cert(file, FORMAT_PEM, "certificate file"); if (x == NULL) goto end; - fprintf(stdout, "%s: ", (file == NULL) ? "stdin" : file); csc = X509_STORE_CTX_new(); if (csc == NULL) { - ERR_print_errors(bio_err); + printf("error %s: X.509 store context allocation failed\n", + (file == NULL) ? "stdin" : file); goto end; } + X509_STORE_set_flags(ctx, vflags); if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) { - ERR_print_errors(bio_err); + X509_STORE_CTX_free(csc); + printf("error %s: X.509 store context initialization failed\n", + (file == NULL) ? "stdin" : file); goto end; } - if (tchain) - X509_STORE_CTX_trusted_stack(csc, tchain); - if (crls) + if (tchain != NULL) + X509_STORE_CTX_set0_trusted_stack(csc, tchain); + if (crls != NULL) X509_STORE_CTX_set0_crls(csc, crls); i = X509_verify_cert(csc); + if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) { + printf("%s: OK\n", (file == NULL) ? "stdin" : file); + ret = 1; + if (show_chain) { + int j; + + chain = X509_STORE_CTX_get1_chain(csc); + num_untrusted = X509_STORE_CTX_get_num_untrusted(csc); + printf("Chain:\n"); + for (j = 0; j < sk_X509_num(chain); j++) { + X509 *cert = sk_X509_value(chain, j); + printf("depth=%d: ", j); + X509_NAME_print_ex_fp(stdout, + X509_get_subject_name(cert), + 0, get_nameopt()); + if (j < num_untrusted) + printf(" (untrusted)"); + printf("\n"); + } + sk_X509_pop_free(chain, X509_free); + } + } else { + printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file); + } X509_STORE_CTX_free(csc); - ret = 0; end: - if (i > 0) { - fprintf(stdout, "OK\n"); - ret = 1; - } else + if (i <= 0) ERR_print_errors(bio_err); - if (x != NULL) - X509_free(x); + X509_free(x); - return (ret); + return ret; } -static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) +static int cb(int ok, X509_STORE_CTX *ctx) { int cert_error = X509_STORE_CTX_get_error(ctx); X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); if (!ok) { - if (current_cert) { - X509_NAME_print_ex_fp(stdout, - X509_get_subject_name(current_cert), - 0, XN_FLAG_ONELINE); - printf("\n"); + if (current_cert != NULL) { + X509_NAME_print_ex(bio_err, + X509_get_subject_name(current_cert), + 0, get_nameopt()); + BIO_printf(bio_err, "\n"); } - printf("%serror %d at %d depth lookup:%s\n", - X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "", + BIO_printf(bio_err, "%serror %d at %d depth lookup: %s\n", + X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path] " : "", cert_error, X509_STORE_CTX_get_error_depth(ctx), X509_verify_cert_error_string(cert_error)); switch (cert_error) { case X509_V_ERR_NO_EXPLICIT_POLICY: - policies_print(NULL, ctx); + policies_print(ctx); + /* fall thru */ case X509_V_ERR_CERT_HAS_EXPIRED: /* * since we are just checking the certificates, it is ok if they * are self signed. But we should still warn the user. */ - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: /* Continue after extension errors too */ case X509_V_ERR_INVALID_CA: @@ -336,15 +306,14 @@ static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: ok = 1; - } return ok; } if (cert_error == X509_V_OK && ok == 2) - policies_print(NULL, ctx); + policies_print(ctx); if (!v_verbose) ERR_clear_error(); - return (ok); + return ok; } diff --git a/apps/version.c b/apps/version.c index 8807d4c7b009..2aca1636152b 100644 --- a/apps/version.c +++ b/apps/version.c @@ -1,118 +1,17 @@ -/* apps/version.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "apps.h" +#include "progs.h" #include <openssl/evp.h> #include <openssl/crypto.h> #include <openssl/bn.h> @@ -132,58 +31,103 @@ # include <openssl/blowfish.h> #endif -#undef PROG -#define PROG version_main +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS version_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"a", OPT_A, '-', "Show all data"}, + {"b", OPT_B, '-', "Show build date"}, + {"d", OPT_D, '-', "Show configuration directory"}, + {"e", OPT_E, '-', "Show engines directory"}, + {"f", OPT_F, '-', "Show compiler flags used"}, + {"o", OPT_O, '-', "Show some internal datatype options"}, + {"p", OPT_P, '-', "Show target build platform"}, + {"r", OPT_R, '-', "Show random seeding options"}, + {"v", OPT_V, '-', "Show library version"}, + {NULL} +}; -int MAIN(int argc, char **argv) +#if defined(OPENSSL_RAND_SEED_DEVRANDOM) || defined(OPENSSL_RAND_SEED_EGD) +static void printlist(const char *prefix, const char **dev) { - int i, ret = 0; - int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0; - - apps_startup(); + printf("%s (", prefix); + for ( ; *dev != NULL; dev++) + printf(" \"%s\"", *dev); + printf(" )"); +} +#endif - if (bio_err == NULL) - if ((bio_err = BIO_new(BIO_s_file())) != NULL) - BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); +int version_main(int argc, char **argv) +{ + int ret = 1, dirty = 0, seed = 0; + int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0; + int engdir = 0; + char *prog; + OPTION_CHOICE o; - if (argc == 1) - version = 1; - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-v") == 0) - version = 1; - else if (strcmp(argv[i], "-b") == 0) - date = 1; - else if (strcmp(argv[i], "-f") == 0) - cflags = 1; - else if (strcmp(argv[i], "-o") == 0) - options = 1; - else if (strcmp(argv[i], "-p") == 0) - platform = 1; - else if (strcmp(argv[i], "-d") == 0) - dir = 1; - else if (strcmp(argv[i], "-a") == 0) - date = version = cflags = options = platform = dir = 1; - else { - BIO_printf(bio_err, "usage:version -[avbofpd]\n"); - ret = 1; + prog = opt_init(argc, argv, version_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; + case OPT_HELP: + opt_help(version_options); + ret = 0; + goto end; + case OPT_B: + dirty = date = 1; + break; + case OPT_D: + dirty = dir = 1; + break; + case OPT_E: + dirty = engdir = 1; + break; + case OPT_F: + dirty = cflags = 1; + break; + case OPT_O: + dirty = options = 1; + break; + case OPT_P: + dirty = platform = 1; + break; + case OPT_R: + dirty = seed = 1; + break; + case OPT_V: + dirty = version = 1; + break; + case OPT_A: + seed = options = cflags = version = date = platform = dir = engdir + = 1; + break; } } + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Extra parameters given.\n"); + goto opthelp; + } + if (!dirty) + version = 1; if (version) { - if (SSLeay() == SSLEAY_VERSION_NUMBER) { - printf("%s\n", SSLeay_version(SSLEAY_VERSION)); - } else { + if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER) + printf("%s\n", OpenSSL_version(OPENSSL_VERSION)); + else printf("%s (Library: %s)\n", - OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); - } + OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION)); } if (date) - printf("%s\n", SSLeay_version(SSLEAY_BUILT_ON)); + printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON)); if (platform) - printf("%s\n", SSLeay_version(SSLEAY_PLATFORM)); + printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM)); if (options) { printf("options: "); printf("%s ", BN_options()); @@ -197,7 +141,7 @@ int MAIN(int argc, char **argv) printf("%s ", DES_options()); #endif #ifndef OPENSSL_NO_IDEA - printf("%s ", idea_options()); + printf("%s ", IDEA_options()); #endif #ifndef OPENSSL_NO_BF printf("%s ", BF_options()); @@ -205,10 +149,46 @@ int MAIN(int argc, char **argv) printf("\n"); } if (cflags) - printf("%s\n", SSLeay_version(SSLEAY_CFLAGS)); + printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS)); if (dir) - printf("%s\n", SSLeay_version(SSLEAY_DIR)); + printf("%s\n", OpenSSL_version(OPENSSL_DIR)); + if (engdir) + printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR)); + if (seed) { + printf("Seeding source:"); +#ifdef OPENSSL_RAND_SEED_RTDSC + printf(" rtdsc"); +#endif +#ifdef OPENSSL_RAND_SEED_RDCPU + printf(" rdrand ( rdseed rdrand )"); +#endif +#ifdef OPENSSL_RAND_SEED_LIBRANDOM + printf(" C-library-random"); +#endif +#ifdef OPENSSL_RAND_SEED_GETRANDOM + printf(" getrandom-syscall"); +#endif +#ifdef OPENSSL_RAND_SEED_DEVRANDOM + { + static const char *dev[] = { DEVRANDOM, NULL }; + printlist(" random-device", dev); + } +#endif +#ifdef OPENSSL_RAND_SEED_EGD + { + static const char *dev[] = { DEVRANDOM_EGD, NULL }; + printlist(" EGD", dev); + } +#endif +#ifdef OPENSSL_RAND_SEED_NONE + printf(" none"); +#endif +#ifdef OPENSSL_RAND_SEED_OS + printf(" os-specific"); +#endif + printf("\n"); + } + ret = 0; end: - apps_shutdown(); - OPENSSL_EXIT(ret); + return ret; } diff --git a/apps/x509.c b/apps/x509.c index add74d556d68..d40960c0b93f 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -1,69 +1,17 @@ -/* apps/x509.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#ifdef OPENSSL_NO_STDIO -# define APPS_WIN16 -#endif #include "apps.h" +#include "progs.h" #include <openssl/bio.h> #include <openssl/asn1.h> #include <openssl/err.h> @@ -80,433 +28,446 @@ # include <openssl/dsa.h> #endif -#undef PROG -#define PROG x509_main - #undef POSTFIX #define POSTFIX ".srl" #define DEF_DAYS 30 -static const char *x509_usage[] = { - "usage: x509 args\n", - " -inform arg - input format - default PEM (one of DER, NET or PEM)\n", - " -outform arg - output format - default PEM (one of DER, NET or PEM)\n", - " -keyform arg - private key format - default PEM\n", - " -CAform arg - CA format - default PEM\n", - " -CAkeyform arg - CA key format - default PEM\n", - " -in arg - input file - default stdin\n", - " -out arg - output file - default stdout\n", - " -passin arg - private key password source\n", - " -serial - print serial number value\n", - " -subject_hash - print subject hash value\n", -#ifndef OPENSSL_NO_MD5 - " -subject_hash_old - print old-style (MD5) subject hash value\n", -#endif - " -issuer_hash - print issuer hash value\n", -#ifndef OPENSSL_NO_MD5 - " -issuer_hash_old - print old-style (MD5) issuer hash value\n", -#endif - " -hash - synonym for -subject_hash\n", - " -subject - print subject DN\n", - " -issuer - print issuer DN\n", - " -email - print email address(es)\n", - " -startdate - notBefore field\n", - " -enddate - notAfter field\n", - " -purpose - print out certificate purposes\n", - " -dates - both Before and After dates\n", - " -modulus - print the RSA key modulus\n", - " -pubkey - output the public key\n", - " -fingerprint - print the certificate fingerprint\n", - " -alias - output certificate alias\n", - " -noout - no certificate output\n", - " -ocspid - print OCSP hash values for the subject name and public key\n", - " -ocsp_uri - print OCSP Responder URL(s)\n", - " -trustout - output a \"trusted\" certificate\n", - " -clrtrust - clear all trusted purposes\n", - " -clrreject - clear all rejected purposes\n", - " -addtrust arg - trust certificate for a given purpose\n", - " -addreject arg - reject certificate for a given purpose\n", - " -setalias arg - set certificate alias\n", - " -days arg - How long till expiry of a signed certificate - def 30 days\n", - " -checkend arg - check whether the cert expires in the next arg seconds\n", - " exit 1 if so, 0 if not\n", - " -signkey arg - self sign cert with arg\n", - " -x509toreq - output a certification request object\n", - " -req - input is a certificate request, sign and output.\n", - " -CA arg - set the CA certificate, must be PEM format.\n", - " -CAkey arg - set the CA key, must be PEM format\n", - " missing, it is assumed to be in the CA file.\n", - " -CAcreateserial - create serial number file if it does not exist\n", - " -CAserial arg - serial file\n", - " -set_serial - serial number to use\n", - " -text - print the certificate in text form\n", - " -C - print out C code forms\n", - " -md2/-md5/-sha1/-mdc2 - digest to use\n", - " -extfile - configuration file with X509V3 extensions to add\n", - " -extensions - section from config file with X509V3 extensions to add\n", - " -clrext - delete extensions before signing and input certificate\n", - " -nameopt arg - various certificate name options\n", -#ifndef OPENSSL_NO_ENGINE - " -engine e - use engine e, possibly a hardware device.\n", -#endif - " -certopt arg - various certificate text options\n", - " -checkhost host - check certificate matches \"host\"\n", - " -checkemail email - check certificate matches \"email\"\n", - " -checkip ipaddr - check certificate matches \"ipaddr\"\n", - NULL -}; - -static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx); +static int callb(int ok, X509_STORE_CTX *ctx); static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, - const EVP_MD *digest, CONF *conf, char *section); -static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, + const EVP_MD *digest, CONF *conf, const char *section, + int preserve_dates); +static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, X509 *x, X509 *xca, EVP_PKEY *pkey, - STACK_OF(OPENSSL_STRING) *sigopts, char *serial, + STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile, int create, int days, int clrext, CONF *conf, - char *section, ASN1_INTEGER *sno); + const char *section, ASN1_INTEGER *sno, int reqfile, + int preserve_dates); static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); -static int reqfile = 0; -#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL -static int force_version = 2; -#endif +static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, + OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, + OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, + OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY, + OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT, + OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, + OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, + OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES, + OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST, + OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST, + OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID, + OPT_SUBJECT_HASH_OLD, + OPT_ISSUER_HASH_OLD, + OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES, + OPT_R_ENUM, OPT_EXT +} OPTION_CHOICE; -int MAIN(int, char **); +const OPTIONS x509_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', + "Input format - default PEM (one of DER, NET or PEM)"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"outform", OPT_OUTFORM, 'f', + "Output format - default PEM (one of DER, NET or PEM)"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"keyform", OPT_KEYFORM, 'F', "Private key format - default PEM"}, + {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"}, + {"serial", OPT_SERIAL, '-', "Print serial number value"}, + {"subject_hash", OPT_HASH, '-', "Print subject hash value"}, + {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"}, + {"hash", OPT_HASH, '-', "Synonym for -subject_hash"}, + {"subject", OPT_SUBJECT, '-', "Print subject DN"}, + {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, + {"email", OPT_EMAIL, '-', "Print email address(es)"}, + {"startdate", OPT_STARTDATE, '-', "Set notBefore field"}, + {"enddate", OPT_ENDDATE, '-', "Set notAfter field"}, + {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"}, + {"dates", OPT_DATES, '-', "Both Before and After dates"}, + {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, + {"pubkey", OPT_PUBKEY, '-', "Output the public key"}, + {"fingerprint", OPT_FINGERPRINT, '-', + "Print the certificate fingerprint"}, + {"alias", OPT_ALIAS, '-', "Output certificate alias"}, + {"noout", OPT_NOOUT, '-', "No output, just status"}, + {"nocert", OPT_NOCERT, '-', "No certificate output"}, + {"ocspid", OPT_OCSPID, '-', + "Print OCSP hash values for the subject name and public key"}, + {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"}, + {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"}, + {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"}, + {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"}, + {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"}, + {"addreject", OPT_ADDREJECT, 's', + "Reject certificate for a given purpose"}, + {"setalias", OPT_SETALIAS, 's', "Set certificate alias"}, + {"days", OPT_DAYS, 'n', + "How long till expiry of a signed certificate - def 30 days"}, + {"checkend", OPT_CHECKEND, 'M', + "Check whether the cert expires in the next arg seconds"}, + {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"}, + {"signkey", OPT_SIGNKEY, '<', "Self sign cert with arg"}, + {"x509toreq", OPT_X509TOREQ, '-', + "Output a certification request object"}, + {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"}, + {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"}, + {"CAkey", OPT_CAKEY, 's', + "The CA key, must be PEM format; if not in CAfile"}, + {"CAcreateserial", OPT_CACREATESERIAL, '-', + "Create serial number file if it does not exist"}, + {"CAserial", OPT_CASERIAL, 's', "Serial file"}, + {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, + {"text", OPT_TEXT, '-', "Print the certificate in text form"}, + {"ext", OPT_EXT, 's', "Print various X509V3 extensions"}, + {"C", OPT_C, '-', "Print out C code forms"}, + {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"}, + OPT_R_OPTIONS, + {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"certopt", OPT_CERTOPT, 's', "Various certificate text options"}, + {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"}, + {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"}, + {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"}, + {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"}, + {"CAkeyform", OPT_CAKEYFORM, 'f', "CA key format - default PEM"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"}, + {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"}, + {"clrreject", OPT_CLRREJECT, '-', + "Clears all the prohibited or rejected uses of the certificate"}, + {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_MD5 + {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-', + "Print old-style (MD5) issuer hash value"}, + {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-', + "Print old-style (MD5) subject hash value"}, +#endif +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"}, + {NULL} +}; -int MAIN(int argc, char **argv) +int x509_main(int argc, char **argv) { - ENGINE *e = NULL; - int ret = 1; - X509_REQ *req = NULL; - X509 *x = NULL, *xca = NULL; - ASN1_OBJECT *objtmp; - STACK_OF(OPENSSL_STRING) *sigopts = NULL; - EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; ASN1_INTEGER *sno = NULL; - int i, num, badops = 0, badsig = 0; + ASN1_OBJECT *objtmp = NULL; BIO *out = NULL; - BIO *STDout = NULL; + CONF *extconf = NULL; + EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; - int informat, outformat, keyformat, CAformat, CAkeyformat; + STACK_OF(OPENSSL_STRING) *sigopts = NULL; + X509 *x = NULL, *xca = NULL; + X509_REQ *req = NULL, *rq = NULL; + X509_STORE *ctx = NULL; + const EVP_MD *digest = NULL; + char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL; + char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL; + char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; - char *CAkeyfile = NULL, *CAserial = NULL; - char *fkeyfile = NULL; - char *alias = NULL; - int text = 0, serial = 0, subject = 0, issuer = 0, startdate = - 0, enddate = 0; - int next_serial = 0; - int subject_hash = 0, issuer_hash = 0, ocspid = 0; + char *prog; + int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0; + int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; + int fingerprint = 0, reqfile = 0, checkend = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; + int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; + int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; + int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; + int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; + int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0; + int enddate = 0; + time_t checkoffset = 0; + unsigned long certflag = 0; + int preserve_dates = 0; + OPTION_CHOICE o; + ENGINE *e = NULL; #ifndef OPENSSL_NO_MD5 int subject_hash_old = 0, issuer_hash_old = 0; #endif - int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; - int ocsp_uri = 0; - int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0; - int C = 0; - int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0; - int pprint = 0; - const char **pp; - X509_STORE *ctx = NULL; - X509_REQ *rq = NULL; - int fingerprint = 0; - char buf[256]; - const EVP_MD *md_alg, *digest = NULL; - CONF *extconf = NULL; - char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; - int need_rand = 0; - int checkend = 0, checkoffset = 0; - unsigned long nmflag = 0, certflag = 0; - char *checkhost = NULL; - char *checkemail = NULL; - char *checkip = NULL; - char *engine = NULL; - - reqfile = 0; - - apps_startup(); - - if (bio_err == NULL) - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - - if (!load_config(bio_err, NULL)) - goto end; - STDout = BIO_new_fp(stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - STDout = BIO_push(tmpbio, STDout); - } -#endif - - informat = FORMAT_PEM; - outformat = FORMAT_PEM; - keyformat = FORMAT_PEM; - CAformat = FORMAT_PEM; - CAkeyformat = FORMAT_PEM; ctx = X509_STORE_new(); if (ctx == NULL) goto end; X509_STORE_set_verify_cb(ctx, callb); - argc--; - argv++; - num = 0; - while (argc >= 1) { - if (strcmp(*argv, "-inform") == 0) { - if (--argc < 1) - goto bad; - informat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-outform") == 0) { - if (--argc < 1) - goto bad; - outformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-keyform") == 0) { - if (--argc < 1) - goto bad; - keyformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-req") == 0) { + prog = opt_init(argc, argv, x509_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(x509_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) + goto opthelp; + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) + goto opthelp; + break; + case OPT_CAFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat)) + goto opthelp; + break; + case OPT_CAKEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_REQ: reqfile = 1; - need_rand = 1; - } else if (strcmp(*argv, "-CAform") == 0) { - if (--argc < 1) - goto bad; - CAformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-CAkeyform") == 0) { - if (--argc < 1) - goto bad; - CAkeyformat = str2fmt(*(++argv)); - } else if (strcmp(*argv, "-sigopt") == 0) { - if (--argc < 1) - goto bad; + break; + + case OPT_SIGOPT: if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); - if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) - goto bad; - } -#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL - else if (strcmp(*argv, "-force_version") == 0) { - if (--argc < 1) - goto bad; - force_version = atoi(*(++argv)) - 1; - } -#endif - else if (strcmp(*argv, "-days") == 0) { - if (--argc < 1) - goto bad; - days = atoi(*(++argv)); - if (days == 0) { - BIO_printf(bio_err, "bad number of days\n"); - goto bad; - } - } else if (strcmp(*argv, "-passin") == 0) { - if (--argc < 1) - goto bad; - passargin = *(++argv); - } else if (strcmp(*argv, "-extfile") == 0) { - if (--argc < 1) - goto bad; - extfile = *(++argv); - } else if (strcmp(*argv, "-extensions") == 0) { - if (--argc < 1) - goto bad; - extsect = *(++argv); - } else if (strcmp(*argv, "-in") == 0) { - if (--argc < 1) - goto bad; - infile = *(++argv); - } else if (strcmp(*argv, "-out") == 0) { - if (--argc < 1) - goto bad; - outfile = *(++argv); - } else if (strcmp(*argv, "-signkey") == 0) { - if (--argc < 1) - goto bad; - keyfile = *(++argv); + if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto opthelp; + break; + case OPT_DAYS: + if (preserve_dates) + goto opthelp; + days = atoi(opt_arg()); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_EXTFILE: + extfile = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_EXTENSIONS: + extsect = opt_arg(); + break; + case OPT_SIGNKEY: + keyfile = opt_arg(); sign_flag = ++num; - need_rand = 1; - } else if (strcmp(*argv, "-CA") == 0) { - if (--argc < 1) - goto bad; - CAfile = *(++argv); + break; + case OPT_CA: + CAfile = opt_arg(); CA_flag = ++num; - need_rand = 1; - } else if (strcmp(*argv, "-CAkey") == 0) { - if (--argc < 1) - goto bad; - CAkeyfile = *(++argv); - } else if (strcmp(*argv, "-CAserial") == 0) { - if (--argc < 1) - goto bad; - CAserial = *(++argv); - } else if (strcmp(*argv, "-set_serial") == 0) { - if (--argc < 1) - goto bad; - if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv)))) - goto bad; - } else if (strcmp(*argv, "-force_pubkey") == 0) { - if (--argc < 1) - goto bad; - fkeyfile = *(++argv); - } else if (strcmp(*argv, "-addtrust") == 0) { - if (--argc < 1) - goto bad; - if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { - BIO_printf(bio_err, "Invalid trust object value %s\n", *argv); - goto bad; + break; + case OPT_CAKEY: + CAkeyfile = opt_arg(); + break; + case OPT_CASERIAL: + CAserial = opt_arg(); + break; + case OPT_SET_SERIAL: + if (sno != NULL) { + BIO_printf(bio_err, "Serial number supplied twice\n"); + goto opthelp; } - if (!trust) - trust = sk_ASN1_OBJECT_new_null(); + if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) + goto opthelp; + break; + case OPT_FORCE_PUBKEY: + fkeyfile = opt_arg(); + break; + case OPT_ADDTRUST: + if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { + BIO_printf(bio_err, + "%s: Invalid trust object value %s\n", + prog, opt_arg()); + goto opthelp; + } + if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; sk_ASN1_OBJECT_push(trust, objtmp); + objtmp = NULL; trustout = 1; - } else if (strcmp(*argv, "-addreject") == 0) { - if (--argc < 1) - goto bad; - if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { + break; + case OPT_ADDREJECT: + if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { BIO_printf(bio_err, - "Invalid reject object value %s\n", *argv); - goto bad; + "%s: Invalid reject object value %s\n", + prog, opt_arg()); + goto opthelp; } - if (!reject) - reject = sk_ASN1_OBJECT_new_null(); + if (reject == NULL + && (reject = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; sk_ASN1_OBJECT_push(reject, objtmp); + objtmp = NULL; trustout = 1; - } else if (strcmp(*argv, "-setalias") == 0) { - if (--argc < 1) - goto bad; - alias = *(++argv); + break; + case OPT_SETALIAS: + alias = opt_arg(); trustout = 1; - } else if (strcmp(*argv, "-certopt") == 0) { - if (--argc < 1) - goto bad; - if (!set_cert_ex(&certflag, *(++argv))) - goto bad; - } else if (strcmp(*argv, "-nameopt") == 0) { - if (--argc < 1) - goto bad; - if (!set_name_ex(&nmflag, *(++argv))) - goto bad; - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*argv, "-engine") == 0) { - if (--argc < 1) - goto bad; - engine = *(++argv); - } -#endif - else if (strcmp(*argv, "-C") == 0) + break; + case OPT_CERTOPT: + if (!set_cert_ex(&certflag, opt_arg())) + goto opthelp; + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto opthelp; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_C: C = ++num; - else if (strcmp(*argv, "-email") == 0) + break; + case OPT_EMAIL: email = ++num; - else if (strcmp(*argv, "-ocsp_uri") == 0) + break; + case OPT_OCSP_URI: ocsp_uri = ++num; - else if (strcmp(*argv, "-serial") == 0) + break; + case OPT_SERIAL: serial = ++num; - else if (strcmp(*argv, "-next_serial") == 0) + break; + case OPT_NEXT_SERIAL: next_serial = ++num; - else if (strcmp(*argv, "-modulus") == 0) + break; + case OPT_MODULUS: modulus = ++num; - else if (strcmp(*argv, "-pubkey") == 0) + break; + case OPT_PUBKEY: pubkey = ++num; - else if (strcmp(*argv, "-x509toreq") == 0) + break; + case OPT_X509TOREQ: x509req = ++num; - else if (strcmp(*argv, "-text") == 0) + break; + case OPT_TEXT: text = ++num; - else if (strcmp(*argv, "-hash") == 0 - || strcmp(*argv, "-subject_hash") == 0) - subject_hash = ++num; -#ifndef OPENSSL_NO_MD5 - else if (strcmp(*argv, "-subject_hash_old") == 0) - subject_hash_old = ++num; -#endif - else if (strcmp(*argv, "-issuer_hash") == 0) - issuer_hash = ++num; -#ifndef OPENSSL_NO_MD5 - else if (strcmp(*argv, "-issuer_hash_old") == 0) - issuer_hash_old = ++num; -#endif - else if (strcmp(*argv, "-subject") == 0) + break; + case OPT_SUBJECT: subject = ++num; - else if (strcmp(*argv, "-issuer") == 0) + break; + case OPT_ISSUER: issuer = ++num; - else if (strcmp(*argv, "-fingerprint") == 0) + break; + case OPT_FINGERPRINT: fingerprint = ++num; - else if (strcmp(*argv, "-dates") == 0) { - startdate = ++num; - enddate = ++num; - } else if (strcmp(*argv, "-purpose") == 0) + break; + case OPT_HASH: + subject_hash = ++num; + break; + case OPT_ISSUER_HASH: + issuer_hash = ++num; + break; + case OPT_PURPOSE: pprint = ++num; - else if (strcmp(*argv, "-startdate") == 0) + break; + case OPT_STARTDATE: startdate = ++num; - else if (strcmp(*argv, "-enddate") == 0) + break; + case OPT_ENDDATE: enddate = ++num; - else if (strcmp(*argv, "-checkend") == 0) { - if (--argc < 1) - goto bad; - checkoffset = atoi(*(++argv)); - checkend = 1; - } else if (strcmp(*argv, "-checkhost") == 0) { - if (--argc < 1) - goto bad; - checkhost = *(++argv); - } else if (strcmp(*argv, "-checkemail") == 0) { - if (--argc < 1) - goto bad; - checkemail = *(++argv); - } else if (strcmp(*argv, "-checkip") == 0) { - if (--argc < 1) - goto bad; - checkip = *(++argv); - } else if (strcmp(*argv, "-noout") == 0) + break; + case OPT_NOOUT: noout = ++num; - else if (strcmp(*argv, "-trustout") == 0) + break; + case OPT_EXT: + ext = ++num; + exts = opt_arg(); + break; + case OPT_NOCERT: + nocert = 1; + break; + case OPT_TRUSTOUT: trustout = 1; - else if (strcmp(*argv, "-clrtrust") == 0) + break; + case OPT_CLRTRUST: clrtrust = ++num; - else if (strcmp(*argv, "-clrreject") == 0) + break; + case OPT_CLRREJECT: clrreject = ++num; - else if (strcmp(*argv, "-alias") == 0) + break; + case OPT_ALIAS: aliasout = ++num; - else if (strcmp(*argv, "-CAcreateserial") == 0) + break; + case OPT_CACREATESERIAL: CA_createserial = ++num; - else if (strcmp(*argv, "-clrext") == 0) - clrext = 1; -#if 1 /* stay backwards-compatible with 0.9.5; this - * should go away soon */ - else if (strcmp(*argv, "-crlext") == 0) { - BIO_printf(bio_err, "use -clrext instead of -crlext\n"); + break; + case OPT_CLREXT: clrext = 1; - } -#endif - else if (strcmp(*argv, "-ocspid") == 0) + break; + case OPT_OCSPID: ocspid = ++num; - else if (strcmp(*argv, "-badsig") == 0) + break; + case OPT_BADSIG: badsig = 1; - else if ((md_alg = EVP_get_digestbyname(*argv + 1))) { - /* ok */ - digest = md_alg; - } else { - BIO_printf(bio_err, "unknown option %s\n", *argv); - badops = 1; break; +#ifndef OPENSSL_NO_MD5 + case OPT_SUBJECT_HASH_OLD: + subject_hash_old = ++num; + break; + case OPT_ISSUER_HASH_OLD: + issuer_hash_old = ++num; + break; +#else + case OPT_SUBJECT_HASH_OLD: + case OPT_ISSUER_HASH_OLD: + break; +#endif + case OPT_DATES: + startdate = ++num; + enddate = ++num; + break; + case OPT_CHECKEND: + checkend = 1; + { + intmax_t temp = 0; + if (!opt_imax(opt_arg(), &temp)) + goto opthelp; + checkoffset = (time_t)temp; + if ((intmax_t)checkoffset != temp) { + BIO_printf(bio_err, "%s: checkend time out of range %s\n", + prog, opt_arg()); + goto opthelp; + } + } + break; + case OPT_CHECKHOST: + checkhost = opt_arg(); + break; + case OPT_CHECKEMAIL: + checkemail = opt_arg(); + break; + case OPT_CHECKIP: + checkip = opt_arg(); + break; + case OPT_PRESERVE_DATES: + if (days != DEF_DAYS) + goto opthelp; + preserve_dates = 1; + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &digest)) + goto opthelp; } - argc--; - argv++; } - - if (badops) { - bad: - for (pp = x509_usage; (*pp != NULL); pp++) - BIO_printf(bio_err, "%s", *pp); - goto end; + argc = opt_num_rest(); + argv = opt_rest(); + if (argc != 0) { + BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]); + goto opthelp; } - e = setup_engine(bio_err, engine, 0); - - if (need_rand) - app_RAND_load_file(NULL, bio_err, 0); - ERR_load_crypto_strings(); - - if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } @@ -516,9 +477,8 @@ int MAIN(int argc, char **argv) goto end; } - if (fkeyfile) { - fkey = load_pubkey(bio_err, fkeyfile, keyformat, 0, - NULL, e, "Forced key"); + if (fkeyfile != NULL) { + fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key"); if (fkey == NULL) goto end; } @@ -531,23 +491,13 @@ int MAIN(int argc, char **argv) goto end; } - if (extfile) { - long errorline = -1; + if (extfile != NULL) { X509V3_CTX ctx2; - extconf = NCONF_new(NULL); - if (!NCONF_load(extconf, extfile, &errorline)) { - if (errorline <= 0) - BIO_printf(bio_err, - "error loading the config file '%s'\n", extfile); - else - BIO_printf(bio_err, - "error on line %ld of config file '%s'\n", - errorline, extfile); + if ((extconf = app_load_config(extfile)) == NULL) goto end; - } - if (!extsect) { + if (extsect == NULL) { extsect = NCONF_get_string(extconf, "default", "extensions"); - if (!extsect) { + if (extsect == NULL) { ERR_clear_error(); extsect = "default"; } @@ -570,21 +520,9 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "We need a private key to sign with\n"); goto end; } - in = BIO_new(BIO_s_file()); - if (in == NULL) { - ERR_print_errors(bio_err); + in = bio_open_default(infile, 'r', informat); + if (in == NULL) goto end; - } - - if (infile == NULL) - BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT); - else { - if (BIO_read_filename(in, infile) <= 0) { - perror(infile); - BIO_free(in); - goto end; - } - } req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); BIO_free(in); @@ -593,21 +531,11 @@ int MAIN(int argc, char **argv) goto end; } - if ((req->req_info == NULL) || - (req->req_info->pubkey == NULL) || - (req->req_info->pubkey->public_key == NULL) || - (req->req_info->pubkey->public_key->data == NULL)) { - BIO_printf(bio_err, - "The certificate request appears to corrupted\n"); - BIO_printf(bio_err, "It does not contain a public key\n"); - goto end; - } - if ((pkey = X509_REQ_get_pubkey(req)) == NULL) { + if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); goto end; } i = X509_REQ_verify(req, pkey); - EVP_PKEY_free(pkey); if (i < 0) { BIO_printf(bio_err, "Signature verification error\n"); ERR_print_errors(bio_err); @@ -617,74 +545,59 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "Signature did not match the certificate request\n"); goto end; - } else + } else { BIO_printf(bio_err, "Signature ok\n"); + } print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), - nmflag); + get_nameopt()); if ((x = X509_new()) == NULL) goto end; if (sno == NULL) { sno = ASN1_INTEGER_new(); - if (!sno || !rand_serial(NULL, sno)) + if (sno == NULL || !rand_serial(NULL, sno)) goto end; if (!X509_set_serialNumber(x, sno)) goto end; ASN1_INTEGER_free(sno); sno = NULL; - } else if (!X509_set_serialNumber(x, sno)) + } else if (!X509_set_serialNumber(x, sno)) { goto end; + } - if (!X509_set_issuer_name(x, req->req_info->subject)) + if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req))) + goto end; + if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req))) goto end; - if (!X509_set_subject_name(x, req->req_info->subject)) + if (!set_cert_times(x, NULL, NULL, days)) goto end; - X509_gmtime_adj(X509_get_notBefore(x), 0); - X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL); - if (fkey) + if (fkey != NULL) { X509_set_pubkey(x, fkey); - else { - pkey = X509_REQ_get_pubkey(req); + } else { + pkey = X509_REQ_get0_pubkey(req); X509_set_pubkey(x, pkey); - EVP_PKEY_free(pkey); } - } else - x = load_cert(bio_err, infile, informat, NULL, e, "Certificate"); + } else { + x = load_cert(infile, informat, "Certificate"); + } if (x == NULL) goto end; if (CA_flag) { - xca = load_cert(bio_err, CAfile, CAformat, NULL, e, "CA Certificate"); + xca = load_cert(CAfile, CAformat, "CA Certificate"); if (xca == NULL) goto end; } - if (!noout || text || next_serial) { - OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; - out = BIO_new(BIO_s_file()); - if (out == NULL) { - ERR_print_errors(bio_err); - goto end; - } - if (outfile == NULL) { - BIO_set_fp(out, stdout, BIO_NOCLOSE); -#ifdef OPENSSL_SYS_VMS - { - BIO *tmpbio = BIO_new(BIO_f_linebuffer()); - out = BIO_push(tmpbio, out); - } -#endif - } else { - if (BIO_write_filename(out, outfile) <= 0) { - perror(outfile); - goto end; - } - } - } + if (!noout || text || next_serial) + OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); @@ -694,37 +607,44 @@ int MAIN(int argc, char **argv) if (clrreject) X509_reject_clear(x); - if (trust) { + if (trust != NULL) { for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { objtmp = sk_ASN1_OBJECT_value(trust, i); X509_add1_trust_object(x, objtmp); } + objtmp = NULL; } - if (reject) { + if (reject != NULL) { for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { objtmp = sk_ASN1_OBJECT_value(reject, i); X509_add1_reject_object(x, objtmp); } + objtmp = NULL; + } + + if (badsig) { + const ASN1_BIT_STRING *signature; + + X509_get0_signature(&signature, NULL, x); + corrupt_signature(signature); } if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { - print_name(STDout, "issuer= ", - X509_get_issuer_name(x), nmflag); + print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); } else if (subject == i) { - print_name(STDout, "subject= ", - X509_get_subject_name(x), nmflag); + print_name(out, "subject=", + X509_get_subject_name(x), get_nameopt()); } else if (serial == i) { - BIO_printf(STDout, "serial="); - i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x)); - BIO_printf(STDout, "\n"); + BIO_printf(out, "serial="); + i2a_ASN1_INTEGER(out, X509_get_serialNumber(x)); + BIO_printf(out, "\n"); } else if (next_serial == i) { - BIGNUM *bnser; - ASN1_INTEGER *ser; - ser = X509_get_serialNumber(x); - bnser = ASN1_INTEGER_to_BN(ser, NULL); + ASN1_INTEGER *ser = X509_get_serialNumber(x); + BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL); + if (!bnser) goto end; if (!BN_add_word(bnser, 1)) @@ -744,160 +664,127 @@ int MAIN(int argc, char **argv) else emlst = X509_get1_ocsp(x); for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) - BIO_printf(STDout, "%s\n", + BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); X509_email_free(emlst); } else if (aliasout == i) { unsigned char *alstr; alstr = X509_alias_get0(x, NULL); if (alstr) - BIO_printf(STDout, "%s\n", alstr); + BIO_printf(out, "%s\n", alstr); else - BIO_puts(STDout, "<No Alias>\n"); + BIO_puts(out, "<No Alias>\n"); } else if (subject_hash == i) { - BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x)); + BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (subject_hash_old == i) { - BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x)); + BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); } #endif else if (issuer_hash == i) { - BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x)); + BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (issuer_hash_old == i) { - BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x)); + BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); } #endif else if (pprint == i) { X509_PURPOSE *ptmp; int j; - BIO_printf(STDout, "Certificate purposes:\n"); + BIO_printf(out, "Certificate purposes:\n"); for (j = 0; j < X509_PURPOSE_get_count(); j++) { ptmp = X509_PURPOSE_get0(j); - purpose_print(STDout, x, ptmp); + purpose_print(out, x, ptmp); } } else if (modulus == i) { EVP_PKEY *pkey; - pkey = X509_get_pubkey(x); + pkey = X509_get0_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Modulus=unavailable\n"); ERR_print_errors(bio_err); goto end; } - BIO_printf(STDout, "Modulus="); + BIO_printf(out, "Modulus="); #ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA) - BN_print(STDout, pkey->pkey.rsa->n); - else + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + const BIGNUM *n; + RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL); + BN_print(out, n); + } else #endif #ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) - BN_print(STDout, pkey->pkey.dsa->pub_key); - else + if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { + const BIGNUM *dsapub = NULL; + DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL); + BN_print(out, dsapub); + } else #endif - BIO_printf(STDout, "Wrong Algorithm type"); - BIO_printf(STDout, "\n"); - EVP_PKEY_free(pkey); + { + BIO_printf(out, "Wrong Algorithm type"); + } + BIO_printf(out, "\n"); } else if (pubkey == i) { EVP_PKEY *pkey; - pkey = X509_get_pubkey(x); + pkey = X509_get0_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Error getting public key\n"); ERR_print_errors(bio_err); goto end; } - PEM_write_bio_PUBKEY(STDout, pkey); - EVP_PKEY_free(pkey); + PEM_write_bio_PUBKEY(out, pkey); } else if (C == i) { unsigned char *d; char *m; - int y, z; + int len; - X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); - BIO_printf(STDout, "/* subject:%s */\n", buf); - m = X509_NAME_oneline(X509_get_issuer_name(x), buf, - sizeof(buf)); - BIO_printf(STDout, "/* issuer :%s */\n", buf); - - z = i2d_X509(x, NULL); - m = OPENSSL_malloc(z); - if (!m) { - BIO_printf(bio_err, "Out of memory\n"); - ERR_print_errors(bio_err); - goto end; - } + print_name(out, "/*\n" + " * Subject: ", X509_get_subject_name(x), get_nameopt()); + print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt()); + BIO_puts(out, " */\n"); + len = i2d_X509(x, NULL); + m = app_malloc(len, "x509 name buffer"); d = (unsigned char *)m; - z = i2d_X509_NAME(X509_get_subject_name(x), &d); - BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n", - z); + len = i2d_X509_NAME(X509_get_subject_name(x), &d); + print_array(out, "the_subject_name", len, (unsigned char *)m); d = (unsigned char *)m; - for (y = 0; y < z; y++) { - BIO_printf(STDout, "0x%02X,", d[y]); - if ((y & 0x0f) == 0x0f) - BIO_printf(STDout, "\n"); - } - if (y % 16 != 0) - BIO_printf(STDout, "\n"); - BIO_printf(STDout, "};\n"); - - z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); - BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z); - d = (unsigned char *)m; - for (y = 0; y < z; y++) { - BIO_printf(STDout, "0x%02X,", d[y]); - if ((y & 0x0f) == 0x0f) - BIO_printf(STDout, "\n"); - } - if (y % 16 != 0) - BIO_printf(STDout, "\n"); - BIO_printf(STDout, "};\n"); - - z = i2d_X509(x, &d); - BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n", - z); + len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); + print_array(out, "the_public_key", len, (unsigned char *)m); d = (unsigned char *)m; - for (y = 0; y < z; y++) { - BIO_printf(STDout, "0x%02X,", d[y]); - if ((y & 0x0f) == 0x0f) - BIO_printf(STDout, "\n"); - } - if (y % 16 != 0) - BIO_printf(STDout, "\n"); - BIO_printf(STDout, "};\n"); - + len = i2d_X509(x, &d); + print_array(out, "the_certificate", len, (unsigned char *)m); OPENSSL_free(m); } else if (text == i) { - X509_print_ex(STDout, x, nmflag, certflag); + X509_print_ex(out, x, get_nameopt(), certflag); } else if (startdate == i) { - BIO_puts(STDout, "notBefore="); - ASN1_TIME_print(STDout, X509_get_notBefore(x)); - BIO_puts(STDout, "\n"); + BIO_puts(out, "notBefore="); + ASN1_TIME_print(out, X509_get0_notBefore(x)); + BIO_puts(out, "\n"); } else if (enddate == i) { - BIO_puts(STDout, "notAfter="); - ASN1_TIME_print(STDout, X509_get_notAfter(x)); - BIO_puts(STDout, "\n"); + BIO_puts(out, "notAfter="); + ASN1_TIME_print(out, X509_get0_notAfter(x)); + BIO_puts(out, "\n"); } else if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; const EVP_MD *fdig = digest; - if (!fdig) + if (fdig == NULL) fdig = EVP_sha1(); if (!X509_digest(x, fdig, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } - BIO_printf(STDout, "%s Fingerprint=", + BIO_printf(out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(fdig))); for (j = 0; j < (int)n; j++) { - BIO_printf(STDout, "%02X%c", md[j], (j + 1 == (int)n) + BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } @@ -906,31 +793,27 @@ int MAIN(int argc, char **argv) else if ((sign_flag == i) && (x509req == 0)) { BIO_printf(bio_err, "Getting Private key\n"); if (Upkey == NULL) { - Upkey = load_key(bio_err, - keyfile, keyformat, 0, + Upkey = load_key(keyfile, keyformat, 0, passin, e, "Private key"); if (Upkey == NULL) goto end; } - assert(need_rand); - if (!sign(x, Upkey, days, clrext, digest, extconf, extsect)) + if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates)) goto end; } else if (CA_flag == i) { BIO_printf(bio_err, "Getting CA Private Key\n"); if (CAkeyfile != NULL) { - CApkey = load_key(bio_err, - CAkeyfile, CAkeyformat, + CApkey = load_key(CAkeyfile, CAkeyformat, 0, passin, e, "CA Private Key"); if (CApkey == NULL) goto end; } - assert(need_rand); if (!x509_certify(ctx, CAfile, digest, x, xca, CApkey, sigopts, CAserial, CA_createserial, days, clrext, - extconf, extsect, sno)) + extconf, extsect, sno, reqfile, preserve_dates)) goto end; } else if (x509req == i) { EVP_PKEY *pk; @@ -940,8 +823,7 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "no request key file specified\n"); goto end; } else { - pk = load_key(bio_err, - keyfile, keyformat, 0, + pk = load_key(keyfile, keyformat, 0, passin, e, "request key"); if (pk == NULL) goto end; @@ -956,12 +838,14 @@ int MAIN(int argc, char **argv) goto end; } if (!noout) { - X509_REQ_print(out, rq); + X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT); PEM_write_bio_X509_REQ(out, rq); } noout = 1; } else if (ocspid == i) { X509_ocspid_print(out, x); + } else if (ext == i) { + print_x509v3_exts(out, x, exts); } } } @@ -969,7 +853,7 @@ int MAIN(int argc, char **argv) if (checkend) { time_t tcheck = time(NULL) + checkoffset; - if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { + if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) { BIO_printf(out, "Certificate will expire\n"); ret = 1; } else { @@ -979,33 +863,20 @@ int MAIN(int argc, char **argv) goto end; } - print_cert_checks(STDout, x, checkhost, checkemail, checkip); + print_cert_checks(out, x, checkhost, checkemail, checkip); - if (noout) { + if (noout || nocert) { ret = 0; goto end; } - if (badsig) - x->signature->data[x->signature->length - 1] ^= 0x1; - - if (outformat == FORMAT_ASN1) + if (outformat == FORMAT_ASN1) { i = i2d_X509_bio(out, x); - else if (outformat == FORMAT_PEM) { + } else if (outformat == FORMAT_PEM) { if (trustout) i = PEM_write_bio_X509_AUX(out, x); else i = PEM_write_bio_X509(out, x); - } else if (outformat == FORMAT_NETSCAPE) { - NETSCAPE_X509 nx; - ASN1_OCTET_STRING hdr; - - hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; - hdr.length = strlen(NETSCAPE_CERT_HDR); - nx.header = &hdr; - nx.cert = x; - - i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx); } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; @@ -1017,12 +888,8 @@ int MAIN(int argc, char **argv) } ret = 0; end: - if (need_rand) - app_RAND_write_file(NULL, bio_err); - OBJ_cleanup(); NCONF_free(extconf); BIO_free_all(out); - BIO_free_all(STDout); X509_STORE_free(ctx); X509_REQ_free(req); X509_free(x); @@ -1030,47 +897,35 @@ int MAIN(int argc, char **argv) EVP_PKEY_free(Upkey); EVP_PKEY_free(CApkey); EVP_PKEY_free(fkey); - if (sigopts) - sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(sigopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); + ASN1_OBJECT_free(objtmp); release_engine(e); - if (passin) - OPENSSL_free(passin); - apps_shutdown(); - OPENSSL_EXIT(ret); + OPENSSL_free(passin); + return ret; } -static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, - int create) +static ASN1_INTEGER *x509_load_serial(const char *CAfile, + const char *serialfile, int create) { - char *buf = NULL, *p; + char *buf = NULL; ASN1_INTEGER *bs = NULL; BIGNUM *serial = NULL; - size_t len; - len = ((serialfile == NULL) - ? (strlen(CAfile) + strlen(POSTFIX) + 1) - : (strlen(serialfile))) + 1; - buf = OPENSSL_malloc(len); - if (buf == NULL) { - BIO_printf(bio_err, "out of mem\n"); - goto end; - } if (serialfile == NULL) { - BUF_strlcpy(buf, CAfile, len); - for (p = buf; *p; p++) - if (*p == '.') { - *p = '\0'; - break; - } - BUF_strlcat(buf, POSTFIX, len); - } else - BUF_strlcpy(buf, serialfile, len); + const char *p = strrchr(CAfile, '.'); + size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile); - serial = load_serial(buf, create, NULL); + buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer"); + memcpy(buf, CAfile, len); + memcpy(buf + len, POSTFIX, sizeof(POSTFIX)); + serialfile = buf; + } + + serial = load_serial(serialfile, create, NULL); if (serial == NULL) goto end; @@ -1079,54 +934,51 @@ static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, goto end; } - if (!save_serial(buf, NULL, serial, &bs)) + if (!save_serial(serialfile, NULL, serial, &bs)) goto end; end: - if (buf) - OPENSSL_free(buf); + OPENSSL_free(buf); BN_free(serial); return bs; } -static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, +static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, - char *serialfile, int create, - int days, int clrext, CONF *conf, char *section, - ASN1_INTEGER *sno) + const char *serialfile, int create, + int days, int clrext, CONF *conf, const char *section, + ASN1_INTEGER *sno, int reqfile, int preserve_dates) { int ret = 0; ASN1_INTEGER *bs = NULL; - X509_STORE_CTX xsc; + X509_STORE_CTX *xsc = NULL; EVP_PKEY *upkey; - upkey = X509_get_pubkey(xca); - if (upkey == NULL) { + upkey = X509_get0_pubkey(xca); + if (upkey == NULL) { BIO_printf(bio_err, "Error obtaining CA X509 public key\n"); goto end; } EVP_PKEY_copy_parameters(upkey, pkey); - EVP_PKEY_free(upkey); - if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) { + xsc = X509_STORE_CTX_new(); + if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } if (sno) bs = sno; - else if (!(bs = x509_load_serial(CAfile, serialfile, create))) + else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL) goto end; -/* if (!X509_STORE_add_cert(ctx,x)) goto end;*/ - /* * NOTE: this certificate can/should be self signed, unless it was a * certificate request in which case it is not. */ - X509_STORE_CTX_set_cert(&xsc, x); - X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); - if (!reqfile && X509_verify_cert(&xsc) <= 0) + X509_STORE_CTX_set_cert(xsc, x); + X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); + if (!reqfile && X509_verify_cert(xsc) <= 0) goto end; if (!X509_check_private_key(xca, pkey)) { @@ -1140,11 +992,7 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, if (!X509_set_serialNumber(x, bs)) goto end; - if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL) - goto end; - - /* hardwired expired */ - if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL) + if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) goto end; if (clrext) { @@ -1152,24 +1000,20 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509_delete_ext(x, 0); } - if (conf) { + if (conf != NULL) { X509V3_CTX ctx2; -#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL - X509_set_version(x, force_version); -#else X509_set_version(x, 2); /* version 3 certificate */ -#endif X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); X509V3_set_nconf(&ctx2, conf); if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end; } - if (!do_X509_sign(bio_err, x, pkey, digest, sigopts)) + if (!do_X509_sign(x, pkey, digest, sigopts)) goto end; ret = 1; end: - X509_STORE_CTX_cleanup(&xsc); + X509_STORE_CTX_free(xsc); if (!ret) ERR_print_errors(bio_err); if (!sno) @@ -1177,7 +1021,7 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, return ret; } -static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx) +static int callb(int ok, X509_STORE_CTX *ctx) { int err; X509 *err_cert; @@ -1212,39 +1056,23 @@ static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx) /* self sign */ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, - const EVP_MD *digest, CONF *conf, char *section) + const EVP_MD *digest, CONF *conf, const char *section, + int preserve_dates) { - EVP_PKEY *pktmp; - - pktmp = X509_get_pubkey(x); - if (pktmp == NULL) - goto err; - EVP_PKEY_copy_parameters(pktmp, pkey); - EVP_PKEY_save_parameters(pktmp, 1); - EVP_PKEY_free(pktmp); - if (!X509_set_issuer_name(x, X509_get_subject_name(x))) goto err; - if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) - goto err; - - if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL) + if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) goto err; - if (!X509_set_pubkey(x, pkey)) goto err; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } - if (conf) { + if (conf != NULL) { X509V3_CTX ctx; -#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL - X509_set_version(x, force_version); -#else X509_set_version(x, 2); /* version 3 certificate */ -#endif X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); X509V3_set_nconf(&ctx, conf); if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) @@ -1261,7 +1089,7 @@ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) { int id, i, idret; - char *pname; + const char *pname; id = X509_PURPOSE_get_id(pt); pname = X509_PURPOSE_get0_name(pt); for (i = 0; i < 2; i++) { @@ -1276,3 +1104,93 @@ static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) } return 1; } + +static int parse_ext_names(char *names, const char **result) +{ + char *p, *q; + int cnt = 0, len = 0; + + p = q = names; + len = strlen(names); + + while (q - names <= len) { + if (*q != ',' && *q != '\0') { + q++; + continue; + } + if (p != q) { + /* found */ + if (result != NULL) { + result[cnt] = p; + *q = '\0'; + } + cnt++; + } + p = ++q; + } + + return cnt; +} + +static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names) +{ + const STACK_OF(X509_EXTENSION) *exts = NULL; + STACK_OF(X509_EXTENSION) *exts2 = NULL; + X509_EXTENSION *ext = NULL; + ASN1_OBJECT *obj; + int i, j, ret = 0, num, nn = 0; + const char *sn, **names = NULL; + char *tmp_ext_names = NULL; + + exts = X509_get0_extensions(x); + if ((num = sk_X509_EXTENSION_num(exts)) <= 0) { + BIO_printf(bio, "No extensions in certificate\n"); + ret = 1; + goto end; + } + + /* parse comma separated ext name string */ + if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL) + goto end; + if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) { + BIO_printf(bio, "Invalid extension names: %s\n", ext_names); + goto end; + } + if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL) + goto end; + parse_ext_names(tmp_ext_names, names); + + for (i = 0; i < num; i++) { + ext = sk_X509_EXTENSION_value(exts, i); + + /* check if this ext is what we want */ + obj = X509_EXTENSION_get_object(ext); + sn = OBJ_nid2sn(OBJ_obj2nid(obj)); + if (sn == NULL || strcmp(sn, "UNDEF") == 0) + continue; + + for (j = 0; j < nn; j++) { + if (strcmp(sn, names[j]) == 0) { + /* push the extension into a new stack */ + if (exts2 == NULL + && (exts2 = sk_X509_EXTENSION_new_null()) == NULL) + goto end; + if (!sk_X509_EXTENSION_push(exts2, ext)) + goto end; + } + } + } + + if (!sk_X509_EXTENSION_num(exts2)) { + BIO_printf(bio, "No extensions matched with %s\n", ext_names); + ret = 1; + goto end; + } + + ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0); + end: + sk_X509_EXTENSION_free(exts2); + OPENSSL_free(names); + OPENSSL_free(tmp_ext_names); + return ret; +} |
