aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/CA.pl.in134
-rw-r--r--apps/asn1parse.c (renamed from apps/asn1pars.c)27
-rw-r--r--apps/bf_prefix.c177
-rw-r--r--apps/build.info147
-rw-r--r--[-rwxr-xr-x]apps/ca.c502
-rw-r--r--apps/ciphers.c66
-rw-r--r--apps/cmp.c3023
-rw-r--r--apps/cms.c685
-rw-r--r--apps/crl.c134
-rw-r--r--apps/crl2pkcs7.c (renamed from apps/crl2p7.c)26
-rw-r--r--apps/dgst.c302
-rw-r--r--apps/dh1024.pem10
-rw-r--r--apps/dh2048.pem14
-rw-r--r--apps/dh4096.pem19
-rw-r--r--apps/dhparam.c432
-rw-r--r--apps/dsa.c219
-rw-r--r--apps/dsaparam.c211
-rw-r--r--apps/ec.c266
-rw-r--r--apps/ecparam.c476
-rw-r--r--apps/enc.c228
-rw-r--r--apps/engine.c27
-rw-r--r--apps/errstr.c23
-rw-r--r--apps/fipsinstall.c590
-rw-r--r--apps/gendsa.c103
-rw-r--r--apps/genpkey.c206
-rw-r--r--apps/genrsa.c173
-rw-r--r--apps/include/__DECC_INCLUDE_EPILOGUE.H22
-rw-r--r--apps/include/__DECC_INCLUDE_PROLOGUE.H26
-rw-r--r--apps/include/app_libctx.h20
-rw-r--r--apps/include/app_params.h14
-rw-r--r--apps/include/apps.h348
-rw-r--r--apps/include/apps_ui.h29
-rw-r--r--apps/include/cmp_mock_srv.h35
-rw-r--r--apps/include/ec_common.h23
-rw-r--r--apps/include/engine_loader.h21
-rw-r--r--apps/include/fmt.h45
-rw-r--r--apps/include/function.h44
-rw-r--r--apps/include/http_server.h125
-rw-r--r--apps/include/names.h17
-rw-r--r--apps/include/opt.h (renamed from apps/apps.h)421
-rw-r--r--apps/include/platform.h32
-rw-r--r--apps/include/s_apps.h (renamed from apps/s_apps.h)43
-rw-r--r--apps/include/vms_term_sock.h31
-rw-r--r--apps/info.c104
-rw-r--r--apps/insta.ca.crtbin0 -> 916 bytes
-rw-r--r--apps/kdf.c211
-rw-r--r--apps/lib/app_libctx.c48
-rw-r--r--apps/lib/app_params.c132
-rw-r--r--apps/lib/app_provider.c92
-rw-r--r--apps/lib/app_rand.c (renamed from apps/app_rand.c)43
-rw-r--r--apps/lib/app_x509.c137
-rw-r--r--apps/lib/apps.c (renamed from apps/apps.c)2269
-rw-r--r--apps/lib/apps_ui.c223
-rw-r--r--apps/lib/build.info23
-rw-r--r--apps/lib/cmp_mock_srv.c450
-rw-r--r--apps/lib/columns.c27
-rw-r--r--apps/lib/engine.c193
-rw-r--r--apps/lib/engine_loader.c203
-rw-r--r--apps/lib/fmt.c15
-rw-r--r--apps/lib/http_server.c533
-rw-r--r--apps/lib/names.c45
-rw-r--r--apps/lib/opt.c (renamed from apps/opt.c)586
-rw-r--r--apps/lib/s_cb.c (renamed from apps/s_cb.c)271
-rw-r--r--apps/lib/s_socket.c (renamed from apps/s_socket.c)112
-rw-r--r--apps/lib/tlssrp_depr.c231
-rw-r--r--apps/lib/vms_decc_argv.c72
-rw-r--r--apps/lib/vms_term_sock.c591
-rw-r--r--apps/lib/win32_init.c307
-rw-r--r--apps/list.c1706
-rw-r--r--apps/mac.c237
-rw-r--r--apps/nseq.c30
-rw-r--r--apps/ocsp.c915
-rw-r--r--apps/openssl.c766
-rw-r--r--apps/openssl.cnf154
-rw-r--r--apps/passwd.c80
-rw-r--r--apps/pkcs12.c493
-rw-r--r--apps/pkcs7.c46
-rw-r--r--apps/pkcs8.c82
-rw-r--r--apps/pkey.c195
-rw-r--r--apps/pkeyparam.c62
-rw-r--r--apps/pkeyutl.c439
-rw-r--r--apps/prime.c43
-rw-r--r--apps/progs.pl285
-rw-r--r--apps/rand.c42
-rw-r--r--apps/rehash.c61
-rw-r--r--apps/req.c1003
-rw-r--r--apps/rsa.c322
-rw-r--r--apps/rsautl.c126
-rw-r--r--apps/s_client.c812
-rw-r--r--apps/s_server.c923
-rw-r--r--apps/s_time.c142
-rw-r--r--apps/sess_id.c19
-rw-r--r--apps/smime.c186
-rw-r--r--apps/speed.c3476
-rw-r--r--apps/spkac.c59
-rw-r--r--apps/srp.c55
-rw-r--r--apps/storeutl.c113
-rw-r--r--apps/testdsa.h51
-rw-r--r--apps/testrsa.h2
-rw-r--r--apps/timeouts.h2
-rw-r--r--apps/ts.c195
-rw-r--r--apps/tsget.in56
-rw-r--r--apps/verify.c179
-rw-r--r--apps/version.c137
-rw-r--r--apps/x509.c1179
105 files changed, 21482 insertions, 9625 deletions
diff --git a/apps/CA.pl.in b/apps/CA.pl.in
index db3cc383189e..f029470005d9 100644
--- a/apps/CA.pl.in
+++ b/apps/CA.pl.in
@@ -1,7 +1,7 @@
#!{- $config{HASHBANGPERL} -}
-# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (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
@@ -14,57 +14,63 @@
use strict;
use warnings;
-my $openssl = "openssl";
-if(defined $ENV{'OPENSSL'}) {
- $openssl = $ENV{'OPENSSL'};
-} else {
- $ENV{'OPENSSL'} = $openssl;
-}
-
my $verbose = 1;
+my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify");
-my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} || "";
-my $DAYS = "-days 365";
-my $CADAYS = "-days 1095"; # 3 years
+my $openssl = $ENV{'OPENSSL'} // "openssl";
+$ENV{'OPENSSL'} = $openssl;
+my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} // "";
+
+# Command invocations.
my $REQ = "$openssl req $OPENSSL_CONFIG";
my $CA = "$openssl ca $OPENSSL_CONFIG";
my $VERIFY = "$openssl verify";
my $X509 = "$openssl x509";
my $PKCS12 = "$openssl pkcs12";
-# default openssl.cnf file has setup as per the following
+# Default values for various configuration settings.
my $CATOP = "./demoCA";
my $CAKEY = "cakey.pem";
my $CAREQ = "careq.pem";
my $CACERT = "cacert.pem";
my $CACRL = "crl.pem";
-my $DIRMODE = 0777;
-
+my $DAYS = "-days 365";
+my $CADAYS = "-days 1095"; # 3 years
my $NEWKEY = "newkey.pem";
my $NEWREQ = "newreq.pem";
my $NEWCERT = "newcert.pem";
my $NEWP12 = "newcert.p12";
-my $RET = 0;
+
+# Commandline parsing
+my %EXTRA;
my $WHAT = shift @ARGV || "";
-my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify");
-my %EXTRA = extra_args(\@ARGV, "-extra-");
-my $FILE;
-
-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 {
- ();
- }
- } reverse grep($$args_ref[$_] =~ /$arg_prefix/, 0..$#$args_ref);
- my %empty = map { ($_, "") } @OPENSSL_CMDS;
- return (%empty, %eargs);
+@ARGV = parse_extra(@ARGV);
+my $RET = 0;
+
+# Split out "-extra-CMD value", and return new |@ARGV|. Fill in
+# |EXTRA{CMD}| with list of values.
+sub parse_extra
+{
+ foreach ( @OPENSSL_CMDS ) {
+ $EXTRA{$_} = '';
+ }
+
+ my @result;
+ while ( scalar(@_) > 0 ) {
+ my $arg = shift;
+ if ( $arg !~ m/-extra-([a-z0-9]+)/ ) {
+ push @result, $arg;
+ next;
+ }
+ $arg =~ s/-extra-//;
+ die("Unknown \"-${arg}-extra\" option, exiting")
+ unless scalar grep { $arg eq $_ } @OPENSSL_CMDS;
+ $EXTRA{$arg} .= " " . shift;
+ }
+ return @result;
}
+
# See if reason for a CRL entry is valid; exit if not.
sub crl_reason_ok
{
@@ -113,19 +119,25 @@ sub run
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";
+ print STDERR <<EOF;
+Usage:
+ CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd parameter]
+ CA.pl -pkcs12 [certname]
+ CA.pl -verify certfile ...
+ CA.pl -revoke certfile [reason]
+EOF
exit 0;
}
+
if ($WHAT eq '-newcert' ) {
# create a certificate
- $RET = run("$REQ -new -x509 -keyout $NEWKEY -out $NEWCERT $DAYS $EXTRA{req}");
+ $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");
+ $RET = run("$REQ -x509 -precert -keyout $NEWKEY -out $NEWCERT $DAYS"
+ . " $EXTRA{req}");
print "Pre-cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0;
} elsif ($WHAT =~ /^\-newreq(\-nodes)?$/ ) {
# create a certificate request
@@ -133,11 +145,20 @@ if ($WHAT eq '-newcert' ) {
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;
+ my @dirs = ( "${CATOP}", "${CATOP}/certs", "${CATOP}/crl",
+ "${CATOP}/newcerts", "${CATOP}/private" );
+ die "${CATOP}/index.txt exists.\nRemove old sub-tree to proceed,"
+ if -f "${CATOP}/index.txt";
+ die "${CATOP}/serial exists.\nRemove old sub-tree to proceed,"
+ if -f "${CATOP}/serial";
+ foreach my $d ( @dirs ) {
+ if ( -d $d ) {
+ warn "Directory $d exists" if -d $d;
+ } else {
+ mkdir $d or die "Can't mkdir $d, $!";
+ }
+ }
+
open OUT, ">${CATOP}/index.txt";
close OUT;
open OUT, ">${CATOP}/crlnumber";
@@ -145,6 +166,7 @@ if ($WHAT eq '-newcert' ) {
close OUT;
# ask user for existing CA certificate
print "CA certificate filename (or enter to create)\n";
+ my $FILE;
$FILE = "" unless defined($FILE = <STDIN>);
$FILE =~ s{\R$}{};
if ($FILE ne "") {
@@ -152,43 +174,43 @@ if ($WHAT eq '-newcert' ) {
copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE");
} else {
print "Making CA certificate ...\n";
- $RET = run("$REQ -new -keyout"
- . " ${CATOP}/private/$CAKEY"
+ $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;
+ . " -extensions v3_ca"
+ . " -infiles ${CATOP}/$CAREQ $EXTRA{ca}") 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"
+ . " -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");
+ $RET = run("$CA -policy policy_anything -infiles $NEWREQ $EXTRA{ca}");
} elsif ($WHAT eq '-sign' ) {
- $RET = run("$CA -policy policy_anything -out $NEWCERT $EXTRA{ca} -infiles $NEWREQ");
+ $RET = run("$CA -policy policy_anything -out $NEWCERT"
+ . " -infiles $NEWREQ $EXTRA{ca}");
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");
+ . " -extensions v3_ca -infiles $NEWREQ $EXTRA{ca}");
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;
+ . "-infiles tmp.pem $EXTRA{ca}") 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) {
+ foreach my $file (@files) {
+ # -CAfile quoted for VMS, since the C RTL downcases all unquoted
+ # arguments to C programs
my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file $EXTRA{verify}");
$RET = $status if $status != 0;
}
diff --git a/apps/asn1pars.c b/apps/asn1parse.c
index 6c44df7de490..f0bfd1d45fc4 100644
--- a/apps/asn1pars.c
+++ b/apps/asn1parse.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -19,7 +19,7 @@
#include <openssl/asn1t.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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,
@@ -27,27 +27,32 @@ typedef enum OPTION_choice {
} OPTION_CHOICE;
const OPTIONS asn1parse_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"oid", OPT_OID, '<', "file of extra oid definitions"},
+
+ OPT_SECTION("I/O"),
{"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"},
+ {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"},
{"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"},
+ {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"},
+
+ OPT_SECTION("Formatting"),
+ {"i", OPT_INDENT, 0, "indents the output"},
+ {"dump", OPT_DUMP, 0, "unknown data in hex form"},
+ {"dlimit", OPT_DLIMIT, 'p',
+ "dump the first arg bytes of unknown data in hex form"},
{NULL}
};
@@ -152,6 +157,8 @@ int asn1parse_main(int argc, char **argv)
break;
}
}
+
+ /* No extra args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
diff --git a/apps/bf_prefix.c b/apps/bf_prefix.c
deleted file mode 100644
index bae3c91bf8b3..000000000000
--- a/apps/bf_prefix.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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
index 01537361820e..020d129f8cac 100644
--- a/apps/build.info
+++ b/apps/build.info
@@ -1,79 +1,90 @@
-{- our @apps_openssl_src =
- qw(openssl.c
- asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c
- enc.c errstr.c
- genpkey.c nseq.c passwd.c pkcs7.c pkcs8.c
- pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c
- s_client.c s_server.c s_time.c sess_id.c smime.c speed.c spkac.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});
- "" -}
+SUBDIRS=lib
-IF[{- !$disabled{apps} -}]
- LIBS_NO_INST=libapps.a
- SOURCE[libapps.a]={- join(" ", @apps_lib_src) -}
- INCLUDE[libapps.a]=.. ../include
+# Program init source, that don't have direct linkage with the rest of the
+# source, and can therefore not be part of a library.
+IF[{- !$disabled{uplink} -}]
+ $INITSRC=../ms/applink.c
+ENDIF
+IF[{- $config{target} =~ /^vms-/ -}]
+ $INITSRC=vms_decc_init.c
+ENDIF
- PROGRAMS=openssl
- SOURCE[openssl]={- join(" ", @apps_init_src) -}
- SOURCE[openssl]={- join(" ", @apps_openssl_src) -}
- INCLUDE[openssl]=.. ../include
- DEPEND[openssl]=libapps.a ../libssl
- IF[{- !$disabled{'des'} -}]
- SOURCE[openssl]=pkcs12.c
- DEPEND[pkcs12.o]=progs.h
- ENDIF
- IF[{- !$disabled{'ec'} -}]
- SOURCE[openssl]=ec.c ecparam.c
- DEPEND[ec.o]=progs.h
- DEPEND[ecparam.o]=progs.h
- ENDIF
- IF[{- !$disabled{'ocsp'} -}]
- SOURCE[openssl]=ocsp.c
- DEPEND[ocsp.o]=progs.h
- ENDIF
- IF[{- !$disabled{'srp'} -}]
- SOURCE[openssl]=srp.c
- DEPEND[srp.o]=progs.h
- ENDIF
- IF[{- !$disabled{'ts'} -}]
- SOURCE[openssl]=ts.c
- DEPEND[ts.o]=progs.h
- ENDIF
- IF[{- !$disabled{'dh'} -}]
- SOURCE[openssl]=dhparam.c
- DEPEND[dhparam.o]=progs.h
- ENDIF
- IF[{- !$disabled{'dsa'} -}]
- SOURCE[openssl]=dsa.c dsaparam.c gendsa.c
- DEPEND[dsa.o]=progs.h
- DEPEND[dsaparam.o]=progs.h
- DEPEND[gendsa.o]=progs.h
- ENDIF
- IF[{- !$disabled{'engine'} -}]
- SOURCE[openssl]=engine.c
- DEPEND[engine.o]=progs.h
- ENDIF
+# Source for the 'openssl' program
+$OPENSSLSRC=\
+ openssl.c \
+ asn1parse.c ca.c ciphers.c crl.c crl2pkcs7.c dgst.c \
+ enc.c errstr.c \
+ genpkey.c kdf.c mac.c nseq.c passwd.c pkcs7.c \
+ pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c \
+ s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \
+ spkac.c verify.c version.c x509.c rehash.c storeutl.c \
+ list.c info.c fipsinstall.c pkcs12.c
+IF[{- !$disabled{'ec'} -}]
+ $OPENSSLSRC=$OPENSSLSRC ec.c ecparam.c
+ENDIF
+IF[{- !$disabled{'ocsp'} -}]
+ $OPENSSLSRC=$OPENSSLSRC ocsp.c
+ENDIF
+IF[{- !$disabled{'srp'} -}]
+ $OPENSSLSRC=$OPENSSLSRC srp.c
+ENDIF
+IF[{- !$disabled{'ts'} -}]
+ $OPENSSLSRC=$OPENSSLSRC ts.c
+ENDIF
+IF[{- !$disabled{'dh'} -}]
+$OPENSSLSRC=$OPENSSLSRC dhparam.c
+ENDIF
+IF[{- !$disabled{'dsa'} -}]
+$OPENSSLSRC=$OPENSSLSRC dsa.c dsaparam.c gendsa.c
+ENDIF
+IF[{- !$disabled{'engine'} -}]
+$OPENSSLSRC=$OPENSSLSRC engine.c
+ENDIF
+IF[{- !$disabled{'rsa'} -}]
+$OPENSSLSRC=$OPENSSLSRC rsa.c genrsa.c
+ENDIF
+IF[{- !$disabled{'deprecated-3.0'} -}]
IF[{- !$disabled{'rsa'} -}]
- SOURCE[openssl]=rsa.c rsautl.c genrsa.c
- DEPEND[rsa.o]=progs.h
- DEPEND[rsautl.o]=progs.h
- DEPEND[genrsa.o]=progs.h
+ $OPENSSLSRC=$OPENSSLSRC rsautl.c
ENDIF
- IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}]
+ENDIF
+IF[{- !$disabled{'cms'} -}]
+ $OPENSSLSRC=$OPENSSLSRC cms.c
+ENDIF
+IF[{- !$disabled{'cmp'} -}]
+ $OPENSSLSRC=$OPENSSLSRC cmp.c lib/cmp_mock_srv.c
+ENDIF
+
+IF[{- !$disabled{apps} -}]
+ PROGRAMS=openssl
+ SOURCE[openssl]=$INITSRC $OPENSSLSRC
+ INCLUDE[openssl]=.. ../include include
+ DEPEND[openssl]=libapps.a ../libssl
+
+ # The nocheck attribute is picked up by progs.pl as a signal not to look
+ # at that file; some systems may have locked it as the output file, and
+ # therefore don't allow it to be read at the same time, making progs.pl
+ # fail.
+ SOURCE[openssl]{nocheck}=progs.c
+ DEPEND[${OPENSSLSRC/.c/.o} progs.o]=progs.h
+ GENERATE[progs.c]=progs.pl "-C" $(APPS_OPENSSL)
+ GENERATE[progs.h]=progs.pl "-H" $(APPS_OPENSSL)
+ # progs.pl tries to read all 'openssl' sources, including progs.c, so we make
+ # sure things are generated in the correct order.
+ DEPEND[progs.h]=progs.c
+ # Because the files to look through may change (depends on $OPENSSLSRC),
+ # always depend on a changed configuration.
+ DEPEND[progs.c]=../configdata.pm
+
+ IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
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
+ SCRIPTS{misc}=CA.pl
SOURCE[CA.pl]=CA.pl.in
+ # linkname tells build files that a symbolic link or copy of this script
+ # without extension must be installed as well. Unix or Unix lookalike only.
+ SCRIPTS{misc,linkname=tsget}=tsget.pl
SOURCE[tsget.pl]=tsget.in
ENDIF
diff --git a/apps/ca.c b/apps/ca.c
index ea375ca0b1d3..e14a5cff7802 100755..100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -26,7 +26,7 @@
#ifndef W_OK
# ifdef OPENSSL_SYS_VMS
# include <unistd.h>
-# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
+# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_TANDEM)
# include <sys/file.h>
# endif
#endif
@@ -88,40 +88,46 @@ typedef enum {
static char *lookup_conf(const CONF *conf, const char *group, const char *tag);
-static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+static int certify(X509 **xret, const char *infile, int informat,
+ EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
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, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt);
+static int certify_cert(X509 **xret, const char *infile, int certformat,
+ const char *passin, EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
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);
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt);
static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
- X509 *x509, const EVP_MD *dgst,
+ X509 *x509, const char *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
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);
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
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);
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt);
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);
@@ -132,77 +138,97 @@ 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 CONF *extfile_conf = NULL;
static int preserve = 0;
static int msie_hack = 0;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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_KEY, OPT_CERT, OPT_CERTFORM, OPT_SELFSIGN,
+ OPT_IN, OPT_INFORM, OPT_OUT, OPT_DATEOPT, OPT_OUTDIR, OPT_VFYOPT,
OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN,
- OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
+ OPT_GENCRL, OPT_MSIE_HACK, OPT_CRL_LASTUPDATE, OPT_CRL_NEXTUPDATE,
+ 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,
+ OPT_R_ENUM, OPT_PROV_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;
const OPTIONS ca_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [certreq...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"verbose", OPT_VERBOSE, '-', "Verbose output during processing"},
+ {"outdir", OPT_OUTDIR, '/', "Where to put output cert"},
+ {"in", OPT_IN, '<', "The input cert request(s)"},
+ {"inform", OPT_INFORM, 'F', "CSR input format (DER or PEM); default PEM"},
+ {"infiles", OPT_INFILES, '-', "The last argument, requests to process"},
+ {"out", OPT_OUT, '>', "Where to put the output file(s)"},
+ {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."},
+ {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"},
+ {"batch", OPT_BATCH, '-', "Don't ask questions"},
+ {"msie_hack", OPT_MSIE_HACK, '-',
+ "msie modifications to handle all Universal Strings"},
+ {"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"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Configuration"),
{"config", OPT_CONFIG, 's', "A config file"},
{"name", OPT_NAME, 's', "The particular CA definition to use"},
+ {"section", OPT_NAME, 's', "An alias for -name"},
+ {"policy", OPT_POLICY, 's', "The CA 'policy' to support"},
+
+ OPT_SECTION("Certificate"),
{"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"},
- {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
+ {"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"},
+ "Deprecated; multi-valued RDNs support is always on."},
{"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"},
+ {"extensions", OPT_EXTENSIONS, 's',
+ "Extension section (override value in config file)"},
+ {"extfile", OPT_EXTFILE, '<',
+ "Configuration file with X509v3 extensions to add"},
+ {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"},
+ {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"},
+
+ OPT_SECTION("Signing"),
+ {"md", OPT_MD, 's', "Digest to use, such as sha256"},
+ {"keyfile", OPT_KEYFILE, 's', "The CA private key"},
+ {"keyform", OPT_KEYFORM, 'f',
+ "Private key file format (ENGINE, other values ignored)"},
+ {"passin", OPT_PASSIN, 's', "Key and cert input file pass phrase source"},
+ {"key", OPT_KEY, 's',
+ "Key to decrypt the private key or cert files if encrypted. Better use -passin"},
{"cert", OPT_CERT, '<', "The CA cert"},
+ {"certform", OPT_CERTFORM, 'F',
+ "Certificate input format (DER/PEM/P12); has no effect"},
{"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"},
+ {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
+
+ OPT_SECTION("Revocation"),
{"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',
@@ -214,10 +240,20 @@ const OPTIONS ca_options[] = {
"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"},
+ {"crl_lastupdate", OPT_CRL_LASTUPDATE, 's',
+ "Sets the CRL lastUpdate time to val (YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ)"},
+ {"crl_nextupdate", OPT_CRL_NEXTUPDATE, 's',
+ "Sets the CRL nextUpdate time to val (YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ)"},
+ {"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"},
+ {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"},
+
OPT_R_OPTIONS,
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"certreq", 0, 0, "Certificate requests to be signed (optional)"},
{NULL}
};
@@ -229,19 +265,21 @@ int ca_main(int argc, char **argv)
EVP_PKEY *pkey = NULL;
BIO *in = NULL, *out = NULL, *Sout = NULL;
ASN1_INTEGER *tmpser;
- ASN1_TIME *tmptm;
CA_DB *db = NULL;
DB_ATTR db_attr;
STACK_OF(CONF_VALUE) *attribs = NULL;
- STACK_OF(OPENSSL_STRING) *sigopts = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
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;
+ char def_dgst[80] = "";
+ char *dgst = NULL, *policy = NULL, *keyfile = NULL;
+ char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL;
+ int certformat = FORMAT_UNDEF, informat = FORMAT_UNDEF;
+ unsigned long dateopt = ASN1_DTFLGS_RFC822;
const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL;
const char *extensions = NULL, *extfile = NULL, *passinarg = NULL;
+ char *passin = NULL;
char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL;
const char *serialfile = NULL, *subj = NULL;
char *prog, *startdate = NULL, *enddate = NULL;
@@ -251,11 +289,12 @@ int ca_main(int argc, char **argv)
char *const *pp;
const char *p;
size_t outdirlen = 0;
- int create_ser = 0, free_key = 0, total = 0, total_done = 0;
+ int create_ser = 0, free_passin = 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 keyformat = FORMAT_UNDEF, multirdn = 1, 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;
+ int rand_ser = 0, i, j, selfsign = 0, def_ret;
+ char *crl_lastupdate = NULL, *crl_nextupdate = NULL;
long crldays = 0, crlhours = 0, crlsec = 0, days = 0;
unsigned long chtype = MBSTRING_ASC, certopt = 0;
X509 *x509 = NULL, *x509p = NULL, *x = NULL;
@@ -279,9 +318,17 @@ opthelp:
req = 1;
infile = opt_arg();
break;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
case OPT_OUT:
outfile = opt_arg();
break;
+ case OPT_DATEOPT:
+ if (!set_dateopt(&dateopt, opt_arg()))
+ goto opthelp;
+ break;
case OPT_VERBOSE:
verbose = 1;
break;
@@ -305,7 +352,7 @@ opthelp:
create_ser = 1;
break;
case OPT_MULTIVALUE_RDN:
- multirdn = 1;
+ /* obsolete */
break;
case OPT_STARTDATE:
startdate = opt_arg();
@@ -317,7 +364,7 @@ opthelp:
days = atoi(opt_arg());
break;
case OPT_MD:
- md = opt_arg();
+ dgst = opt_arg();
break;
case OPT_POLICY:
policy = opt_arg();
@@ -336,12 +383,20 @@ opthelp:
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_KEY:
- key = opt_arg();
+ passin = opt_arg();
break;
case OPT_CERT:
certfile = opt_arg();
break;
+ case OPT_CERTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &certformat))
+ goto opthelp;
+ break;
case OPT_SELFSIGN:
selfsign = 1;
break;
@@ -354,6 +409,12 @@ opthelp:
if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto end;
break;
+ case OPT_VFYOPT:
+ if (vfyopts == NULL)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (vfyopts == NULL || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
+ goto end;
+ break;
case OPT_NOTEXT:
notext = 1;
break;
@@ -372,6 +433,12 @@ opthelp:
case OPT_MSIE_HACK:
msie_hack = 1;
break;
+ case OPT_CRL_LASTUPDATE:
+ crl_lastupdate = opt_arg();
+ break;
+ case OPT_CRL_NEXTUPDATE:
+ crl_nextupdate = opt_arg();
+ break;
case OPT_CRLDAYS:
crldays = atol(opt_arg());
break;
@@ -427,13 +494,13 @@ opthelp:
break;
}
}
+
end_of_options:
+ /* Remaining args are files to certify. */
argc = opt_num_rest();
argv = opt_rest();
- BIO_printf(bio_err, "Using configuration from %s\n", configfile);
-
- if ((conf = app_load_config(configfile)) == NULL)
+ if ((conf = app_load_config_verbose(configfile, 1)) == NULL)
goto end;
if (configfile != default_config_file && !app_load_modules(conf))
goto end;
@@ -456,12 +523,12 @@ end_of_options:
BIO_free(oid_bio);
}
}
- if (!add_oid_section(conf)) {
- ERR_print_errors(bio_err);
+ if (!add_oid_section(conf))
goto end;
- }
app_RAND_load_conf(conf, BASE_SECTION);
+ if (!app_RAND_load())
+ goto end;
f = NCONF_get_string(conf, section, STRING_MASK);
if (f == NULL)
@@ -495,8 +562,10 @@ end_of_options:
goto end;
db = load_index(dbfile, &db_attr);
- if (db == NULL)
+ if (db == NULL) {
+ BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", dbfile);
goto end;
+ }
if (index_index(db) <= 0)
goto end;
@@ -513,16 +582,15 @@ end_of_options:
&& (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL)
goto end;
- if (key == NULL) {
- free_key = 1;
- if (!app_passwd(passinarg, NULL, &key, NULL)) {
+ if (passin == NULL) {
+ free_passin = 1;
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
}
- pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key");
- if (key != NULL)
- OPENSSL_cleanse(key, strlen(key));
+ pkey = load_key(keyfile, keyformat, 0, passin, e, "CA private key");
+ cleanse(passin);
if (pkey == NULL)
/* load_key() has already printed an appropriate message */
goto end;
@@ -534,7 +602,7 @@ end_of_options:
&& (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL)
goto end;
- x509 = load_cert(certfile, FORMAT_PEM, "CA certificate");
+ x509 = load_cert_pass(certfile, certformat, 1, passin, "CA certificate");
if (x509 == NULL)
goto end;
@@ -624,8 +692,10 @@ end_of_options:
goto end;
db = load_index(dbfile, &db_attr);
- if (db == NULL)
+ if (db == NULL) {
+ BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", dbfile);
goto end;
+ }
/* Lets check some fields */
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
@@ -703,7 +773,7 @@ end_of_options:
/*****************************************************************/
/* Read extensions config file */
if (extfile) {
- if ((extconf = app_load_config(extfile)) == NULL) {
+ if ((extfile_conf = app_load_config(extfile)) == NULL) {
ret = 1;
goto end;
}
@@ -714,7 +784,7 @@ end_of_options:
/* We can have sections in the ext file */
if (extensions == NULL) {
- extensions = NCONF_get_string(extconf, "default", "extensions");
+ extensions = NCONF_get_string(extfile_conf, "default", "extensions");
if (extensions == NULL)
extensions = "default";
}
@@ -728,28 +798,25 @@ end_of_options:
}
}
- def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid);
+ def_ret = EVP_PKEY_get_default_digest_name(pkey, def_dgst, sizeof(def_dgst));
/*
- * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is
+ * EVP_PKEY_get_default_digest_name() returns 2 if the digest is
* mandatory for this algorithm.
*/
- if (def_ret == 2 && def_nid == NID_undef) {
+ if (def_ret == 2 && strcmp(def_dgst, "UNDEF") == 0) {
/* 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) {
+ dgst = NULL;
+ } else if (dgst == NULL
+ && (dgst = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) {
goto end;
} else {
- if (strcmp(md, "default") == 0) {
+ if (strcmp(dgst, "default") == 0) {
if (def_ret <= 0) {
BIO_puts(bio_err, "no default digest\n");
goto end;
}
- md = (char *)OBJ_nid2sn(def_nid);
+ dgst = def_dgst;
}
-
- if (!opt_md(md, &dgst))
- goto end;
}
if (req) {
@@ -761,8 +828,7 @@ end_of_options:
email_dn = 0;
}
if (verbose)
- BIO_printf(bio_err, "message digest is %s\n",
- OBJ_nid2ln(EVP_MD_type(dgst)));
+ BIO_printf(bio_err, "message digest is %s\n", dgst);
if (policy == NULL
&& (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL)
goto end;
@@ -778,7 +844,20 @@ end_of_options:
goto end;
}
- if (extconf == NULL) {
+ if (extfile_conf != NULL) {
+ /* Check syntax of extfile */
+ X509V3_CTX ctx;
+
+ X509V3_set_ctx_test(&ctx);
+ X509V3_set_nconf(&ctx, extfile_conf);
+ if (!X509V3_EXT_add_nconf(extfile_conf, &ctx, extensions, NULL)) {
+ BIO_printf(bio_err,
+ "Error checking certificate extensions from extfile section %s\n",
+ extensions);
+ ret = 1;
+ goto end;
+ }
+ } else {
/*
* no '-extfile' option, so we look for extensions in the main
* configuration file
@@ -789,13 +868,14 @@ end_of_options:
ERR_clear_error();
}
if (extensions != NULL) {
- /* Check syntax of file */
+ /* Check syntax of config file section */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, conf);
if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) {
BIO_printf(bio_err,
- "Error Loading extension section %s\n",
+ "Error checking certificate extension config section %s\n",
extensions);
ret = 1;
goto end;
@@ -874,7 +954,7 @@ end_of_options:
attribs, db, serial, subj, chtype, multirdn,
email_dn, startdate, enddate, days, extensions,
conf, verbose, certopt, get_nameopt(), default_op,
- ext_copy);
+ ext_copy, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -890,12 +970,12 @@ end_of_options:
}
if (ss_cert_file != NULL) {
total++;
- j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts,
- attribs,
+ j = certify_cert(&x, ss_cert_file, certformat, passin, pkey,
+ x509, dgst, sigopts, vfyopts, attribs,
db, serial, subj, chtype, multirdn, email_dn,
startdate, enddate, days, batch, extensions,
conf, verbose, certopt, get_nameopt(), default_op,
- ext_copy);
+ ext_copy, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -911,10 +991,11 @@ end_of_options:
}
if (infile != NULL) {
total++;
- j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db,
+ j = certify(&x, infile, informat, pkey, x509p, dgst,
+ sigopts, vfyopts, attribs, db,
serial, subj, chtype, multirdn, email_dn, startdate,
enddate, days, batch, extensions, conf, verbose,
- certopt, get_nameopt(), default_op, ext_copy, selfsign);
+ certopt, get_nameopt(), default_op, ext_copy, selfsign, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -930,10 +1011,12 @@ end_of_options:
}
for (i = 0; i < argc; i++) {
total++;
- j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db,
+ j = certify(&x, argv[i], informat, pkey, x509p, dgst,
+ sigopts, vfyopts,
+ attribs, db,
serial, subj, chtype, multirdn, email_dn, startdate,
enddate, days, batch, extensions, conf, verbose,
- certopt, get_nameopt(), default_op, ext_copy, selfsign);
+ certopt, get_nameopt(), default_op, ext_copy, selfsign, dateopt);
if (j < 0)
goto end;
if (j > 0) {
@@ -996,7 +1079,7 @@ end_of_options:
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 ASN1_INTEGER *serialNumber = X509_get0_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");
@@ -1067,11 +1150,12 @@ end_of_options:
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 checking CRL extension section %s\n", crl_ext);
ret = 1;
goto end;
}
@@ -1094,7 +1178,8 @@ end_of_options:
crlhours = 0;
ERR_clear_error();
}
- if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
+ if ((crl_nextupdate == NULL) &&
+ (crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
BIO_printf(bio_err,
"cannot lookup how long until the next CRL is issued\n");
goto end;
@@ -1102,24 +1187,23 @@ end_of_options:
if (verbose)
BIO_printf(bio_err, "making CRL\n");
- if ((crl = X509_CRL_new()) == NULL)
+ if ((crl = X509_CRL_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
goto end;
if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509)))
goto end;
- tmptm = ASN1_TIME_new();
- 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");
- ASN1_TIME_free(tmptm);
+ if (!set_crl_lastupdate(crl, crl_lastupdate)) {
+ BIO_puts(bio_err, "error setting CRL lastUpdate\n");
+ ret = 1;
goto end;
}
- X509_CRL_set1_nextUpdate(crl, tmptm);
- ASN1_TIME_free(tmptm);
+ if (!set_crl_nextupdate(crl, crl_nextupdate,
+ crldays, crlhours, crlsec)) {
+ BIO_puts(bio_err, "error setting CRL nextUpdate\n");
+ ret = 1;
+ goto end;
+ }
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
@@ -1157,12 +1241,16 @@ end_of_options:
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 != NULL)
- if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
+ if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) {
+ BIO_printf(bio_err,
+ "Error adding CRL extensions from section %s\n", crl_ext);
goto end;
+ }
if (crlnumberfile != NULL) {
tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
if (!tmpser)
@@ -1175,8 +1263,8 @@ end_of_options:
}
}
if (crl_ext != NULL || crl_v2) {
- if (!X509_CRL_set_version(crl, 1))
- goto end; /* version 2 CRL */
+ if (!X509_CRL_set_version(crl, X509_CRL_VERSION_2))
+ goto end;
}
/* we have a CRL number that need updating */
@@ -1210,7 +1298,9 @@ end_of_options:
goto end;
} else {
X509 *revcert;
- revcert = load_cert(infile, FORMAT_PEM, infile);
+
+ revcert = load_cert_pass(infile, informat, 1, passin,
+ "certificate to be revoked");
if (revcert == NULL)
goto end;
if (dorevoke == 2)
@@ -1239,17 +1329,19 @@ end_of_options:
BIO_free_all(in);
sk_X509_pop_free(cert_sk, X509_free);
- if (free_key)
- OPENSSL_free(key);
+ cleanse(passin);
+ if (free_passin)
+ OPENSSL_free(passin);
BN_free(serial);
BN_free(crlnumber);
free_index(db);
sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(vfyopts);
EVP_PKEY_free(pkey);
X509_free(x509);
X509_CRL_free(crl);
NCONF_free(conf);
- NCONF_free(extconf);
+ NCONF_free(extfile_conf);
release_engine(e);
return ret;
}
@@ -1262,101 +1354,94 @@ static char *lookup_conf(const CONF *conf, const char *section, const char *tag)
return entry;
}
-static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+static int certify(X509 **xret, const char *infile, int informat,
+ EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
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)
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt)
{
X509_REQ *req = NULL;
- BIO *in = NULL;
EVP_PKEY *pktmp = NULL;
int ok = -1, i;
- in = BIO_new_file(infile, "r");
- if (in == NULL) {
- ERR_print_errors(bio_err);
+ req = load_csr(infile, informat, "certificate request");
+ if (req == NULL)
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);
+ if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) {
+ BIO_printf(bio_err, "Error unpacking public key\n");
goto end;
}
if (verbose)
X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT);
BIO_printf(bio_err, "Check that the request matches the signature\n");
+ ok = 0;
if (selfsign && !X509_REQ_check_private_key(req, pkey)) {
BIO_printf(bio_err,
"Certificate request and CA private key do not match\n");
- ok = 0;
- goto end;
- }
- if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) {
- BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
- i = X509_REQ_verify(req, pktmp);
- pktmp = NULL;
+ i = do_X509_REQ_verify(req, pktmp, vfyopts);
if (i < 0) {
- ok = 0;
- BIO_printf(bio_err, "Signature verification problems....\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Signature verification problems...\n");
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 end;
- } else {
- BIO_printf(bio_err, "Signature ok\n");
}
+ 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);
+ ext_copy, selfsign, dateopt);
end:
+ ERR_print_errors(bio_err);
X509_REQ_free(req);
- BIO_free(in);
return ok;
}
-static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+static int certify_cert(X509 **xret, const char *infile, int certformat,
+ const char *passin, EVP_PKEY *pkey, X509 *x509,
+ const char *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(OPENSSL_STRING) *vfyopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
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)
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt)
{
- X509 *req = NULL;
+ X509 *template_cert = NULL;
X509_REQ *rreq = NULL;
EVP_PKEY *pktmp = NULL;
int ok = -1, i;
- if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL)
+ if ((template_cert = load_cert_pass(infile, certformat, 1, passin,
+ "template certificate")) == NULL)
goto end;
if (verbose)
- X509_print(bio_err, req);
+ X509_print(bio_err, template_cert);
BIO_printf(bio_err, "Check that the request matches the signature\n");
- if ((pktmp = X509_get0_pubkey(req)) == NULL) {
+ if ((pktmp = X509_get0_pubkey(template_cert)) == NULL) {
BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
- i = X509_verify(req, pktmp);
+ i = do_X509_verify(template_cert, pktmp, vfyopts);
if (i < 0) {
ok = 0;
BIO_printf(bio_err, "Signature verification problems....\n");
@@ -1370,30 +1455,31 @@ static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x
BIO_printf(bio_err, "Signature ok\n");
}
- if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL)
+ if ((rreq = X509_to_X509_REQ(template_cert, 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);
+ ext_copy, 0, dateopt);
end:
X509_REQ_free(rreq);
- X509_free(req);
+ X509_free(template_cert);
return ok;
}
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
- const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
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)
+ int default_op, int ext_copy, int selfsign, unsigned long dateopt)
{
- X509_NAME *name = NULL, *CAname = NULL, *subject = NULL;
+ const X509_NAME *name = NULL;
+ X509_NAME *CAname = NULL, *subject = NULL;
const ASN1_TIME *tm;
ASN1_STRING *str, *str2;
ASN1_OBJECT *obj;
@@ -1407,17 +1493,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
OPENSSL_STRING *irow = NULL;
OPENSSL_STRING *rrow = NULL;
char buf[25];
+ X509V3_CTX ext_ctx;
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
if (subj) {
- X509_NAME *n = parse_name(subj, chtype, multirdn);
+ X509_NAME *n = parse_name(subj, chtype, multirdn, "subject");
- if (!n) {
- ERR_print_errors(bio_err);
+ if (!n)
goto end;
- }
X509_REQ_set_subject_name(req, n);
X509_NAME_free(n);
}
@@ -1592,15 +1677,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
BIO_printf(bio_err,
"Everything appears to be ok, creating and signing the certificate\n");
- if ((ret = X509_new()) == NULL)
+ if ((ret = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
goto end;
-#ifdef X509_V3
- /* Make it an X509 v3 certificate. */
- if (!X509_set_version(ret, 2))
- goto end;
-#endif
-
if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL)
goto end;
if (selfsign) {
@@ -1630,32 +1709,24 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
if (!i)
goto end;
+ /* Initialize the context structure */
+ X509V3_set_ctx(&ext_ctx, selfsign ? ret : x509,
+ ret, req, NULL, X509V3_CTX_REPLACE);
+
/* Lets add the extensions, if there are any */
if (ext_sect) {
- X509V3_CTX ctx;
-
- /* 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 != NULL) {
+ if (extfile_conf != NULL) {
if (verbose)
BIO_printf(bio_err, "Extra configuration file found\n");
- /* Use the extconf configuration db LHASH */
- X509V3_set_nconf(&ctx, extconf);
-
- /* Test the structure (needed?) */
- /* X509V3_set_ctx_test(&ctx); */
+ /* Use the extfile_conf configuration db LHASH */
+ X509V3_set_nconf(&ext_ctx, extfile_conf);
/* Adds exts contained in the configuration file */
- if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) {
+ if (!X509V3_EXT_add_nconf(extfile_conf, &ext_ctx, ext_sect, ret)) {
BIO_printf(bio_err,
- "ERROR: adding extensions in section %s\n",
+ "Error adding certificate extensions from extfile section %s\n",
ext_sect);
- ERR_print_errors(bio_err);
goto end;
}
if (verbose)
@@ -1663,13 +1734,12 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
"Successfully added extensions from file.\n");
} else if (ext_sect) {
/* We found extensions to be set from config file */
- X509V3_set_nconf(&ctx, lconf);
+ X509V3_set_nconf(&ext_ctx, lconf);
- if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) {
+ if (!X509V3_EXT_add_nconf(lconf, &ext_ctx, ext_sect, ret)) {
BIO_printf(bio_err,
- "ERROR: adding extensions in section %s\n",
+ "Error adding certificate extensions from config section %s\n",
ext_sect);
- ERR_print_errors(bio_err);
goto end;
}
@@ -1683,19 +1753,9 @@ 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 end;
}
- {
- 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 end;
- }
-
if (verbose)
BIO_printf(bio_err,
"The subject name appears to be ok, checking data base for clashes\n");
@@ -1825,7 +1885,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_get0_notAfter(ret));
+ ASN1_TIME_print_ex(bio_err, X509_get0_notAfter(ret), dateopt);
if (days)
BIO_printf(bio_err, " (%ld days)", days);
BIO_printf(bio_err, "\n");
@@ -1853,7 +1913,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
!EVP_PKEY_missing_parameters(pkey))
EVP_PKEY_copy_parameters(pktmp, pkey);
- if (!do_X509_sign(ret, pkey, dgst, sigopts))
+ if (!do_X509_sign(ret, pkey, dgst, sigopts, &ext_ctx))
goto end;
/* We now just add it to the database as DB_TYPE_VAL('V') */
@@ -1911,14 +1971,14 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
}
static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
- X509 *x509, const EVP_MD *dgst,
+ X509 *x509, const char *dgst,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(CONF_VALUE) *policy, CA_DB *db,
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)
+ unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt)
{
STACK_OF(CONF_VALUE) *sk = NULL;
LHASH_OF(CONF_VALUE) *parms = NULL;
@@ -1941,7 +2001,6 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
parms = CONF_load(NULL, infile, &errline);
if (parms == NULL) {
BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile);
- ERR_print_errors(bio_err);
goto end;
}
@@ -1959,10 +2018,8 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
* and we can use the same code as if you had a real X509 request.
*/
req = X509_REQ_new();
- if (req == NULL) {
- ERR_print_errors(bio_err);
+ if (req == NULL)
goto end;
- }
/*
* Build up the subject name set.
@@ -1993,7 +2050,6 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
if (spki == NULL) {
BIO_printf(bio_err,
"unable to load Netscape SPKAC structure\n");
- ERR_print_errors(bio_err);
goto end;
}
}
@@ -2035,7 +2091,7 @@ static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
chtype, multirdn, email_dn, startdate, enddate, days, 1,
verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
- ext_copy, 0);
+ ext_copy, 0, dateopt);
end:
X509_REQ_free(req);
CONF_free(parms);
@@ -2062,7 +2118,7 @@ static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0);
- bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL);
+ bn = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x509), NULL);
if (!bn)
goto end;
if (BN_is_zero(bn))
@@ -2313,7 +2369,7 @@ static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg)
case REV_CRL_REASON:
for (i = 0; i < 8; i++) {
- if (strcasecmp(rev_arg, crl_reasons[i]) == 0) {
+ if (OPENSSL_strcasecmp(rev_arg, crl_reasons[i]) == 0) {
reason = crl_reasons[i];
break;
}
@@ -2413,18 +2469,18 @@ static int make_revoked(X509_REVOKED *rev, const char *str)
rtmp = ASN1_ENUMERATED_new();
if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code))
goto end;
- if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
+ if (X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0) <= 0)
goto end;
}
if (rev && comp_time) {
- if (!X509_REVOKED_add1_ext_i2d
- (rev, NID_invalidity_date, comp_time, 0, 0))
+ if (X509_REVOKED_add1_ext_i2d
+ (rev, NID_invalidity_date, comp_time, 0, 0) <= 0)
goto end;
}
if (rev && hold) {
- if (!X509_REVOKED_add1_ext_i2d
- (rev, NID_hold_instruction_code, hold, 0, 0))
+ if (X509_REVOKED_add1_ext_i2d
+ (rev, NID_hold_instruction_code, hold, 0, 0) <= 0)
goto end;
}
@@ -2530,7 +2586,7 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
}
if (reason_str) {
for (i = 0; i < NUM_REASONS; i++) {
- if (strcasecmp(reason_str, crl_reasons[i]) == 0) {
+ if (OPENSSL_strcasecmp(reason_str, crl_reasons[i]) == 0) {
reason_code = i;
break;
}
diff --git a/apps/ciphers.c b/apps/ciphers.c
index aade3fbf5671..42a0bb79f651 100644
--- a/apps/ciphers.c
+++ b/apps/ciphers.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -14,9 +14,10 @@
#include "progs.h"
#include <openssl/err.h>
#include <openssl/ssl.h>
+#include "s_apps.h"
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_STDNAME,
OPT_CONVERT,
OPT_SSL3,
@@ -27,39 +28,50 @@ typedef enum OPTION_choice {
OPT_PSK,
OPT_SRP,
OPT_CIPHERSUITES,
- OPT_V, OPT_UPPER_V, OPT_S
+ OPT_V, OPT_UPPER_V, OPT_S, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ciphers_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cipher]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
{"v", OPT_V, '-', "Verbose listing of the SSL/TLS ciphers"},
{"V", OPT_UPPER_V, '-', "Even more verbose"},
+ {"stdname", OPT_STDNAME, '-', "Show standard cipher names"},
+ {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"},
+
+ OPT_SECTION("Cipher specification"),
{"s", OPT_S, '-', "Only supported ciphers"},
#ifndef OPENSSL_NO_SSL3
- {"ssl3", OPT_SSL3, '-', "SSL3 mode"},
+ {"ssl3", OPT_SSL3, '-', "Ciphers compatible with SSL3"},
#endif
#ifndef OPENSSL_NO_TLS1
- {"tls1", OPT_TLS1, '-', "TLS1 mode"},
+ {"tls1", OPT_TLS1, '-', "Ciphers compatible with TLS1"},
#endif
#ifndef OPENSSL_NO_TLS1_1
- {"tls1_1", OPT_TLS1_1, '-', "TLS1.1 mode"},
+ {"tls1_1", OPT_TLS1_1, '-', "Ciphers compatible with TLS1.1"},
#endif
#ifndef OPENSSL_NO_TLS1_2
- {"tls1_2", OPT_TLS1_2, '-', "TLS1.2 mode"},
+ {"tls1_2", OPT_TLS1_2, '-', "Ciphers compatible with TLS1.2"},
#endif
#ifndef OPENSSL_NO_TLS1_3
- {"tls1_3", OPT_TLS1_3, '-', "TLS1.3 mode"},
+ {"tls1_3", OPT_TLS1_3, '-', "Ciphers compatible with TLS1.3"},
#endif
- {"stdname", OPT_STDNAME, '-', "Show standard cipher names"},
#ifndef OPENSSL_NO_PSK
- {"psk", OPT_PSK, '-', "include ciphersuites requiring PSK"},
+ {"psk", OPT_PSK, '-', "Include ciphersuites requiring PSK"},
#endif
#ifndef OPENSSL_NO_SRP
- {"srp", OPT_SRP, '-', "include ciphersuites requiring SRP"},
+ {"srp", OPT_SRP, '-', "(deprecated) 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"},
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"cipher", 0, 0, "Cipher string to decode (optional)"},
{NULL}
};
@@ -72,12 +84,6 @@ static unsigned int dummy_psk(SSL *ssl, const char *hint, char *identity,
return 0;
}
#endif
-#ifndef OPENSSL_NO_SRP
-static char *dummy_srp(SSL *ssl, void *arg)
-{
- return "";
-}
-#endif
int ciphers_main(int argc, char **argv)
{
@@ -159,13 +165,18 @@ int ciphers_main(int argc, char **argv)
case OPT_CIPHERSUITES:
ciphersuites = opt_arg();
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional arg is cipher name. */
argv = opt_rest();
argc = opt_num_rest();
-
if (argc == 1)
- ciphers = *argv;
+ ciphers = argv[0];
else if (argc != 0)
goto opthelp;
@@ -176,7 +187,7 @@ int ciphers_main(int argc, char **argv)
goto end;
}
- ctx = SSL_CTX_new(meth);
+ ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx == NULL)
goto err;
if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
@@ -190,7 +201,7 @@ int ciphers_main(int argc, char **argv)
#endif
#ifndef OPENSSL_NO_SRP
if (srp)
- SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp);
+ set_up_dummy_srp(ctx);
#endif
if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) {
@@ -216,6 +227,10 @@ int ciphers_main(int argc, char **argv)
if (!verbose) {
for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i);
+
+ if (!ossl_assert(c != NULL))
+ continue;
+
p = SSL_CIPHER_get_name(c);
if (p == NULL)
break;
@@ -231,6 +246,9 @@ int ciphers_main(int argc, char **argv)
c = sk_SSL_CIPHER_value(sk, i);
+ if (!ossl_assert(c != NULL))
+ continue;
+
if (Verbose) {
unsigned long id = SSL_CIPHER_get_id(c);
int id0 = (int)(id >> 24);
@@ -248,7 +266,7 @@ int ciphers_main(int argc, char **argv)
const char *nm = SSL_CIPHER_standard_name(c);
if (nm == NULL)
nm = "UNKNOWN";
- BIO_printf(bio_out, "%s - ", nm);
+ BIO_printf(bio_out, "%-45s - ", nm);
}
BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof(buf)));
}
diff --git a/apps/cmp.c b/apps/cmp.c
new file mode 100644
index 000000000000..9b9e405bb248
--- /dev/null
+++ b/apps/cmp.c
@@ -0,0 +1,3023 @@
+/*
+ * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/* This app is disabled when OPENSSL_NO_CMP is defined. */
+
+#include <string.h>
+#include <ctype.h>
+
+#include "apps.h"
+#include "http_server.h"
+#include "s_apps.h"
+#include "progs.h"
+
+#include "cmp_mock_srv.h"
+
+/* tweaks needed due to missing unistd.h on Windows */
+#if defined(_WIN32) && !defined(__BORLANDC__)
+# define access _access
+#endif
+#ifndef F_OK
+# define F_OK 0
+#endif
+
+#include <openssl/ui.h>
+#include <openssl/pkcs12.h>
+#include <openssl/ssl.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <stdlib.h>
+#include <openssl/cmp.h>
+#include <openssl/cmp_util.h>
+#include <openssl/crmf.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/store.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+
+static char *prog;
+static char *opt_config = NULL;
+#define CMP_SECTION "cmp"
+#define SECTION_NAME_MAX 40 /* max length of section name */
+#define DEFAULT_SECTION "default"
+static char *opt_section = CMP_SECTION;
+static int opt_verbosity = OSSL_CMP_LOG_INFO;
+
+static int read_config(void);
+
+static CONF *conf = NULL; /* OpenSSL config file context structure */
+static OSSL_CMP_CTX *cmp_ctx = NULL; /* the client-side CMP context */
+
+/* the type of cmp command we want to send */
+typedef enum {
+ CMP_IR,
+ CMP_KUR,
+ CMP_CR,
+ CMP_P10CR,
+ CMP_RR,
+ CMP_GENM
+} cmp_cmd_t;
+
+/* message transfer */
+#ifndef OPENSSL_NO_SOCK
+static char *opt_server = NULL;
+static char *opt_proxy = NULL;
+static char *opt_no_proxy = NULL;
+#endif
+static char *opt_recipient = NULL;
+static char *opt_path = NULL;
+static int opt_keep_alive = 1;
+static int opt_msg_timeout = -1;
+static int opt_total_timeout = -1;
+
+/* server authentication */
+static char *opt_trusted = NULL;
+static char *opt_untrusted = NULL;
+static char *opt_srvcert = NULL;
+static char *opt_expect_sender = NULL;
+static int opt_ignore_keyusage = 0;
+static int opt_unprotected_errors = 0;
+static char *opt_extracertsout = NULL;
+static char *opt_cacertsout = NULL;
+
+/* client authentication */
+static char *opt_ref = NULL;
+static char *opt_secret = NULL;
+static char *opt_cert = NULL;
+static char *opt_own_trusted = NULL;
+static char *opt_key = NULL;
+static char *opt_keypass = NULL;
+static char *opt_digest = NULL;
+static char *opt_mac = NULL;
+static char *opt_extracerts = NULL;
+static int opt_unprotected_requests = 0;
+
+/* generic message */
+static char *opt_cmd_s = NULL;
+static int opt_cmd = -1;
+static char *opt_geninfo = NULL;
+static char *opt_infotype_s = NULL;
+static int opt_infotype = NID_undef;
+
+/* certificate enrollment */
+static char *opt_newkey = NULL;
+static char *opt_newkeypass = NULL;
+static char *opt_subject = NULL;
+static char *opt_issuer = NULL;
+static int opt_days = 0;
+static char *opt_reqexts = NULL;
+static char *opt_sans = NULL;
+static int opt_san_nodefault = 0;
+static char *opt_policies = NULL;
+static char *opt_policy_oids = NULL;
+static int opt_policy_oids_critical = 0;
+static int opt_popo = OSSL_CRMF_POPO_NONE - 1;
+static char *opt_csr = NULL;
+static char *opt_out_trusted = NULL;
+static int opt_implicit_confirm = 0;
+static int opt_disable_confirm = 0;
+static char *opt_certout = NULL;
+static char *opt_chainout = NULL;
+
+/* certificate enrollment and revocation */
+static char *opt_oldcert = NULL;
+static int opt_revreason = CRL_REASON_NONE;
+
+/* credentials format */
+static char *opt_certform_s = "PEM";
+static int opt_certform = FORMAT_PEM;
+static char *opt_keyform_s = NULL;
+static int opt_keyform = FORMAT_UNDEF;
+static char *opt_otherpass = NULL;
+static char *opt_engine = NULL;
+
+#ifndef OPENSSL_NO_SOCK
+/* TLS connection */
+static int opt_tls_used = 0;
+static char *opt_tls_cert = NULL;
+static char *opt_tls_key = NULL;
+static char *opt_tls_keypass = NULL;
+static char *opt_tls_extra = NULL;
+static char *opt_tls_trusted = NULL;
+static char *opt_tls_host = NULL;
+#endif
+
+/* client-side debugging */
+static int opt_batch = 0;
+static int opt_repeat = 1;
+static char *opt_reqin = NULL;
+static int opt_reqin_new_tid = 0;
+static char *opt_reqout = NULL;
+static char *opt_rspin = NULL;
+static char *opt_rspout = NULL;
+static int opt_use_mock_srv = 0;
+
+/* mock server */
+#ifndef OPENSSL_NO_SOCK
+static char *opt_port = NULL;
+static int opt_max_msgs = 0;
+#endif
+static char *opt_srv_ref = NULL;
+static char *opt_srv_secret = NULL;
+static char *opt_srv_cert = NULL;
+static char *opt_srv_key = NULL;
+static char *opt_srv_keypass = NULL;
+
+static char *opt_srv_trusted = NULL;
+static char *opt_srv_untrusted = NULL;
+static char *opt_rsp_cert = NULL;
+static char *opt_rsp_extracerts = NULL;
+static char *opt_rsp_capubs = NULL;
+static int opt_poll_count = 0;
+static int opt_check_after = 1;
+static int opt_grant_implicitconf = 0;
+
+static int opt_pkistatus = OSSL_CMP_PKISTATUS_accepted;
+static int opt_failure = INT_MIN;
+static int opt_failurebits = 0;
+static char *opt_statusstring = NULL;
+static int opt_send_error = 0;
+static int opt_send_unprotected = 0;
+static int opt_send_unprot_err = 0;
+static int opt_accept_unprotected = 0;
+static int opt_accept_unprot_err = 0;
+static int opt_accept_raverified = 0;
+
+static X509_VERIFY_PARAM *vpm = NULL;
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY,
+
+ OPT_CMD, OPT_INFOTYPE, OPT_GENINFO,
+
+ OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_ISSUER,
+ OPT_DAYS, OPT_REQEXTS,
+ OPT_SANS, OPT_SAN_NODEFAULT,
+ OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL,
+ OPT_POPO, OPT_CSR,
+ OPT_OUT_TRUSTED, OPT_IMPLICIT_CONFIRM, OPT_DISABLE_CONFIRM,
+ OPT_CERTOUT, OPT_CHAINOUT,
+
+ OPT_OLDCERT, OPT_REVREASON,
+
+#ifndef OPENSSL_NO_SOCK
+ OPT_SERVER, OPT_PROXY, OPT_NO_PROXY,
+#endif
+ OPT_RECIPIENT, OPT_PATH,
+ OPT_KEEP_ALIVE, OPT_MSG_TIMEOUT, OPT_TOTAL_TIMEOUT,
+
+ OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT,
+ OPT_EXPECT_SENDER,
+ OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS,
+ OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
+
+ OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
+ OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
+ OPT_UNPROTECTED_REQUESTS,
+
+ OPT_CERTFORM, OPT_KEYFORM,
+ OPT_OTHERPASS,
+#ifndef OPENSSL_NO_ENGINE
+ OPT_ENGINE,
+#endif
+ OPT_PROV_ENUM,
+ OPT_R_ENUM,
+
+#ifndef OPENSSL_NO_SOCK
+ OPT_TLS_USED, OPT_TLS_CERT, OPT_TLS_KEY,
+ OPT_TLS_KEYPASS,
+ OPT_TLS_EXTRA, OPT_TLS_TRUSTED, OPT_TLS_HOST,
+#endif
+
+ OPT_BATCH, OPT_REPEAT,
+ OPT_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_RSPIN, OPT_RSPOUT,
+ OPT_USE_MOCK_SRV,
+
+#ifndef OPENSSL_NO_SOCK
+ OPT_PORT, OPT_MAX_MSGS,
+#endif
+ OPT_SRV_REF, OPT_SRV_SECRET,
+ OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
+ OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
+ OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
+ OPT_POLL_COUNT, OPT_CHECK_AFTER,
+ OPT_GRANT_IMPLICITCONF,
+ OPT_PKISTATUS, OPT_FAILURE,
+ OPT_FAILUREBITS, OPT_STATUSSTRING,
+ OPT_SEND_ERROR, OPT_SEND_UNPROTECTED,
+ OPT_SEND_UNPROT_ERR, OPT_ACCEPT_UNPROTECTED,
+ OPT_ACCEPT_UNPROT_ERR, OPT_ACCEPT_RAVERIFIED,
+
+ OPT_V_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS cmp_options[] = {
+ /* entries must be in the same order as enumerated above!! */
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"config", OPT_CONFIG, 's',
+ "Configuration file to use. \"\" = none. Default from env variable OPENSSL_CONF"},
+ {"section", OPT_SECTION, 's',
+ "Section(s) in config file to get options from. \"\" = 'default'. Default 'cmp'"},
+ {"verbosity", OPT_VERBOSITY, 'N',
+ "Log level; 3=ERR, 4=WARN, 6=INFO, 7=DEBUG, 8=TRACE. Default 6 = INFO"},
+
+ OPT_SECTION("Generic message"),
+ {"cmd", OPT_CMD, 's', "CMP request to send: ir/cr/kur/p10cr/rr/genm"},
+ {"infotype", OPT_INFOTYPE, 's',
+ "InfoType name for requesting specific info in genm, e.g. 'signKeyPairTypes'"},
+ {"geninfo", OPT_GENINFO, 's',
+ "generalInfo integer values to place in request PKIHeader with given OID"},
+ {OPT_MORE_STR, 0, 0,
+ "specified in the form <OID>:int:<n>, e.g. \"1.2.3.4:int:56789\""},
+
+ OPT_SECTION("Certificate enrollment"),
+ {"newkey", OPT_NEWKEY, 's',
+ "Private or public key for the requested cert. Default: CSR key or client key"},
+ {"newkeypass", OPT_NEWKEYPASS, 's', "New private key pass phrase source"},
+ {"subject", OPT_SUBJECT, 's',
+ "Distinguished Name (DN) of subject to use in the requested cert template"},
+ {OPT_MORE_STR, 0, 0,
+ "For kur, default is subject of -csr arg or reference cert (see -oldcert)"},
+ {OPT_MORE_STR, 0, 0,
+ "this default is used for ir and cr only if no Subject Alt Names are set"},
+ {"issuer", OPT_ISSUER, 's',
+ "DN of the issuer to place in the requested certificate template"},
+ {OPT_MORE_STR, 0, 0,
+ "also used as recipient if neither -recipient nor -srvcert are given"},
+ {"days", OPT_DAYS, 'N',
+ "Requested validity time of the new certificate in number of days"},
+ {"reqexts", OPT_REQEXTS, 's',
+ "Name of config file section defining certificate request extensions."},
+ {OPT_MORE_STR, 0, 0,
+ "Augments or replaces any extensions contained CSR given with -csr"},
+ {"sans", OPT_SANS, 's',
+ "Subject Alt Names (IPADDR/DNS/URI) to add as (critical) cert req extension"},
+ {"san_nodefault", OPT_SAN_NODEFAULT, '-',
+ "Do not take default SANs from reference certificate (see -oldcert)"},
+ {"policies", OPT_POLICIES, 's',
+ "Name of config file section defining policies certificate request extension"},
+ {"policy_oids", OPT_POLICY_OIDS, 's',
+ "Policy OID(s) to add as policies certificate request extension"},
+ {"policy_oids_critical", OPT_POLICY_OIDS_CRITICAL, '-',
+ "Flag the policy OID(s) given with -policy_oids as critical"},
+ {"popo", OPT_POPO, 'n',
+ "Proof-of-Possession (POPO) method to use for ir/cr/kur where"},
+ {OPT_MORE_STR, 0, 0,
+ "-1 = NONE, 0 = RAVERIFIED, 1 = SIGNATURE (default), 2 = KEYENC"},
+ {"csr", OPT_CSR, 's',
+ "PKCS#10 CSR file in PEM or DER format to convert or to use in p10cr"},
+ {"out_trusted", OPT_OUT_TRUSTED, 's',
+ "Certificates to trust when verifying newly enrolled certificates"},
+ {"implicit_confirm", OPT_IMPLICIT_CONFIRM, '-',
+ "Request implicit confirmation of newly enrolled certificates"},
+ {"disable_confirm", OPT_DISABLE_CONFIRM, '-',
+ "Do not confirm newly enrolled certificate w/o requesting implicit"},
+ {OPT_MORE_STR, 0, 0,
+ "confirmation. WARNING: This leads to behavior violating RFC 4210"},
+ {"certout", OPT_CERTOUT, 's',
+ "File to save newly enrolled certificate"},
+ {"chainout", OPT_CHAINOUT, 's',
+ "File to save the chain of newly enrolled certificate"},
+
+ OPT_SECTION("Certificate enrollment and revocation"),
+
+ {"oldcert", OPT_OLDCERT, 's',
+ "Certificate to be updated (defaulting to -cert) or to be revoked in rr;"},
+ {OPT_MORE_STR, 0, 0,
+ "also used as reference (defaulting to -cert) for subject DN and SANs."},
+ {OPT_MORE_STR, 0, 0,
+ "Issuer is used as recipient unless -recipient, -srvcert, or -issuer given"},
+ {"revreason", OPT_REVREASON, 'n',
+ "Reason code to include in revocation request (rr); possible values:"},
+ {OPT_MORE_STR, 0, 0,
+ "0..6, 8..10 (see RFC5280, 5.3.1) or -1. Default -1 = none included"},
+
+ OPT_SECTION("Message transfer"),
+#ifdef OPENSSL_NO_SOCK
+ {OPT_MORE_STR, 0, 0,
+ "NOTE: -server, -proxy, and -no_proxy not supported due to no-sock build"},
+#else
+ {"server", OPT_SERVER, 's',
+ "[http[s]://]address[:port][/path] of CMP server. Default port 80 or 443."},
+ {OPT_MORE_STR, 0, 0,
+ "address may be a DNS name or an IP address; path can be overridden by -path"},
+ {"proxy", OPT_PROXY, 's',
+ "[http[s]://]address[:port][/path] of HTTP(S) proxy to use; path is ignored"},
+ {"no_proxy", OPT_NO_PROXY, 's',
+ "List of addresses of servers not to use HTTP(S) proxy for"},
+ {OPT_MORE_STR, 0, 0,
+ "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
+#endif
+ {"recipient", OPT_RECIPIENT, 's',
+ "DN of CA. Default: subject of -srvcert, -issuer, issuer of -oldcert or -cert"},
+ {"path", OPT_PATH, 's',
+ "HTTP path (aka CMP alias) at the CMP server. Default from -server, else \"/\""},
+ {"keep_alive", OPT_KEEP_ALIVE, 'N',
+ "Persistent HTTP connections. 0: no, 1 (the default): request, 2: require"},
+ {"msg_timeout", OPT_MSG_TIMEOUT, 'N',
+ "Number of seconds allowed per CMP message round trip, or 0 for infinite"},
+ {"total_timeout", OPT_TOTAL_TIMEOUT, 'N',
+ "Overall time an enrollment incl. polling may take. Default 0 = infinite"},
+
+ OPT_SECTION("Server authentication"),
+ {"trusted", OPT_TRUSTED, 's',
+ "Certificates to trust as chain roots when verifying signed CMP responses"},
+ {OPT_MORE_STR, 0, 0, "unless -srvcert is given"},
+ {"untrusted", OPT_UNTRUSTED, 's',
+ "Intermediate CA certs for chain construction for CMP/TLS/enrolled certs"},
+ {"srvcert", OPT_SRVCERT, 's',
+ "Server cert to pin and trust directly when verifying signed CMP responses"},
+ {"expect_sender", OPT_EXPECT_SENDER, 's',
+ "DN of expected sender of responses. Defaults to subject of -srvcert, if any"},
+ {"ignore_keyusage", OPT_IGNORE_KEYUSAGE, '-',
+ "Ignore CMP signer cert key usage, else 'digitalSignature' must be allowed"},
+ {"unprotected_errors", OPT_UNPROTECTED_ERRORS, '-',
+ "Accept missing or invalid protection of regular error messages and negative"},
+ {OPT_MORE_STR, 0, 0,
+ "certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf"},
+ {OPT_MORE_STR, 0, 0,
+ "WARNING: This setting leads to behavior allowing violation of RFC 4210"},
+ {"extracertsout", OPT_EXTRACERTSOUT, 's',
+ "File to save extra certificates received in the extraCerts field"},
+ {"cacertsout", OPT_CACERTSOUT, 's',
+ "File to save CA certificates received in the caPubs field of 'ip' messages"},
+
+ OPT_SECTION("Client authentication"),
+ {"ref", OPT_REF, 's',
+ "Reference value to use as senderKID in case no -cert is given"},
+ {"secret", OPT_SECRET, 's',
+ "Prefer PBM (over signatures) for protecting msgs with given password source"},
+ {"cert", OPT_CERT, 's',
+ "Client's CMP signer certificate; its public key must match the -key argument"},
+ {OPT_MORE_STR, 0, 0,
+ "This also used as default reference for subject DN and SANs."},
+ {OPT_MORE_STR, 0, 0,
+ "Any further certs included are appended to the untrusted certs"},
+ {"own_trusted", OPT_OWN_TRUSTED, 's',
+ "Optional certs to verify chain building for own CMP signer cert"},
+ {"key", OPT_KEY, 's', "CMP signer private key, not used when -secret given"},
+ {"keypass", OPT_KEYPASS, 's',
+ "Client private key (and cert and old cert) pass phrase source"},
+ {"digest", OPT_DIGEST, 's',
+ "Digest to use in message protection and POPO signatures. Default \"sha256\""},
+ {"mac", OPT_MAC, 's',
+ "MAC algorithm to use in PBM-based message protection. Default \"hmac-sha1\""},
+ {"extracerts", OPT_EXTRACERTS, 's',
+ "Certificates to append in extraCerts field of outgoing messages."},
+ {OPT_MORE_STR, 0, 0,
+ "This can be used as the default CMP signer cert chain to include"},
+ {"unprotected_requests", OPT_UNPROTECTED_REQUESTS, '-',
+ "Send messages without CMP-level protection"},
+
+ OPT_SECTION("Credentials format"),
+ {"certform", OPT_CERTFORM, 's',
+ "Format (PEM or DER) to use when saving a certificate to a file. Default PEM"},
+ {"keyform", OPT_KEYFORM, 's',
+ "Format of the key input (ENGINE, other values ignored)"},
+ {"otherpass", OPT_OTHERPASS, 's',
+ "Pass phrase source potentially needed for loading certificates of others"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's',
+ "Use crypto engine with given identifier, possibly a hardware device."},
+ {OPT_MORE_STR, 0, 0,
+ "Engines may also be defined in OpenSSL config file engine section."},
+#endif
+ OPT_PROV_OPTIONS,
+ OPT_R_OPTIONS,
+
+ OPT_SECTION("TLS connection"),
+#ifdef OPENSSL_NO_SOCK
+ {OPT_MORE_STR, 0, 0,
+ "NOTE: -tls_used and all other TLS options not supported due to no-sock build"},
+#else
+ {"tls_used", OPT_TLS_USED, '-',
+ "Enable using TLS (also when other TLS options are not set)"},
+ {"tls_cert", OPT_TLS_CERT, 's',
+ "Client's TLS certificate. May include chain to be provided to TLS server"},
+ {"tls_key", OPT_TLS_KEY, 's',
+ "Private key for the client's TLS certificate"},
+ {"tls_keypass", OPT_TLS_KEYPASS, 's',
+ "Pass phrase source for the client's private TLS key (and TLS cert)"},
+ {"tls_extra", OPT_TLS_EXTRA, 's',
+ "Extra certificates to provide to TLS server during TLS handshake"},
+ {"tls_trusted", OPT_TLS_TRUSTED, 's',
+ "Trusted certificates to use for verifying the TLS server certificate;"},
+ {OPT_MORE_STR, 0, 0, "this implies host name validation"},
+ {"tls_host", OPT_TLS_HOST, 's',
+ "Address to be checked (rather than -server) during TLS host name validation"},
+#endif
+
+ OPT_SECTION("Client-side debugging"),
+ {"batch", OPT_BATCH, '-',
+ "Do not interactively prompt for input when a password is required etc."},
+ {"repeat", OPT_REPEAT, 'p',
+ "Invoke the transaction the given positive number of times. Default 1"},
+ {"reqin", OPT_REQIN, 's', "Take sequence of CMP requests from file(s)"},
+ {"reqin_new_tid", OPT_REQIN_NEW_TID, '-',
+ "Use fresh transactionID for CMP requests read from -reqin"},
+ {"reqout", OPT_REQOUT, 's', "Save sequence of CMP requests to file(s)"},
+ {"rspin", OPT_RSPIN, 's',
+ "Process sequence of CMP responses provided in file(s), skipping server"},
+ {"rspout", OPT_RSPOUT, 's', "Save sequence of CMP responses to file(s)"},
+
+ {"use_mock_srv", OPT_USE_MOCK_SRV, '-',
+ "Use internal mock server at API level, bypassing socket-based HTTP"},
+
+ OPT_SECTION("Mock server"),
+#ifdef OPENSSL_NO_SOCK
+ {OPT_MORE_STR, 0, 0,
+ "NOTE: -port and -max_msgs not supported due to no-sock build"},
+#else
+ {"port", OPT_PORT, 's',
+ "Act as HTTP-based mock server listening on given port"},
+ {"max_msgs", OPT_MAX_MSGS, 'N',
+ "max number of messages handled by HTTP mock server. Default: 0 = unlimited"},
+#endif
+
+ {"srv_ref", OPT_SRV_REF, 's',
+ "Reference value to use as senderKID of server in case no -srv_cert is given"},
+ {"srv_secret", OPT_SRV_SECRET, 's',
+ "Password source for server authentication with a pre-shared key (secret)"},
+ {"srv_cert", OPT_SRV_CERT, 's', "Certificate of the server"},
+ {"srv_key", OPT_SRV_KEY, 's',
+ "Private key used by the server for signing messages"},
+ {"srv_keypass", OPT_SRV_KEYPASS, 's',
+ "Server private key (and cert) pass phrase source"},
+
+ {"srv_trusted", OPT_SRV_TRUSTED, 's',
+ "Trusted certificates for client authentication"},
+ {"srv_untrusted", OPT_SRV_UNTRUSTED, 's',
+ "Intermediate certs that may be useful for verifying CMP protection"},
+ {"rsp_cert", OPT_RSP_CERT, 's',
+ "Certificate to be returned as mock enrollment result"},
+ {"rsp_extracerts", OPT_RSP_EXTRACERTS, 's',
+ "Extra certificates to be included in mock certification responses"},
+ {"rsp_capubs", OPT_RSP_CAPUBS, 's',
+ "CA certificates to be included in mock ip response"},
+ {"poll_count", OPT_POLL_COUNT, 'N',
+ "Number of times the client must poll before receiving a certificate"},
+ {"check_after", OPT_CHECK_AFTER, 'N',
+ "The check_after value (time to wait) to include in poll response"},
+ {"grant_implicitconf", OPT_GRANT_IMPLICITCONF, '-',
+ "Grant implicit confirmation of newly enrolled certificate"},
+
+ {"pkistatus", OPT_PKISTATUS, 'N',
+ "PKIStatus to be included in server response. Possible values: 0..6"},
+ {"failure", OPT_FAILURE, 'N',
+ "A single failure info bit number to include in server response, 0..26"},
+ {"failurebits", OPT_FAILUREBITS, 'N',
+ "Number representing failure bits to include in server response, 0..2^27 - 1"},
+ {"statusstring", OPT_STATUSSTRING, 's',
+ "Status string to be included in server response"},
+ {"send_error", OPT_SEND_ERROR, '-',
+ "Force server to reply with error message"},
+ {"send_unprotected", OPT_SEND_UNPROTECTED, '-',
+ "Send response messages without CMP-level protection"},
+ {"send_unprot_err", OPT_SEND_UNPROT_ERR, '-',
+ "In case of negative responses, server shall send unprotected error messages,"},
+ {OPT_MORE_STR, 0, 0,
+ "certificate responses (ip/cp/kup), and revocation responses (rp)."},
+ {OPT_MORE_STR, 0, 0,
+ "WARNING: This setting leads to behavior violating RFC 4210"},
+ {"accept_unprotected", OPT_ACCEPT_UNPROTECTED, '-',
+ "Accept missing or invalid protection of requests"},
+ {"accept_unprot_err", OPT_ACCEPT_UNPROT_ERR, '-',
+ "Accept unprotected error messages from client"},
+ {"accept_raverified", OPT_ACCEPT_RAVERIFIED, '-',
+ "Accept RAVERIFIED as proof-of-possession (POPO)"},
+
+ OPT_V_OPTIONS,
+ {NULL}
+};
+
+typedef union {
+ char **txt;
+ int *num;
+ long *num_long;
+} varref;
+static varref cmp_vars[] = { /* must be in same order as enumerated above! */
+ {&opt_config}, {&opt_section}, {(char **)&opt_verbosity},
+
+ {&opt_cmd_s}, {&opt_infotype_s}, {&opt_geninfo},
+
+ {&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {&opt_issuer},
+ {(char **)&opt_days}, {&opt_reqexts},
+ {&opt_sans}, {(char **)&opt_san_nodefault},
+ {&opt_policies}, {&opt_policy_oids}, {(char **)&opt_policy_oids_critical},
+ {(char **)&opt_popo}, {&opt_csr},
+ {&opt_out_trusted},
+ {(char **)&opt_implicit_confirm}, {(char **)&opt_disable_confirm},
+ {&opt_certout}, {&opt_chainout},
+
+ {&opt_oldcert}, {(char **)&opt_revreason},
+
+#ifndef OPENSSL_NO_SOCK
+ {&opt_server}, {&opt_proxy}, {&opt_no_proxy},
+#endif
+ {&opt_recipient}, {&opt_path}, {(char **)&opt_keep_alive},
+ {(char **)&opt_msg_timeout}, {(char **)&opt_total_timeout},
+
+ {&opt_trusted}, {&opt_untrusted}, {&opt_srvcert},
+ {&opt_expect_sender},
+ {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors},
+ {&opt_extracertsout}, {&opt_cacertsout},
+
+ {&opt_ref}, {&opt_secret},
+ {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
+ {&opt_digest}, {&opt_mac}, {&opt_extracerts},
+ {(char **)&opt_unprotected_requests},
+
+ {&opt_certform_s}, {&opt_keyform_s},
+ {&opt_otherpass},
+#ifndef OPENSSL_NO_ENGINE
+ {&opt_engine},
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+ {(char **)&opt_tls_used}, {&opt_tls_cert}, {&opt_tls_key},
+ {&opt_tls_keypass},
+ {&opt_tls_extra}, {&opt_tls_trusted}, {&opt_tls_host},
+#endif
+
+ {(char **)&opt_batch}, {(char **)&opt_repeat},
+ {&opt_reqin}, {(char **)&opt_reqin_new_tid},
+ {&opt_reqout}, {&opt_rspin}, {&opt_rspout},
+
+ {(char **)&opt_use_mock_srv},
+#ifndef OPENSSL_NO_SOCK
+ {&opt_port}, {(char **)&opt_max_msgs},
+#endif
+ {&opt_srv_ref}, {&opt_srv_secret},
+ {&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
+ {&opt_srv_trusted}, {&opt_srv_untrusted},
+ {&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs},
+ {(char **)&opt_poll_count}, {(char **)&opt_check_after},
+ {(char **)&opt_grant_implicitconf},
+ {(char **)&opt_pkistatus}, {(char **)&opt_failure},
+ {(char **)&opt_failurebits}, {&opt_statusstring},
+ {(char **)&opt_send_error}, {(char **)&opt_send_unprotected},
+ {(char **)&opt_send_unprot_err}, {(char **)&opt_accept_unprotected},
+ {(char **)&opt_accept_unprot_err}, {(char **)&opt_accept_raverified},
+
+ {NULL}
+};
+
+#define FUNC (strcmp(OPENSSL_FUNC, "(unknown function)") == 0 \
+ ? "CMP" : OPENSSL_FUNC)
+#define CMP_print(bio, level, prefix, msg, a1, a2, a3) \
+ ((void)(level > opt_verbosity ? 0 : \
+ (BIO_printf(bio, "%s:%s:%d:CMP %s: " msg "\n", \
+ FUNC, OPENSSL_FILE, OPENSSL_LINE, prefix, a1, a2, a3))))
+#define CMP_DEBUG(m, a1, a2, a3) \
+ CMP_print(bio_out, OSSL_CMP_LOG_DEBUG, "debug", m, a1, a2, a3)
+#define CMP_debug(msg) CMP_DEBUG(msg"%s%s%s", "", "", "")
+#define CMP_debug1(msg, a1) CMP_DEBUG(msg"%s%s", a1, "", "")
+#define CMP_debug2(msg, a1, a2) CMP_DEBUG(msg"%s", a1, a2, "")
+#define CMP_debug3(msg, a1, a2, a3) CMP_DEBUG(msg, a1, a2, a3)
+#define CMP_INFO(msg, a1, a2, a3) \
+ CMP_print(bio_out, OSSL_CMP_LOG_INFO, "info", msg, a1, a2, a3)
+#define CMP_info(msg) CMP_INFO(msg"%s%s%s", "", "", "")
+#define CMP_info1(msg, a1) CMP_INFO(msg"%s%s", a1, "", "")
+#define CMP_info2(msg, a1, a2) CMP_INFO(msg"%s", a1, a2, "")
+#define CMP_info3(msg, a1, a2, a3) CMP_INFO(msg, a1, a2, a3)
+#define CMP_WARN(m, a1, a2, a3) \
+ CMP_print(bio_out, OSSL_CMP_LOG_WARNING, "warning", m, a1, a2, a3)
+#define CMP_warn(msg) CMP_WARN(msg"%s%s%s", "", "", "")
+#define CMP_warn1(msg, a1) CMP_WARN(msg"%s%s", a1, "", "")
+#define CMP_warn2(msg, a1, a2) CMP_WARN(msg"%s", a1, a2, "")
+#define CMP_warn3(msg, a1, a2, a3) CMP_WARN(msg, a1, a2, a3)
+#define CMP_ERR(msg, a1, a2, a3) \
+ CMP_print(bio_err, OSSL_CMP_LOG_ERR, "error", msg, a1, a2, a3)
+#define CMP_err(msg) CMP_ERR(msg"%s%s%s", "", "", "")
+#define CMP_err1(msg, a1) CMP_ERR(msg"%s%s", a1, "", "")
+#define CMP_err2(msg, a1, a2) CMP_ERR(msg"%s", a1, a2, "")
+#define CMP_err3(msg, a1, a2, a3) CMP_ERR(msg, a1, a2, a3)
+
+static int print_to_bio_out(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg)
+{
+ return OSSL_CMP_print_to_bio(bio_out, func, file, line, level, msg);
+}
+
+static int print_to_bio_err(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg)
+{
+ return OSSL_CMP_print_to_bio(bio_err, func, file, line, level, msg);
+}
+
+static int set_verbosity(int level)
+{
+ if (level < OSSL_CMP_LOG_EMERG || level > OSSL_CMP_LOG_MAX) {
+ CMP_err1("Logging verbosity level %d out of range (0 .. 8)", level);
+ return 0;
+ }
+ opt_verbosity = level;
+ return 1;
+}
+
+static EVP_PKEY *load_key_pwd(const char *uri, int format,
+ const char *pass, ENGINE *eng, const char *desc)
+{
+ char *pass_string = get_passwd(pass, desc);
+ EVP_PKEY *pkey = load_key(uri, format, 0, pass_string, eng, desc);
+
+ clear_free(pass_string);
+ return pkey;
+}
+
+static X509 *load_cert_pwd(const char *uri, const char *pass, const char *desc)
+{
+ X509 *cert;
+ char *pass_string = get_passwd(pass, desc);
+
+ cert = load_cert_pass(uri, FORMAT_UNDEF, 0, pass_string, desc);
+ clear_free(pass_string);
+ return cert;
+}
+
+static X509_REQ *load_csr_autofmt(const char *infile, const char *desc)
+{
+ X509_REQ *csr;
+ BIO *bio_bak = bio_err;
+
+ bio_err = NULL; /* do not show errors on more than one try */
+ csr = load_csr(infile, FORMAT_PEM, desc);
+ bio_err = bio_bak;
+ if (csr == NULL) {
+ ERR_clear_error();
+ csr = load_csr(infile, FORMAT_ASN1, desc);
+ }
+ if (csr == NULL) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "error: unable to load %s from file '%s'\n", desc,
+ infile);
+ } else {
+ EVP_PKEY *pkey = X509_REQ_get0_pubkey(csr);
+ int ret = do_X509_REQ_verify(csr, pkey, NULL /* vfyopts */);
+
+ if (pkey == NULL || ret < 0)
+ CMP_warn("error while verifying CSR self-signature");
+ else if (ret == 0)
+ CMP_warn("CSR self-signature does not match the contents");
+ }
+ return csr;
+}
+
+/* set expected host name/IP addr and clears the email addr in the given ts */
+static int truststore_set_host_etc(X509_STORE *ts, const char *host)
+{
+ X509_VERIFY_PARAM *ts_vpm = X509_STORE_get0_param(ts);
+
+ /* first clear any host names, IP, and email addresses */
+ if (!X509_VERIFY_PARAM_set1_host(ts_vpm, NULL, 0)
+ || !X509_VERIFY_PARAM_set1_ip(ts_vpm, NULL, 0)
+ || !X509_VERIFY_PARAM_set1_email(ts_vpm, NULL, 0))
+ return 0;
+ X509_VERIFY_PARAM_set_hostflags(ts_vpm,
+ X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT |
+ X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ return (host != NULL && X509_VERIFY_PARAM_set1_ip_asc(ts_vpm, host))
+ || X509_VERIFY_PARAM_set1_host(ts_vpm, host, 0);
+}
+
+/* write OSSL_CMP_MSG DER-encoded to the specified file name item */
+static int write_PKIMESSAGE(const OSSL_CMP_MSG *msg, char **filenames)
+{
+ char *file;
+
+ if (msg == NULL || filenames == NULL) {
+ CMP_err("NULL arg to write_PKIMESSAGE");
+ return 0;
+ }
+ if (*filenames == NULL) {
+ CMP_err("not enough file names provided for writing PKIMessage");
+ return 0;
+ }
+
+ file = *filenames;
+ *filenames = next_item(file);
+ if (OSSL_CMP_MSG_write(file, msg) < 0) {
+ CMP_err1("cannot write PKIMessage to file '%s'", file);
+ return 0;
+ }
+ return 1;
+}
+
+/* read DER-encoded OSSL_CMP_MSG from the specified file name item */
+static OSSL_CMP_MSG *read_PKIMESSAGE(char **filenames)
+{
+ char *file;
+ OSSL_CMP_MSG *ret;
+
+ if (filenames == NULL) {
+ CMP_err("NULL arg to read_PKIMESSAGE");
+ return NULL;
+ }
+ if (*filenames == NULL) {
+ CMP_err("not enough file names provided for reading PKIMessage");
+ return NULL;
+ }
+
+ file = *filenames;
+ *filenames = next_item(file);
+
+ ret = OSSL_CMP_MSG_read(file, app_get0_libctx(), app_get0_propq());
+ if (ret == NULL)
+ CMP_err1("cannot read PKIMessage from file '%s'", file);
+ return ret;
+}
+
+/*-
+ * Sends the PKIMessage req and on success place the response in *res
+ * basically like OSSL_CMP_MSG_http_perform(), but in addition allows
+ * to dump the sequence of requests and responses to files and/or
+ * to take the sequence of requests and responses from files.
+ */
+static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_MSG *req_new = NULL;
+ OSSL_CMP_MSG *res = NULL;
+ OSSL_CMP_PKIHEADER *hdr;
+ const char *prev_opt_rspin = opt_rspin;
+
+ if (req != NULL && opt_reqout != NULL
+ && !write_PKIMESSAGE(req, &opt_reqout))
+ goto err;
+ if (opt_reqin != NULL && opt_rspin == NULL) {
+ if ((req_new = read_PKIMESSAGE(&opt_reqin)) == NULL)
+ goto err;
+ /*-
+ * The transaction ID in req_new read from opt_reqin may not be fresh.
+ * In this case the server may complain "Transaction id already in use."
+ * The following workaround unfortunately requires re-protection.
+ */
+ if (opt_reqin_new_tid
+ && !OSSL_CMP_MSG_update_transactionID(ctx, req_new))
+ goto err;
+ }
+
+ if (opt_rspin != NULL) {
+ res = read_PKIMESSAGE(&opt_rspin);
+ } else {
+ const OSSL_CMP_MSG *actual_req = opt_reqin != NULL ? req_new : req;
+
+ res = opt_use_mock_srv
+ ? OSSL_CMP_CTX_server_perform(ctx, actual_req)
+ : OSSL_CMP_MSG_http_perform(ctx, actual_req);
+ }
+ if (res == NULL)
+ goto err;
+
+ if (opt_reqin != NULL || prev_opt_rspin != NULL) {
+ /* need to satisfy nonce and transactionID checks */
+ ASN1_OCTET_STRING *nonce;
+ ASN1_OCTET_STRING *tid;
+
+ hdr = OSSL_CMP_MSG_get0_header(res);
+ nonce = OSSL_CMP_HDR_get0_recipNonce(hdr);
+ tid = OSSL_CMP_HDR_get0_transactionID(hdr);
+ if (!OSSL_CMP_CTX_set1_senderNonce(ctx, nonce)
+ || !OSSL_CMP_CTX_set1_transactionID(ctx, tid)) {
+ OSSL_CMP_MSG_free(res);
+ res = NULL;
+ goto err;
+ }
+ }
+
+ if (opt_rspout != NULL && !write_PKIMESSAGE(res, &opt_rspout)) {
+ OSSL_CMP_MSG_free(res);
+ res = NULL;
+ }
+
+ err:
+ OSSL_CMP_MSG_free(req_new);
+ return res;
+}
+
+static int set_name(const char *str,
+ int (*set_fn) (OSSL_CMP_CTX *ctx, const X509_NAME *name),
+ OSSL_CMP_CTX *ctx, const char *desc)
+{
+ if (str != NULL) {
+ X509_NAME *n = parse_name(str, MBSTRING_ASC, 1, desc);
+
+ if (n == NULL)
+ return 0;
+ if (!(*set_fn) (ctx, n)) {
+ X509_NAME_free(n);
+ CMP_err("out of memory");
+ return 0;
+ }
+ X509_NAME_free(n);
+ }
+ return 1;
+}
+
+static int set_gennames(OSSL_CMP_CTX *ctx, char *names, const char *desc)
+{
+ char *next;
+
+ for (; names != NULL; names = next) {
+ GENERAL_NAME *n;
+
+ next = next_item(names);
+ if (strcmp(names, "critical") == 0) {
+ (void)OSSL_CMP_CTX_set_option(ctx,
+ OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL,
+ 1);
+ continue;
+ }
+
+ /* try IP address first, then URI or domain name */
+ (void)ERR_set_mark();
+ n = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_IPADD, names, 0);
+ if (n == NULL)
+ n = a2i_GENERAL_NAME(NULL, NULL, NULL,
+ strchr(names, ':') != NULL ? GEN_URI : GEN_DNS,
+ names, 0);
+ (void)ERR_pop_to_mark();
+
+ if (n == NULL) {
+ CMP_err2("bad syntax of %s '%s'", desc, names);
+ return 0;
+ }
+ if (!OSSL_CMP_CTX_push1_subjectAltName(ctx, n)) {
+ GENERAL_NAME_free(n);
+ CMP_err("out of memory");
+ return 0;
+ }
+ GENERAL_NAME_free(n);
+ }
+ return 1;
+}
+
+static X509_STORE *load_trusted(char *input, int for_new_cert, const char *desc)
+{
+ X509_STORE *ts = load_certstore(input, opt_otherpass, desc, vpm);
+
+ if (ts == NULL)
+ return NULL;
+ X509_STORE_set_verify_cb(ts, X509_STORE_CTX_print_verify_cb);
+
+ /* copy vpm to store */
+ if (X509_STORE_set1_param(ts, vpm /* may be NULL */)
+ && (for_new_cert || truststore_set_host_etc(ts, NULL)))
+ return ts;
+ BIO_printf(bio_err, "error setting verification parameters for %s\n", desc);
+ OSSL_CMP_CTX_print_errors(cmp_ctx);
+ X509_STORE_free(ts);
+ return NULL;
+}
+
+typedef int (*add_X509_stack_fn_t)(void *ctx, const STACK_OF(X509) *certs);
+
+static int setup_certs(char *files, const char *desc, void *ctx,
+ add_X509_stack_fn_t set1_fn)
+{
+ STACK_OF(X509) *certs;
+ int ok;
+
+ if (files == NULL)
+ return 1;
+ if ((certs = load_certs_multifile(files, opt_otherpass, desc, vpm)) == NULL)
+ return 0;
+ ok = (*set1_fn)(ctx, certs);
+ sk_X509_pop_free(certs, X509_free);
+ return ok;
+}
+
+
+/*
+ * parse and transform some options, checking their syntax.
+ * Returns 1 on success, 0 on error
+ */
+static int transform_opts(void)
+{
+ if (opt_cmd_s != NULL) {
+ if (!strcmp(opt_cmd_s, "ir")) {
+ opt_cmd = CMP_IR;
+ } else if (!strcmp(opt_cmd_s, "kur")) {
+ opt_cmd = CMP_KUR;
+ } else if (!strcmp(opt_cmd_s, "cr")) {
+ opt_cmd = CMP_CR;
+ } else if (!strcmp(opt_cmd_s, "p10cr")) {
+ opt_cmd = CMP_P10CR;
+ } else if (!strcmp(opt_cmd_s, "rr")) {
+ opt_cmd = CMP_RR;
+ } else if (!strcmp(opt_cmd_s, "genm")) {
+ opt_cmd = CMP_GENM;
+ } else {
+ CMP_err1("unknown cmp command '%s'", opt_cmd_s);
+ return 0;
+ }
+ } else {
+ CMP_err("no cmp command to execute");
+ return 0;
+ }
+
+#ifndef OPENSSL_NO_ENGINE
+# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_ENGINE)
+#else
+# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12)
+#endif
+
+ if (opt_keyform_s != NULL
+ && !opt_format(opt_keyform_s, FORMAT_OPTIONS, &opt_keyform)) {
+ CMP_err("unknown option given for key loading format");
+ return 0;
+ }
+
+#undef FORMAT_OPTIONS
+
+ if (opt_certform_s != NULL
+ && !opt_format(opt_certform_s, OPT_FMT_PEMDER, &opt_certform)) {
+ CMP_err("unknown option given for certificate storing format");
+ return 0;
+ }
+
+ return 1;
+}
+
+static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
+{
+ OSSL_CMP_CTX *ctx; /* extra CMP (client) ctx partly used by server */
+ OSSL_CMP_SRV_CTX *srv_ctx = ossl_cmp_mock_srv_new(app_get0_libctx(),
+ app_get0_propq());
+
+ if (srv_ctx == NULL)
+ return NULL;
+ ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx);
+
+ if (opt_srv_ref == NULL) {
+ if (opt_srv_cert == NULL) {
+ /* opt_srv_cert should determine the sender */
+ CMP_err("must give -srv_ref for mock server if no -srv_cert given");
+ goto err;
+ }
+ } else {
+ if (!OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_srv_ref,
+ strlen(opt_srv_ref)))
+ goto err;
+ }
+
+ if (opt_srv_secret != NULL) {
+ int res;
+ char *pass_str = get_passwd(opt_srv_secret, "PBMAC secret of mock server");
+
+ if (pass_str != NULL) {
+ cleanse(opt_srv_secret);
+ res = OSSL_CMP_CTX_set1_secretValue(ctx, (unsigned char *)pass_str,
+ strlen(pass_str));
+ clear_free(pass_str);
+ if (res == 0)
+ goto err;
+ }
+ } else if (opt_srv_cert == NULL) {
+ CMP_err("mock server credentials must be given if -use_mock_srv or -port is used");
+ goto err;
+ } else {
+ CMP_warn("mock server will not be able to handle PBM-protected requests since -srv_secret is not given");
+ }
+
+ if (opt_srv_secret == NULL
+ && ((opt_srv_cert == NULL) != (opt_srv_key == NULL))) {
+ CMP_err("must give both -srv_cert and -srv_key options or neither");
+ goto err;
+ }
+ if (opt_srv_cert != NULL) {
+ X509 *srv_cert = load_cert_pwd(opt_srv_cert, opt_srv_keypass,
+ "certificate of the mock server");
+
+ if (srv_cert == NULL || !OSSL_CMP_CTX_set1_cert(ctx, srv_cert)) {
+ X509_free(srv_cert);
+ goto err;
+ }
+ X509_free(srv_cert);
+ }
+ if (opt_srv_key != NULL) {
+ EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform,
+ opt_srv_keypass,
+ engine, "private key for mock server cert");
+
+ if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) {
+ EVP_PKEY_free(pkey);
+ goto err;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ cleanse(opt_srv_keypass);
+
+ if (opt_srv_trusted != NULL) {
+ X509_STORE *ts =
+ load_trusted(opt_srv_trusted, 0, "certs trusted by mock server");
+
+ if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) {
+ X509_STORE_free(ts);
+ goto err;
+ }
+ } else {
+ CMP_warn("mock server will not be able to handle signature-protected requests since -srv_trusted is not given");
+ }
+ if (!setup_certs(opt_srv_untrusted,
+ "untrusted certificates for mock server", ctx,
+ (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
+ goto err;
+
+ if (opt_rsp_cert == NULL) {
+ CMP_warn("no -rsp_cert given for mock server");
+ } else {
+ X509 *cert = load_cert_pwd(opt_rsp_cert, opt_keypass,
+ "cert to be returned by the mock server");
+
+ if (cert == NULL)
+ goto err;
+ /* from server perspective the server is the client */
+ if (!ossl_cmp_mock_srv_set1_certOut(srv_ctx, cert)) {
+ X509_free(cert);
+ goto err;
+ }
+ X509_free(cert);
+ }
+ if (!setup_certs(opt_rsp_extracerts,
+ "CMP extra certificates for mock server", srv_ctx,
+ (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_chainOut))
+ goto err;
+ if (!setup_certs(opt_rsp_capubs, "caPubs for mock server", srv_ctx,
+ (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_caPubsOut))
+ goto err;
+ (void)ossl_cmp_mock_srv_set_pollCount(srv_ctx, opt_poll_count);
+ (void)ossl_cmp_mock_srv_set_checkAfterTime(srv_ctx, opt_check_after);
+ if (opt_grant_implicitconf)
+ (void)OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(srv_ctx, 1);
+
+ if (opt_failure != INT_MIN) { /* option has been set explicity */
+ if (opt_failure < 0 || OSSL_CMP_PKIFAILUREINFO_MAX < opt_failure) {
+ CMP_err1("-failure out of range, should be >= 0 and <= %d",
+ OSSL_CMP_PKIFAILUREINFO_MAX);
+ goto err;
+ }
+ if (opt_failurebits != 0)
+ CMP_warn("-failurebits overrides -failure");
+ else
+ opt_failurebits = 1 << opt_failure;
+ }
+ if ((unsigned)opt_failurebits > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
+ CMP_err("-failurebits out of range");
+ goto err;
+ }
+ if (!ossl_cmp_mock_srv_set_statusInfo(srv_ctx, opt_pkistatus,
+ opt_failurebits, opt_statusstring))
+ goto err;
+
+ if (opt_send_error)
+ (void)ossl_cmp_mock_srv_set_send_error(srv_ctx, 1);
+
+ if (opt_send_unprotected)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1);
+ if (opt_send_unprot_err)
+ (void)OSSL_CMP_SRV_CTX_set_send_unprotected_errors(srv_ctx, 1);
+ if (opt_accept_unprotected)
+ (void)OSSL_CMP_SRV_CTX_set_accept_unprotected(srv_ctx, 1);
+ if (opt_accept_unprot_err)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
+ if (opt_accept_raverified)
+ (void)OSSL_CMP_SRV_CTX_set_accept_raverified(srv_ctx, 1);
+
+ return srv_ctx;
+
+ err:
+ ossl_cmp_mock_srv_free(srv_ctx);
+ return NULL;
+}
+
+/*
+ * set up verification aspects of OSSL_CMP_CTX w.r.t. opts from config file/CLI.
+ * Returns pointer on success, NULL on error
+ */
+static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
+{
+ if (!setup_certs(opt_untrusted, "untrusted certificates", ctx,
+ (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
+ return 0;
+
+ if (opt_srvcert != NULL || opt_trusted != NULL) {
+ X509 *srvcert;
+ X509_STORE *ts;
+ int ok;
+
+ if (opt_srvcert != NULL) {
+ if (opt_trusted != NULL) {
+ CMP_warn("-trusted option is ignored since -srvcert option is present");
+ opt_trusted = NULL;
+ }
+ if (opt_recipient != NULL) {
+ CMP_warn("-recipient option is ignored since -srvcert option is present");
+ opt_recipient = NULL;
+ }
+ srvcert = load_cert_pwd(opt_srvcert, opt_otherpass,
+ "directly trusted CMP server certificate");
+ ok = srvcert != NULL && OSSL_CMP_CTX_set1_srvCert(ctx, srvcert);
+ X509_free(srvcert);
+ if (!ok)
+ return 0;
+ }
+ if (opt_trusted != NULL) {
+ /*
+ * the 0 arg below clears any expected host/ip/email address;
+ * opt_expect_sender is used instead
+ */
+ ts = load_trusted(opt_trusted, 0, "certs trusted by client");
+
+ if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) {
+ X509_STORE_free(ts);
+ return 0;
+ }
+ }
+ }
+
+ if (opt_ignore_keyusage)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IGNORE_KEYUSAGE, 1);
+
+ if (opt_unprotected_errors)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
+
+ if (opt_out_trusted != NULL) { /* for use in OSSL_CMP_certConf_cb() */
+ X509_VERIFY_PARAM *out_vpm = NULL;
+ X509_STORE *out_trusted =
+ load_trusted(opt_out_trusted, 1,
+ "trusted certs for verifying newly enrolled cert");
+
+ if (out_trusted == NULL)
+ return 0;
+ /* ignore any -attime here, new certs are current anyway */
+ out_vpm = X509_STORE_get0_param(out_trusted);
+ X509_VERIFY_PARAM_clear_flags(out_vpm, X509_V_FLAG_USE_CHECK_TIME);
+
+ (void)OSSL_CMP_CTX_set_certConf_cb_arg(ctx, out_trusted);
+ }
+
+ if (opt_disable_confirm)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DISABLE_CONFIRM, 1);
+
+ if (opt_implicit_confirm)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM, 1);
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SOCK
+/*
+ * set up ssl_ctx for the OSSL_CMP_CTX based on options from config file/CLI.
+ * Returns pointer on success, NULL on error
+ */
+static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host,
+ ENGINE *engine)
+{
+ STACK_OF(X509) *untrusted = OSSL_CMP_CTX_get0_untrusted(ctx);
+ EVP_PKEY *pkey = NULL;
+ X509_STORE *trust_store = NULL;
+ SSL_CTX *ssl_ctx;
+ int i;
+
+ ssl_ctx = SSL_CTX_new(TLS_client_method());
+ if (ssl_ctx == NULL)
+ return NULL;
+
+ if (opt_tls_trusted != NULL) {
+ trust_store = load_trusted(opt_tls_trusted, 0, "trusted TLS certs");
+ if (trust_store == NULL)
+ goto err;
+ SSL_CTX_set_cert_store(ssl_ctx, trust_store);
+ }
+
+ if (opt_tls_cert != NULL && opt_tls_key != NULL) {
+ X509 *cert;
+ STACK_OF(X509) *certs = NULL;
+ int ok;
+
+ if (!load_cert_certs(opt_tls_cert, &cert, &certs, 0, opt_tls_keypass,
+ "TLS client certificate (optionally with chain)",
+ vpm))
+ /* need opt_tls_keypass if opt_tls_cert is encrypted PKCS#12 file */
+ goto err;
+
+ ok = SSL_CTX_use_certificate(ssl_ctx, cert) > 0;
+ X509_free(cert);
+
+ /*
+ * Any further certs and any untrusted certs are used for constructing
+ * the chain to be provided with the TLS client cert to the TLS server.
+ */
+ if (!ok || !SSL_CTX_set0_chain(ssl_ctx, certs)) {
+ CMP_err1("unable to use client TLS certificate file '%s'",
+ opt_tls_cert);
+ sk_X509_pop_free(certs, X509_free);
+ goto err;
+ }
+ for (i = 0; i < sk_X509_num(untrusted); i++) {
+ cert = sk_X509_value(untrusted, i);
+ if (!SSL_CTX_add1_chain_cert(ssl_ctx, cert)) {
+ CMP_err("could not add untrusted cert to TLS client cert chain");
+ goto err;
+ }
+ }
+
+ {
+ X509_VERIFY_PARAM *tls_vpm = NULL;
+ unsigned long bak_flags = 0; /* compiler warns without init */
+
+ if (trust_store != NULL) {
+ tls_vpm = X509_STORE_get0_param(trust_store);
+ bak_flags = X509_VERIFY_PARAM_get_flags(tls_vpm);
+ /* disable any cert status/revocation checking etc. */
+ X509_VERIFY_PARAM_clear_flags(tls_vpm,
+ ~(X509_V_FLAG_USE_CHECK_TIME
+ | X509_V_FLAG_NO_CHECK_TIME));
+ }
+ CMP_debug("trying to build cert chain for own TLS cert");
+ if (SSL_CTX_build_cert_chain(ssl_ctx,
+ SSL_BUILD_CHAIN_FLAG_UNTRUSTED |
+ SSL_BUILD_CHAIN_FLAG_NO_ROOT)) {
+ CMP_debug("success building cert chain for own TLS cert");
+ } else {
+ OSSL_CMP_CTX_print_errors(ctx);
+ CMP_warn("could not build cert chain for own TLS cert");
+ }
+ if (trust_store != NULL)
+ X509_VERIFY_PARAM_set_flags(tls_vpm, bak_flags);
+ }
+
+ /* If present we append to the list also the certs from opt_tls_extra */
+ if (opt_tls_extra != NULL) {
+ STACK_OF(X509) *tls_extra = load_certs_multifile(opt_tls_extra,
+ opt_otherpass,
+ "extra certificates for TLS",
+ vpm);
+ int res = 1;
+
+ if (tls_extra == NULL)
+ goto err;
+ for (i = 0; i < sk_X509_num(tls_extra); i++) {
+ cert = sk_X509_value(tls_extra, i);
+ if (res != 0)
+ res = SSL_CTX_add_extra_chain_cert(ssl_ctx, cert);
+ if (res == 0)
+ X509_free(cert);
+ }
+ sk_X509_free(tls_extra);
+ if (res == 0) {
+ BIO_printf(bio_err, "error: unable to add TLS extra certs\n");
+ goto err;
+ }
+ }
+
+ pkey = load_key_pwd(opt_tls_key, opt_keyform, opt_tls_keypass,
+ engine, "TLS client private key");
+ cleanse(opt_tls_keypass);
+ if (pkey == NULL)
+ goto err;
+ /*
+ * verify the key matches the cert,
+ * not using SSL_CTX_check_private_key(ssl_ctx)
+ * because it gives poor and sometimes misleading diagnostics
+ */
+ if (!X509_check_private_key(SSL_CTX_get0_certificate(ssl_ctx),
+ pkey)) {
+ CMP_err2("TLS private key '%s' does not match the TLS certificate '%s'\n",
+ opt_tls_key, opt_tls_cert);
+ EVP_PKEY_free(pkey);
+ pkey = NULL; /* otherwise, for some reason double free! */
+ goto err;
+ }
+ if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) <= 0) {
+ CMP_err1("unable to use TLS client private key '%s'", opt_tls_key);
+ EVP_PKEY_free(pkey);
+ pkey = NULL; /* otherwise, for some reason double free! */
+ goto err;
+ }
+ EVP_PKEY_free(pkey); /* we do not need the handle any more */
+ }
+ if (opt_tls_trusted != NULL) {
+ /* enable and parameterize server hostname/IP address check */
+ if (!truststore_set_host_etc(trust_store,
+ opt_tls_host != NULL ? opt_tls_host : host))
+ goto err;
+ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+ }
+ return ssl_ctx;
+ err:
+ SSL_CTX_free(ssl_ctx);
+ return NULL;
+}
+#endif /* OPENSSL_NO_SOCK */
+
+/*
+ * set up protection aspects of OSSL_CMP_CTX based on options from config
+ * file/CLI while parsing options and checking their consistency.
+ * Returns 1 on success, 0 on error
+ */
+static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
+{
+ if (!opt_unprotected_requests && opt_secret == NULL && opt_key == NULL) {
+ CMP_err("must give -key or -secret unless -unprotected_requests is used");
+ return 0;
+ }
+
+ if (opt_ref == NULL && opt_cert == NULL && opt_subject == NULL) {
+ /* cert or subject should determine the sender */
+ CMP_err("must give -ref if no -cert and no -subject given");
+ return 0;
+ }
+ if (!opt_secret && ((opt_cert == NULL) != (opt_key == NULL))) {
+ CMP_err("must give both -cert and -key options or neither");
+ return 0;
+ }
+ if (opt_secret != NULL) {
+ char *pass_string = get_passwd(opt_secret, "PBMAC");
+ int res;
+
+ if (pass_string != NULL) {
+ cleanse(opt_secret);
+ res = OSSL_CMP_CTX_set1_secretValue(ctx,
+ (unsigned char *)pass_string,
+ strlen(pass_string));
+ clear_free(pass_string);
+ if (res == 0)
+ return 0;
+ }
+ if (opt_cert != NULL || opt_key != NULL)
+ CMP_warn("-cert and -key not used for protection since -secret is given");
+ }
+ if (opt_ref != NULL
+ && !OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_ref,
+ strlen(opt_ref)))
+ return 0;
+
+ if (opt_key != NULL) {
+ EVP_PKEY *pkey = load_key_pwd(opt_key, opt_keyform, opt_keypass, engine,
+ "private key for CMP client certificate");
+
+ if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) {
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ if (opt_secret == NULL && opt_srvcert == NULL && opt_trusted == NULL)
+ CMP_warn("will not authenticate server due to missing -secret, -trusted, or -srvcert");
+
+ if (opt_cert != NULL) {
+ X509 *cert;
+ STACK_OF(X509) *certs = NULL;
+ X509_STORE *own_trusted = NULL;
+ int ok;
+
+ if (!load_cert_certs(opt_cert, &cert, &certs, 0, opt_keypass,
+ "CMP client certificate (optionally with chain)",
+ vpm))
+ /* opt_keypass is needed if opt_cert is an encrypted PKCS#12 file */
+ return 0;
+ ok = OSSL_CMP_CTX_set1_cert(ctx, cert);
+ X509_free(cert);
+ if (!ok) {
+ CMP_err("out of memory");
+ } else {
+ if (opt_own_trusted != NULL) {
+ own_trusted = load_trusted(opt_own_trusted, 0,
+ "trusted certs for verifying own CMP signer cert");
+ ok = own_trusted != NULL;
+ }
+ ok = ok && OSSL_CMP_CTX_build_cert_chain(ctx, own_trusted, certs);
+ }
+ X509_STORE_free(own_trusted);
+ sk_X509_pop_free(certs, X509_free);
+ if (!ok)
+ return 0;
+ } else if (opt_own_trusted != NULL) {
+ CMP_warn("-own_trusted option is ignored without -cert");
+ }
+
+ if (!setup_certs(opt_extracerts, "extra certificates for CMP", ctx,
+ (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_extraCertsOut))
+ return 0;
+ cleanse(opt_otherpass);
+
+ if (opt_unprotected_requests)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1);
+
+ if (opt_digest != NULL) {
+ int digest = OBJ_ln2nid(opt_digest);
+
+ if (digest == NID_undef) {
+ CMP_err1("digest algorithm name not recognized: '%s'", opt_digest);
+ return 0;
+ }
+ if (!OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DIGEST_ALGNID, digest)
+ || !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_OWF_ALGNID, digest)) {
+ CMP_err1("digest algorithm name not supported: '%s'", opt_digest);
+ return 0;
+ }
+ }
+
+ if (opt_mac != NULL) {
+ int mac = OBJ_ln2nid(opt_mac);
+ if (mac == NID_undef) {
+ CMP_err1("MAC algorithm name not recognized: '%s'", opt_mac);
+ return 0;
+ }
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MAC_ALGNID, mac);
+ }
+ return 1;
+}
+
+/*
+ * set up IR/CR/KUR/CertConf/RR specific parts of the OSSL_CMP_CTX
+ * based on options from config file/CLI.
+ * Returns pointer on success, NULL on error
+ */
+static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
+{
+ X509_REQ *csr = NULL;
+ X509_EXTENSIONS *exts = NULL;
+ X509V3_CTX ext_ctx;
+
+ if (opt_subject == NULL
+ && opt_csr == NULL && opt_oldcert == NULL && opt_cert == NULL
+ && opt_cmd != CMP_RR && opt_cmd != CMP_GENM)
+ CMP_warn("no -subject given; no -csr or -oldcert or -cert available for fallback");
+
+ if (opt_cmd == CMP_IR || opt_cmd == CMP_CR || opt_cmd == CMP_KUR) {
+ if (opt_newkey == NULL && opt_key == NULL && opt_csr == NULL) {
+ CMP_err("missing -newkey (or -key) to be certified and no -csr given");
+ return 0;
+ }
+ if (opt_certout == NULL) {
+ CMP_err("-certout not given, nowhere to save newly enrolled certificate");
+ return 0;
+ }
+ if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject")
+ || !set_name(opt_issuer, OSSL_CMP_CTX_set1_issuer, ctx, "issuer"))
+ return 0;
+ } else {
+ const char *msg = "option is ignored for commands other than 'ir', 'cr', and 'kur'";
+
+ if (opt_subject != NULL) {
+ if (opt_ref == NULL && opt_cert == NULL) {
+ /* use subject as default sender unless oldcert subject is used */
+ if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject"))
+ return 0;
+ } else {
+ CMP_warn1("-subject %s since -ref or -cert is given", msg);
+ }
+ }
+ if (opt_issuer != NULL)
+ CMP_warn1("-issuer %s", msg);
+ if (opt_reqexts != NULL)
+ CMP_warn1("-reqexts %s", msg);
+ if (opt_san_nodefault)
+ CMP_warn1("-san_nodefault %s", msg);
+ if (opt_sans != NULL)
+ CMP_warn1("-sans %s", msg);
+ if (opt_policies != NULL)
+ CMP_warn1("-policies %s", msg);
+ if (opt_policy_oids != NULL)
+ CMP_warn1("-policy_oids %s", msg);
+ }
+ if (opt_cmd == CMP_KUR) {
+ char *ref_cert = opt_oldcert != NULL ? opt_oldcert : opt_cert;
+
+ if (ref_cert == NULL && opt_csr == NULL) {
+ CMP_err("missing -oldcert for certificate to be updated and no -csr given");
+ return 0;
+ }
+ if (opt_subject != NULL)
+ CMP_warn2("given -subject '%s' overrides the subject of '%s' for KUR",
+ opt_subject, ref_cert != NULL ? ref_cert : opt_csr);
+ }
+ if (opt_cmd == CMP_RR) {
+ if (opt_oldcert == NULL && opt_csr == NULL) {
+ CMP_err("missing -oldcert for certificate to be revoked and no -csr given");
+ return 0;
+ }
+ if (opt_oldcert != NULL && opt_csr != NULL)
+ CMP_warn("ignoring -csr since certificate to be revoked is given");
+ }
+ if (opt_cmd == CMP_P10CR && opt_csr == NULL) {
+ CMP_err("missing PKCS#10 CSR for p10cr");
+ return 0;
+ }
+
+ if (opt_recipient == NULL && opt_srvcert == NULL && opt_issuer == NULL
+ && opt_oldcert == NULL && opt_cert == NULL)
+ CMP_warn("missing -recipient, -srvcert, -issuer, -oldcert or -cert; recipient will be set to \"NULL-DN\"");
+
+ if (opt_cmd == CMP_P10CR || opt_cmd == CMP_RR) {
+ const char *msg = "option is ignored for 'p10cr' and 'rr' commands";
+
+ if (opt_newkeypass != NULL)
+ CMP_warn1("-newkeytype %s", msg);
+ if (opt_newkey != NULL)
+ CMP_warn1("-newkey %s", msg);
+ if (opt_days != 0)
+ CMP_warn1("-days %s", msg);
+ if (opt_popo != OSSL_CRMF_POPO_NONE - 1)
+ CMP_warn1("-popo %s", msg);
+ } else if (opt_newkey != NULL) {
+ const char *file = opt_newkey;
+ const int format = opt_keyform;
+ const char *pass = opt_newkeypass;
+ const char *desc = "new private key for cert to be enrolled";
+ EVP_PKEY *pkey;
+ int priv = 1;
+ BIO *bio_bak = bio_err;
+
+ bio_err = NULL; /* suppress diagnostics on first try loading key */
+ pkey = load_key_pwd(file, format, pass, engine, desc);
+ bio_err = bio_bak;
+ if (pkey == NULL) {
+ ERR_clear_error();
+ desc = opt_csr == NULL
+ ? "fallback public key for cert to be enrolled"
+ : "public key for checking cert resulting from p10cr";
+ pkey = load_pubkey(file, format, 0, pass, engine, desc);
+ priv = 0;
+ }
+ cleanse(opt_newkeypass);
+ if (pkey == NULL || !OSSL_CMP_CTX_set0_newPkey(ctx, priv, pkey)) {
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+ }
+
+ if (opt_days > 0
+ && !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_VALIDITY_DAYS,
+ opt_days)) {
+ CMP_err("could not set requested cert validity period");
+ return 0;
+ }
+
+ if (opt_policies != NULL && opt_policy_oids != NULL) {
+ CMP_err("cannot have policies both via -policies and via -policy_oids");
+ return 0;
+ }
+
+ if (opt_csr != NULL) {
+ if (opt_cmd == CMP_GENM) {
+ CMP_warn("-csr option is ignored for command 'genm'");
+ } else {
+ if ((csr = load_csr_autofmt(opt_csr, "PKCS#10 CSR")) == NULL)
+ return 0;
+ if (!OSSL_CMP_CTX_set1_p10CSR(ctx, csr))
+ goto oom;
+ }
+ }
+ if (opt_reqexts != NULL || opt_policies != NULL) {
+ if ((exts = sk_X509_EXTENSION_new_null()) == NULL)
+ goto oom;
+ X509V3_set_ctx(&ext_ctx, NULL, NULL, csr, NULL, X509V3_CTX_REPLACE);
+ X509V3_set_nconf(&ext_ctx, conf);
+ if (opt_reqexts != NULL
+ && !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_reqexts, &exts)) {
+ CMP_err1("cannot load certificate request extension section '%s'",
+ opt_reqexts);
+ goto exts_err;
+ }
+ if (opt_policies != NULL
+ && !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_policies, &exts)) {
+ CMP_err1("cannot load policy cert request extension section '%s'",
+ opt_policies);
+ goto exts_err;
+ }
+ OSSL_CMP_CTX_set0_reqExtensions(ctx, exts);
+ }
+ X509_REQ_free(csr);
+ /* After here, must not goto oom/exts_err */
+
+ if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) && opt_sans != NULL) {
+ CMP_err("cannot have Subject Alternative Names both via -reqexts and via -sans");
+ return 0;
+ }
+ if (!set_gennames(ctx, opt_sans, "Subject Alternative Name"))
+ return 0;
+
+ if (opt_san_nodefault) {
+ if (opt_sans != NULL)
+ CMP_warn("-opt_san_nodefault has no effect when -sans is used");
+ (void)OSSL_CMP_CTX_set_option(ctx,
+ OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT, 1);
+ }
+
+ if (opt_policy_oids_critical) {
+ if (opt_policy_oids == NULL)
+ CMP_warn("-opt_policy_oids_critical has no effect unless -policy_oids is given");
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POLICIES_CRITICAL, 1);
+ }
+
+ while (opt_policy_oids != NULL) {
+ ASN1_OBJECT *policy;
+ POLICYINFO *pinfo;
+ char *next = next_item(opt_policy_oids);
+
+ if ((policy = OBJ_txt2obj(opt_policy_oids, 1)) == 0) {
+ CMP_err1("unknown policy OID '%s'", opt_policy_oids);
+ return 0;
+ }
+
+ if ((pinfo = POLICYINFO_new()) == NULL) {
+ ASN1_OBJECT_free(policy);
+ return 0;
+ }
+ pinfo->policyid = policy;
+
+ if (!OSSL_CMP_CTX_push0_policy(ctx, pinfo)) {
+ CMP_err1("cannot add policy with OID '%s'", opt_policy_oids);
+ POLICYINFO_free(pinfo);
+ return 0;
+ }
+ opt_policy_oids = next;
+ }
+
+ if (opt_popo >= OSSL_CRMF_POPO_NONE)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POPO_METHOD, opt_popo);
+
+ if (opt_oldcert != NULL) {
+ if (opt_cmd == CMP_GENM) {
+ CMP_warn("-oldcert option is ignored for command 'genm'");
+ } else {
+ X509 *oldcert = load_cert_pwd(opt_oldcert, opt_keypass,
+ opt_cmd == CMP_KUR ?
+ "certificate to be updated" :
+ opt_cmd == CMP_RR ?
+ "certificate to be revoked" :
+ "reference certificate (oldcert)");
+ /* opt_keypass needed if opt_oldcert is an encrypted PKCS#12 file */
+
+ if (oldcert == NULL)
+ return 0;
+ if (!OSSL_CMP_CTX_set1_oldCert(ctx, oldcert)) {
+ X509_free(oldcert);
+ CMP_err("out of memory");
+ return 0;
+ }
+ X509_free(oldcert);
+ }
+ }
+ cleanse(opt_keypass);
+ if (opt_revreason > CRL_REASON_NONE)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_REVOCATION_REASON,
+ opt_revreason);
+
+ return 1;
+
+ oom:
+ CMP_err("out of memory");
+ exts_err:
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ X509_REQ_free(csr);
+ return 0;
+}
+
+static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
+{
+ long value;
+ ASN1_OBJECT *type;
+ ASN1_INTEGER *aint;
+ ASN1_TYPE *val;
+ OSSL_CMP_ITAV *itav;
+ char *endstr;
+ char *valptr = strchr(opt_geninfo, ':');
+
+ if (valptr == NULL) {
+ CMP_err("missing ':' in -geninfo option");
+ return 0;
+ }
+ valptr[0] = '\0';
+ valptr++;
+
+ if (OPENSSL_strncasecmp(valptr, "int:", 4) != 0) {
+ CMP_err("missing 'int:' in -geninfo option");
+ return 0;
+ }
+ valptr += 4;
+
+ value = strtol(valptr, &endstr, 10);
+ if (endstr == valptr || *endstr != '\0') {
+ CMP_err("cannot parse int in -geninfo option");
+ return 0;
+ }
+
+ type = OBJ_txt2obj(opt_geninfo, 1);
+ if (type == NULL) {
+ CMP_err("cannot parse OID in -geninfo option");
+ return 0;
+ }
+
+ if ((aint = ASN1_INTEGER_new()) == NULL)
+ goto oom;
+
+ val = ASN1_TYPE_new();
+ if (!ASN1_INTEGER_set(aint, value) || val == NULL) {
+ ASN1_INTEGER_free(aint);
+ goto oom;
+ }
+ ASN1_TYPE_set(val, V_ASN1_INTEGER, aint);
+ itav = OSSL_CMP_ITAV_create(type, val);
+ if (itav == NULL) {
+ ASN1_TYPE_free(val);
+ goto oom;
+ }
+
+ if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) {
+ OSSL_CMP_ITAV_free(itav);
+ return 0;
+ }
+ return 1;
+
+ oom:
+ ASN1_OBJECT_free(type);
+ CMP_err("out of memory");
+ return 0;
+}
+
+
+/*
+ * set up the client-side OSSL_CMP_CTX based on options from config file/CLI
+ * while parsing options and checking their consistency.
+ * Prints reason for error to bio_err.
+ * Returns 1 on success, 0 on error
+ */
+static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
+{
+ int ret = 0;
+ char *host = NULL, *port = NULL, *path = NULL, *used_path = opt_path;
+#ifndef OPENSSL_NO_SOCK
+ int portnum, ssl;
+ static char server_port[32] = { '\0' };
+ const char *proxy_host = NULL;
+#endif
+ char server_buf[200] = "mock server";
+ char proxy_buf[200] = "";
+
+ if (!opt_use_mock_srv && opt_rspin == NULL) { /* note: -port is not given */
+#ifndef OPENSSL_NO_SOCK
+ if (opt_server == NULL) {
+ CMP_err("missing -server or -use_mock_srv or -rspin option");
+ goto err;
+ }
+#else
+ CMP_err("missing -use_mock_srv or -rspin option; -server option is not supported due to no-sock build");
+ goto err;
+#endif
+ }
+#ifndef OPENSSL_NO_SOCK
+ if (opt_server == NULL) {
+ if (opt_proxy != NULL)
+ CMP_warn("ignoring -proxy option since -server is not given");
+ if (opt_no_proxy != NULL)
+ CMP_warn("ignoring -no_proxy option since -server is not given");
+ if (opt_tls_used) {
+ CMP_warn("ignoring -tls_used option since -server is not given");
+ opt_tls_used = 0;
+ }
+ goto set_path;
+ }
+ if (!OSSL_HTTP_parse_url(opt_server, &ssl, NULL /* user */, &host, &port,
+ &portnum, &path, NULL /* q */, NULL /* frag */)) {
+ CMP_err1("cannot parse -server URL: %s", opt_server);
+ goto err;
+ }
+ if (ssl && !opt_tls_used) {
+ CMP_err("missing -tls_used option since -server URL indicates https");
+ goto err;
+ }
+
+ BIO_snprintf(server_port, sizeof(server_port), "%s", port);
+ if (opt_path == NULL)
+ used_path = path;
+ if (!OSSL_CMP_CTX_set1_server(ctx, host)
+ || !OSSL_CMP_CTX_set_serverPort(ctx, portnum))
+ goto oom;
+ if (opt_proxy != NULL && !OSSL_CMP_CTX_set1_proxy(ctx, opt_proxy))
+ goto oom;
+ if (opt_no_proxy != NULL && !OSSL_CMP_CTX_set1_no_proxy(ctx, opt_no_proxy))
+ goto oom;
+ (void)BIO_snprintf(server_buf, sizeof(server_buf), "http%s://%s:%s/%s",
+ opt_tls_used ? "s" : "", host, port,
+ *used_path == '/' ? used_path + 1 : used_path);
+
+ proxy_host = OSSL_HTTP_adapt_proxy(opt_proxy, opt_no_proxy, host, ssl);
+ if (proxy_host != NULL)
+ (void)BIO_snprintf(proxy_buf, sizeof(proxy_buf), " via %s", proxy_host);
+
+ set_path:
+#endif
+
+ if (!OSSL_CMP_CTX_set1_serverPath(ctx, used_path))
+ goto oom;
+ if (!transform_opts())
+ goto err;
+
+ if (opt_infotype_s != NULL) {
+ char id_buf[100] = "id-it-";
+
+ strncat(id_buf, opt_infotype_s, sizeof(id_buf) - strlen(id_buf) - 1);
+ if ((opt_infotype = OBJ_sn2nid(id_buf)) == NID_undef) {
+ CMP_err("unknown OID name in -infotype option");
+ goto err;
+ }
+ }
+
+ if (!setup_verification_ctx(ctx))
+ goto err;
+
+ if (opt_keep_alive != 1)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_KEEP_ALIVE,
+ opt_keep_alive);
+ if (opt_total_timeout > 0 && opt_msg_timeout > 0
+ && opt_total_timeout < opt_msg_timeout) {
+ CMP_err2("-total_timeout argument = %d must not be < %d (-msg_timeout)",
+ opt_total_timeout, opt_msg_timeout);
+ goto err;
+ }
+ if (opt_msg_timeout >= 0) /* must do this before setup_ssl_ctx() */
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT,
+ opt_msg_timeout);
+ if (opt_total_timeout >= 0)
+ (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT,
+ opt_total_timeout);
+
+ if (opt_reqin != NULL && opt_rspin != NULL)
+ CMP_warn("-reqin is ignored since -rspin is present");
+ if (opt_reqin_new_tid && opt_reqin == NULL)
+ CMP_warn("-reqin_new_tid is ignored since -reqin is not present");
+ if (opt_reqin != NULL || opt_reqout != NULL
+ || opt_rspin != NULL || opt_rspout != NULL || opt_use_mock_srv)
+ (void)OSSL_CMP_CTX_set_transfer_cb(ctx, read_write_req_resp);
+
+#ifndef OPENSSL_NO_SOCK
+ if (opt_tls_used) {
+ APP_HTTP_TLS_INFO *info;
+
+ if (opt_tls_cert != NULL
+ || opt_tls_key != NULL || opt_tls_keypass != NULL) {
+ if (opt_tls_key == NULL) {
+ CMP_err("missing -tls_key option");
+ goto err;
+ } else if (opt_tls_cert == NULL) {
+ CMP_err("missing -tls_cert option");
+ goto err;
+ }
+ }
+
+ if ((info = OPENSSL_zalloc(sizeof(*info))) == NULL)
+ goto err;
+ (void)OSSL_CMP_CTX_set_http_cb_arg(ctx, info);
+ info->server = opt_server;
+ info->port = server_port;
+ /* workaround for callback design flaw, see #17088: */
+ info->use_proxy = proxy_host != NULL;
+ info->timeout = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT);
+ info->ssl_ctx = setup_ssl_ctx(ctx, host, engine);
+
+ if (info->ssl_ctx == NULL)
+ goto err;
+ (void)OSSL_CMP_CTX_set_http_cb(ctx, app_http_tls_cb);
+ }
+#endif
+
+ if (!setup_protection_ctx(ctx, engine))
+ goto err;
+
+ if (!setup_request_ctx(ctx, engine))
+ goto err;
+
+ if (!set_name(opt_recipient, OSSL_CMP_CTX_set1_recipient, ctx, "recipient")
+ || !set_name(opt_expect_sender, OSSL_CMP_CTX_set1_expected_sender,
+ ctx, "expected sender"))
+ goto err;
+
+ if (opt_geninfo != NULL && !handle_opt_geninfo(ctx))
+ goto err;
+
+ /* not printing earlier, to minimize confusion in case setup fails before */
+ if (opt_rspin != NULL)
+ CMP_info("will not contact any server since -rspin is given");
+ else
+ CMP_info2("will contact %s%s", server_buf, proxy_buf);
+
+ ret = 1;
+
+ err:
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ OPENSSL_free(path);
+ return ret;
+ oom:
+ CMP_err("out of memory");
+ goto err;
+}
+
+/*
+ * write out the given certificate to the output specified by bio.
+ * Depending on options use either PEM or DER format.
+ * Returns 1 on success, 0 on error
+ */
+static int write_cert(BIO *bio, X509 *cert)
+{
+ if ((opt_certform == FORMAT_PEM && PEM_write_bio_X509(bio, cert))
+ || (opt_certform == FORMAT_ASN1 && i2d_X509_bio(bio, cert)))
+ return 1;
+ if (opt_certform != FORMAT_PEM && opt_certform != FORMAT_ASN1)
+ BIO_printf(bio_err,
+ "error: unsupported type '%s' for writing certificates\n",
+ opt_certform_s);
+ return 0;
+}
+
+/*
+ * If destFile != NULL writes out a stack of certs to the given file.
+ * In any case frees the certs.
+ * Depending on options use either PEM or DER format,
+ * where DER does not make much sense for writing more than one cert!
+ * Returns number of written certificates on success, -1 on error.
+ */
+static int save_free_certs(OSSL_CMP_CTX *ctx,
+ STACK_OF(X509) *certs, char *destFile, char *desc)
+{
+ BIO *bio = NULL;
+ int i;
+ int n = sk_X509_num(certs);
+
+ if (destFile == NULL)
+ goto end;
+ CMP_info3("received %d %s certificate(s), saving to file '%s'",
+ n, desc, destFile);
+ if (n > 1 && opt_certform != FORMAT_PEM)
+ CMP_warn("saving more than one certificate in non-PEM format");
+
+ if (destFile == NULL || (bio = BIO_new(BIO_s_file())) == NULL
+ || !BIO_write_filename(bio, (char *)destFile)) {
+ CMP_err1("could not open file '%s' for writing", destFile);
+ n = -1;
+ goto end;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (!write_cert(bio, sk_X509_value(certs, i))) {
+ CMP_err1("cannot write certificate to file '%s'", destFile);
+ n = -1;
+ goto end;
+ }
+ }
+
+ end:
+ BIO_free(bio);
+ sk_X509_pop_free(certs, X509_free);
+ return n;
+}
+
+static void print_itavs(STACK_OF(OSSL_CMP_ITAV) *itavs)
+{
+ OSSL_CMP_ITAV *itav = NULL;
+ char buf[128];
+ int i, r;
+ int n = sk_OSSL_CMP_ITAV_num(itavs); /* itavs == NULL leads to 0 */
+
+ if (n == 0) {
+ CMP_info("genp contains no ITAV");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ itav = sk_OSSL_CMP_ITAV_value(itavs, i);
+ r = OBJ_obj2txt(buf, 128, OSSL_CMP_ITAV_get0_type(itav), 0);
+ if (r < 0)
+ CMP_err("could not get ITAV details");
+ else if (r == 0)
+ CMP_info("genp contains empty ITAV");
+ else
+ CMP_info1("genp contains ITAV of type: %s", buf);
+ }
+}
+
+static char opt_item[SECTION_NAME_MAX + 1];
+/* get previous name from a comma or space-separated list of names */
+static const char *prev_item(const char *opt, const char *end)
+{
+ const char *beg;
+ size_t len;
+
+ if (end == opt)
+ return NULL;
+ beg = end;
+ while (beg > opt) {
+ --beg;
+ if (beg[0] == ',' || isspace(beg[0])) {
+ ++beg;
+ break;
+ }
+ }
+ len = end - beg;
+ if (len > SECTION_NAME_MAX) {
+ CMP_warn3("using only first %d characters of section name starting with \"%.*s\"",
+ SECTION_NAME_MAX, SECTION_NAME_MAX, beg);
+ len = SECTION_NAME_MAX;
+ }
+ memcpy(opt_item, beg, len);
+ opt_item[len] = '\0';
+ while (beg > opt) {
+ --beg;
+ if (beg[0] != ',' && !isspace(beg[0])) {
+ ++beg;
+ break;
+ }
+ }
+ return beg;
+}
+
+/* get str value for name from a comma-separated hierarchy of config sections */
+static char *conf_get_string(const CONF *src_conf, const char *groups,
+ const char *name)
+{
+ char *res = NULL;
+ const char *end = groups + strlen(groups);
+
+ while ((end = prev_item(groups, end)) != NULL) {
+ if ((res = NCONF_get_string(src_conf, opt_item, name)) != NULL)
+ return res;
+ }
+ return res;
+}
+
+/* get long val for name from a comma-separated hierarchy of config sections */
+static int conf_get_number_e(const CONF *conf_, const char *groups,
+ const char *name, long *result)
+{
+ char *str = conf_get_string(conf_, groups, name);
+ char *tailptr;
+ long res;
+
+ if (str == NULL || *str == '\0')
+ return 0;
+
+ res = strtol(str, &tailptr, 10);
+ if (res == LONG_MIN || res == LONG_MAX || *tailptr != '\0')
+ return 0;
+
+ *result = res;
+ return 1;
+}
+
+/*
+ * use the command line option table to read values from the CMP section
+ * of openssl.cnf. Defaults are taken from the config file, they can be
+ * overwritten on the command line.
+ */
+static int read_config(void)
+{
+ unsigned int i;
+ long num = 0;
+ char *txt = NULL;
+ const OPTIONS *opt;
+ int start_opt = OPT_VERBOSITY - OPT_HELP;
+ int start_idx = OPT_VERBOSITY - 2;
+ /*
+ * starting with offset OPT_VERBOSITY because OPT_CONFIG and OPT_SECTION
+ * would not make sense within the config file.
+ */
+ int n_options = OSSL_NELEM(cmp_options) - 1;
+
+ for (opt = &cmp_options[start_opt], i = start_idx;
+ opt->name != NULL; i++, opt++)
+ if (!strcmp(opt->name, OPT_SECTION_STR)
+ || !strcmp(opt->name, OPT_MORE_STR))
+ n_options--;
+ OPENSSL_assert(OSSL_NELEM(cmp_vars) == n_options
+ + OPT_PROV__FIRST + 1 - OPT_PROV__LAST
+ + OPT_R__FIRST + 1 - OPT_R__LAST
+ + OPT_V__FIRST + 1 - OPT_V__LAST);
+ for (opt = &cmp_options[start_opt], i = start_idx;
+ opt->name != NULL; i++, opt++) {
+ int provider_option = (OPT_PROV__FIRST <= opt->retval
+ && opt->retval < OPT_PROV__LAST);
+ int rand_state_option = (OPT_R__FIRST <= opt->retval
+ && opt->retval < OPT_R__LAST);
+ int verification_option = (OPT_V__FIRST <= opt->retval
+ && opt->retval < OPT_V__LAST);
+
+ if (strcmp(opt->name, OPT_SECTION_STR) == 0
+ || strcmp(opt->name, OPT_MORE_STR) == 0) {
+ i--;
+ continue;
+ }
+ if (provider_option || rand_state_option || verification_option)
+ i--;
+ switch (opt->valtype) {
+ case '-':
+ case 'p':
+ case 'n':
+ case 'N':
+ case 'l':
+ if (!conf_get_number_e(conf, opt_section, opt->name, &num)) {
+ ERR_clear_error();
+ continue; /* option not provided */
+ }
+ if (opt->valtype == 'p' && num <= 0) {
+ opt_printf_stderr("Non-positive number \"%ld\" for config option -%s\n",
+ num, opt->name);
+ return -1;
+ }
+ if (opt->valtype == 'N' && num < 0) {
+ opt_printf_stderr("Negative number \"%ld\" for config option -%s\n",
+ num, opt->name);
+ return -1;
+ }
+ break;
+ case 's':
+ case '>':
+ case 'M':
+ txt = conf_get_string(conf, opt_section, opt->name);
+ if (txt == NULL) {
+ ERR_clear_error();
+ continue; /* option not provided */
+ }
+ break;
+ default:
+ CMP_err2("internal: unsupported type '%c' for option '%s'",
+ opt->valtype, opt->name);
+ return 0;
+ break;
+ }
+ if (provider_option || verification_option) {
+ int conf_argc = 1;
+ char *conf_argv[3];
+ char arg1[82];
+
+ BIO_snprintf(arg1, 81, "-%s", (char *)opt->name);
+ conf_argv[0] = prog;
+ conf_argv[1] = arg1;
+ if (opt->valtype == '-') {
+ if (num != 0)
+ conf_argc = 2;
+ } else {
+ conf_argc = 3;
+ conf_argv[2] = conf_get_string(conf, opt_section, opt->name);
+ /* not NULL */
+ }
+ if (conf_argc > 1) {
+ (void)opt_init(conf_argc, conf_argv, cmp_options);
+
+ if (provider_option
+ ? !opt_provider(opt_next())
+ : !opt_verify(opt_next(), vpm)) {
+ CMP_err2("for option '%s' in config file section '%s'",
+ opt->name, opt_section);
+ return 0;
+ }
+ }
+ } else {
+ switch (opt->valtype) {
+ case '-':
+ case 'p':
+ case 'n':
+ case 'N':
+ if (num < INT_MIN || INT_MAX < num) {
+ BIO_printf(bio_err,
+ "integer value out of range for option '%s'\n",
+ opt->name);
+ return 0;
+ }
+ *cmp_vars[i].num = (int)num;
+ break;
+ case 'l':
+ *cmp_vars[i].num_long = num;
+ break;
+ default:
+ if (txt != NULL && txt[0] == '\0')
+ txt = NULL; /* reset option on empty string input */
+ *cmp_vars[i].txt = txt;
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static char *opt_str(void)
+{
+ char *arg = opt_arg();
+
+ if (arg[0] == '\0') {
+ CMP_warn1("%s option argument is empty string, resetting option",
+ opt_flag());
+ arg = NULL;
+ } else if (arg[0] == '-') {
+ CMP_warn1("%s option argument starts with hyphen", opt_flag());
+ }
+ return arg;
+}
+
+/* returns 1 on success, 0 on error, -1 on -help (i.e., stop with success) */
+static int get_opts(int argc, char **argv)
+{
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, cmp_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);
+ return 0;
+ case OPT_HELP:
+ opt_help(cmp_options);
+ return -1;
+ case OPT_CONFIG: /* has already been handled */
+ case OPT_SECTION: /* has already been handled */
+ break;
+ case OPT_VERBOSITY:
+ if (!set_verbosity(opt_int_arg()))
+ goto opthelp;
+ break;
+#ifndef OPENSSL_NO_SOCK
+ case OPT_SERVER:
+ opt_server = opt_str();
+ break;
+ case OPT_PROXY:
+ opt_proxy = opt_str();
+ break;
+ case OPT_NO_PROXY:
+ opt_no_proxy = opt_str();
+ break;
+#endif
+ case OPT_RECIPIENT:
+ opt_recipient = opt_str();
+ break;
+ case OPT_PATH:
+ opt_path = opt_str();
+ break;
+ case OPT_KEEP_ALIVE:
+ opt_keep_alive = opt_int_arg();
+ if (opt_keep_alive > 2) {
+ CMP_err("-keep_alive argument must be 0, 1, or 2");
+ goto opthelp;
+ }
+ break;
+ case OPT_MSG_TIMEOUT:
+ opt_msg_timeout = opt_int_arg();
+ break;
+ case OPT_TOTAL_TIMEOUT:
+ opt_total_timeout = opt_int_arg();
+ break;
+#ifndef OPENSSL_NO_SOCK
+ case OPT_TLS_USED:
+ opt_tls_used = 1;
+ break;
+ case OPT_TLS_CERT:
+ opt_tls_cert = opt_str();
+ break;
+ case OPT_TLS_KEY:
+ opt_tls_key = opt_str();
+ break;
+ case OPT_TLS_KEYPASS:
+ opt_tls_keypass = opt_str();
+ break;
+ case OPT_TLS_EXTRA:
+ opt_tls_extra = opt_str();
+ break;
+ case OPT_TLS_TRUSTED:
+ opt_tls_trusted = opt_str();
+ break;
+ case OPT_TLS_HOST:
+ opt_tls_host = opt_str();
+ break;
+#endif
+
+ case OPT_REF:
+ opt_ref = opt_str();
+ break;
+ case OPT_SECRET:
+ opt_secret = opt_str();
+ break;
+ case OPT_CERT:
+ opt_cert = opt_str();
+ break;
+ case OPT_OWN_TRUSTED:
+ opt_own_trusted = opt_str();
+ break;
+ case OPT_KEY:
+ opt_key = opt_str();
+ break;
+ case OPT_KEYPASS:
+ opt_keypass = opt_str();
+ break;
+ case OPT_DIGEST:
+ opt_digest = opt_str();
+ break;
+ case OPT_MAC:
+ opt_mac = opt_str();
+ break;
+ case OPT_EXTRACERTS:
+ opt_extracerts = opt_str();
+ break;
+ case OPT_UNPROTECTED_REQUESTS:
+ opt_unprotected_requests = 1;
+ break;
+
+ case OPT_TRUSTED:
+ opt_trusted = opt_str();
+ break;
+ case OPT_UNTRUSTED:
+ opt_untrusted = opt_str();
+ break;
+ case OPT_SRVCERT:
+ opt_srvcert = opt_str();
+ break;
+ case OPT_EXPECT_SENDER:
+ opt_expect_sender = opt_str();
+ break;
+ case OPT_IGNORE_KEYUSAGE:
+ opt_ignore_keyusage = 1;
+ break;
+ case OPT_UNPROTECTED_ERRORS:
+ opt_unprotected_errors = 1;
+ break;
+ case OPT_EXTRACERTSOUT:
+ opt_extracertsout = opt_str();
+ break;
+ case OPT_CACERTSOUT:
+ opt_cacertsout = opt_str();
+ break;
+
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto opthelp;
+ break;
+ case OPT_CMD:
+ opt_cmd_s = opt_str();
+ break;
+ case OPT_INFOTYPE:
+ opt_infotype_s = opt_str();
+ break;
+ case OPT_GENINFO:
+ opt_geninfo = opt_str();
+ break;
+
+ case OPT_NEWKEY:
+ opt_newkey = opt_str();
+ break;
+ case OPT_NEWKEYPASS:
+ opt_newkeypass = opt_str();
+ break;
+ case OPT_SUBJECT:
+ opt_subject = opt_str();
+ break;
+ case OPT_ISSUER:
+ opt_issuer = opt_str();
+ break;
+ case OPT_DAYS:
+ opt_days = opt_int_arg();
+ break;
+ case OPT_REQEXTS:
+ opt_reqexts = opt_str();
+ break;
+ case OPT_SANS:
+ opt_sans = opt_str();
+ break;
+ case OPT_SAN_NODEFAULT:
+ opt_san_nodefault = 1;
+ break;
+ case OPT_POLICIES:
+ opt_policies = opt_str();
+ break;
+ case OPT_POLICY_OIDS:
+ opt_policy_oids = opt_str();
+ break;
+ case OPT_POLICY_OIDS_CRITICAL:
+ opt_policy_oids_critical = 1;
+ break;
+ case OPT_POPO:
+ opt_popo = opt_int_arg();
+ if (opt_popo < OSSL_CRMF_POPO_NONE
+ || opt_popo > OSSL_CRMF_POPO_KEYENC) {
+ CMP_err("invalid popo spec. Valid values are -1 .. 2");
+ goto opthelp;
+ }
+ break;
+ case OPT_CSR:
+ opt_csr = opt_arg();
+ break;
+ case OPT_OUT_TRUSTED:
+ opt_out_trusted = opt_str();
+ break;
+ case OPT_IMPLICIT_CONFIRM:
+ opt_implicit_confirm = 1;
+ break;
+ case OPT_DISABLE_CONFIRM:
+ opt_disable_confirm = 1;
+ break;
+ case OPT_CERTOUT:
+ opt_certout = opt_str();
+ break;
+ case OPT_CHAINOUT:
+ opt_chainout = opt_str();
+ break;
+ case OPT_OLDCERT:
+ opt_oldcert = opt_str();
+ break;
+ case OPT_REVREASON:
+ opt_revreason = opt_int_arg();
+ if (opt_revreason < CRL_REASON_NONE
+ || opt_revreason > CRL_REASON_AA_COMPROMISE
+ || opt_revreason == 7) {
+ CMP_err("invalid revreason. Valid values are -1 .. 6, 8 .. 10");
+ goto opthelp;
+ }
+ break;
+ case OPT_CERTFORM:
+ opt_certform_s = opt_str();
+ break;
+ case OPT_KEYFORM:
+ opt_keyform_s = opt_str();
+ break;
+ case OPT_OTHERPASS:
+ opt_otherpass = opt_str();
+ break;
+#ifndef OPENSSL_NO_ENGINE
+ case OPT_ENGINE:
+ opt_engine = opt_str();
+ break;
+#endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto opthelp;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto opthelp;
+ break;
+
+ case OPT_BATCH:
+ opt_batch = 1;
+ break;
+ case OPT_REPEAT:
+ opt_repeat = opt_int_arg();
+ break;
+ case OPT_REQIN:
+ opt_reqin = opt_str();
+ break;
+ case OPT_REQIN_NEW_TID:
+ opt_reqin_new_tid = 1;
+ break;
+ case OPT_REQOUT:
+ opt_reqout = opt_str();
+ break;
+ case OPT_RSPIN:
+ opt_rspin = opt_str();
+ break;
+ case OPT_RSPOUT:
+ opt_rspout = opt_str();
+ break;
+ case OPT_USE_MOCK_SRV:
+ opt_use_mock_srv = 1;
+ break;
+
+#ifndef OPENSSL_NO_SOCK
+ case OPT_PORT:
+ opt_port = opt_str();
+ break;
+ case OPT_MAX_MSGS:
+ opt_max_msgs = opt_int_arg();
+ break;
+#endif
+ case OPT_SRV_REF:
+ opt_srv_ref = opt_str();
+ break;
+ case OPT_SRV_SECRET:
+ opt_srv_secret = opt_str();
+ break;
+ case OPT_SRV_CERT:
+ opt_srv_cert = opt_str();
+ break;
+ case OPT_SRV_KEY:
+ opt_srv_key = opt_str();
+ break;
+ case OPT_SRV_KEYPASS:
+ opt_srv_keypass = opt_str();
+ break;
+ case OPT_SRV_TRUSTED:
+ opt_srv_trusted = opt_str();
+ break;
+ case OPT_SRV_UNTRUSTED:
+ opt_srv_untrusted = opt_str();
+ break;
+ case OPT_RSP_CERT:
+ opt_rsp_cert = opt_str();
+ break;
+ case OPT_RSP_EXTRACERTS:
+ opt_rsp_extracerts = opt_str();
+ break;
+ case OPT_RSP_CAPUBS:
+ opt_rsp_capubs = opt_str();
+ break;
+ case OPT_POLL_COUNT:
+ opt_poll_count = opt_int_arg();
+ break;
+ case OPT_CHECK_AFTER:
+ opt_check_after = opt_int_arg();
+ break;
+ case OPT_GRANT_IMPLICITCONF:
+ opt_grant_implicitconf = 1;
+ break;
+ case OPT_PKISTATUS:
+ opt_pkistatus = opt_int_arg();
+ break;
+ case OPT_FAILURE:
+ opt_failure = opt_int_arg();
+ break;
+ case OPT_FAILUREBITS:
+ opt_failurebits = opt_int_arg();
+ break;
+ case OPT_STATUSSTRING:
+ opt_statusstring = opt_str();
+ break;
+ case OPT_SEND_ERROR:
+ opt_send_error = 1;
+ break;
+ case OPT_SEND_UNPROTECTED:
+ opt_send_unprotected = 1;
+ break;
+ case OPT_SEND_UNPROT_ERR:
+ opt_send_unprot_err = 1;
+ break;
+ case OPT_ACCEPT_UNPROTECTED:
+ opt_accept_unprotected = 1;
+ break;
+ case OPT_ACCEPT_UNPROT_ERR:
+ opt_accept_unprot_err = 1;
+ break;
+ case OPT_ACCEPT_RAVERIFIED:
+ opt_accept_raverified = 1;
+ break;
+ }
+ }
+
+ /* No extra args. */
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc != 0)
+ goto opthelp;
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SOCK
+static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) {
+ BIO *acbio;
+ BIO *cbio = NULL;
+ int keep_alive = 0;
+ int msgs = 0;
+ int retry = 1;
+ int ret = 1;
+
+ if ((acbio = http_server_init_bio(prog, opt_port)) == NULL)
+ return 0;
+ while (opt_max_msgs <= 0 || msgs < opt_max_msgs) {
+ char *path = NULL;
+ OSSL_CMP_MSG *req = NULL;
+ OSSL_CMP_MSG *resp = NULL;
+
+ ret = http_server_get_asn1_req(ASN1_ITEM_rptr(OSSL_CMP_MSG),
+ (ASN1_VALUE **)&req, &path,
+ &cbio, acbio, &keep_alive,
+ prog, opt_port, 0, 0);
+ if (ret == 0) { /* no request yet */
+ if (retry) {
+ ossl_sleep(1000);
+ retry = 0;
+ continue;
+ }
+ ret = 0;
+ goto next;
+ }
+ if (ret++ == -1) /* fatal error */
+ break;
+
+ ret = 0;
+ msgs++;
+ if (req != NULL) {
+ if (strcmp(path, "") != 0 && strcmp(path, "pkix/") != 0) {
+ (void)http_server_send_status(cbio, 404, "Not Found");
+ CMP_err1("expecting empty path or 'pkix/' but got '%s'",
+ path);
+ OPENSSL_free(path);
+ OSSL_CMP_MSG_free(req);
+ goto next;
+ }
+ OPENSSL_free(path);
+ resp = OSSL_CMP_CTX_server_perform(cmp_ctx, req);
+ OSSL_CMP_MSG_free(req);
+ if (resp == NULL) {
+ (void)http_server_send_status(cbio,
+ 500, "Internal Server Error");
+ break; /* treated as fatal error */
+ }
+ ret = http_server_send_asn1_resp(cbio, keep_alive,
+ "application/pkixcmp",
+ ASN1_ITEM_rptr(OSSL_CMP_MSG),
+ (const ASN1_VALUE *)resp);
+ OSSL_CMP_MSG_free(resp);
+ if (!ret)
+ break; /* treated as fatal error */
+ }
+ next:
+ if (!ret) { /* on transmission error, cancel CMP transaction */
+ (void)OSSL_CMP_CTX_set1_transactionID(srv_cmp_ctx, NULL);
+ (void)OSSL_CMP_CTX_set1_senderNonce(srv_cmp_ctx, NULL);
+ }
+ if (!ret || !keep_alive
+ || OSSL_CMP_CTX_get_status(srv_cmp_ctx) != OSSL_CMP_PKISTATUS_trans
+ /* transaction closed by OSSL_CMP_CTX_server_perform() */) {
+ BIO_free_all(cbio);
+ cbio = NULL;
+ }
+ }
+
+ BIO_free_all(cbio);
+ BIO_free_all(acbio);
+ return ret;
+}
+#endif
+
+static void print_status(void)
+{
+ /* print PKIStatusInfo */
+ int status = OSSL_CMP_CTX_get_status(cmp_ctx);
+ char *buf = app_malloc(OSSL_CMP_PKISI_BUFLEN, "PKIStatusInfo buf");
+ const char *string =
+ OSSL_CMP_CTX_snprint_PKIStatus(cmp_ctx, buf, OSSL_CMP_PKISI_BUFLEN);
+ const char *from = "", *server = "";
+
+#ifndef OPENSSL_NO_SOCK
+ if (opt_server != NULL) {
+ from = " from ";
+ server = opt_server;
+ }
+#endif
+ CMP_print(bio_err,
+ status == OSSL_CMP_PKISTATUS_accepted
+ ? OSSL_CMP_LOG_INFO :
+ status == OSSL_CMP_PKISTATUS_rejection
+ || status == OSSL_CMP_PKISTATUS_waiting
+ ? OSSL_CMP_LOG_ERR : OSSL_CMP_LOG_WARNING,
+ status == OSSL_CMP_PKISTATUS_accepted ? "info" :
+ status == OSSL_CMP_PKISTATUS_rejection ? "server error" :
+ status == OSSL_CMP_PKISTATUS_waiting ? "internal error"
+ : "warning", "received%s%s %s", from, server,
+ string != NULL ? string : "<unknown PKIStatus>");
+ OPENSSL_free(buf);
+}
+
+int cmp_main(int argc, char **argv)
+{
+ char *configfile = NULL;
+ int i;
+ X509 *newcert = NULL;
+ ENGINE *engine = NULL;
+ OSSL_CMP_CTX *srv_cmp_ctx = NULL;
+ int ret = 0; /* default: failure */
+
+ prog = opt_appname(argv[0]);
+ if (argc <= 1) {
+ opt_help(cmp_options);
+ goto err;
+ }
+
+ /*
+ * handle options -config, -section, and -verbosity upfront
+ * to take effect for other options
+ */
+ for (i = 1; i < argc - 1; i++) {
+ if (*argv[i] == '-') {
+ if (!strcmp(argv[i] + 1, cmp_options[OPT_CONFIG - OPT_HELP].name))
+ opt_config = argv[++i];
+ else if (!strcmp(argv[i] + 1,
+ cmp_options[OPT_SECTION - OPT_HELP].name))
+ opt_section = argv[++i];
+ else if (strcmp(argv[i] + 1,
+ cmp_options[OPT_VERBOSITY - OPT_HELP].name) == 0
+ && !set_verbosity(atoi(argv[++i])))
+ goto err;
+ }
+ }
+ if (opt_section[0] == '\0') /* empty string */
+ opt_section = DEFAULT_SECTION;
+
+ vpm = X509_VERIFY_PARAM_new();
+ if (vpm == NULL) {
+ CMP_err("out of memory");
+ goto err;
+ }
+
+ /* read default values for options from config file */
+ configfile = opt_config != NULL ? opt_config : default_config_file;
+ if (configfile != NULL && configfile[0] != '\0' /* non-empty string */
+ && (configfile != default_config_file || access(configfile, F_OK) != -1)) {
+ CMP_info2("using section(s) '%s' of OpenSSL configuration file '%s'",
+ opt_section, configfile);
+ conf = app_load_config(configfile);
+ if (conf == NULL) {
+ goto err;
+ } else {
+ if (strcmp(opt_section, CMP_SECTION) == 0) { /* default */
+ if (!NCONF_get_section(conf, opt_section))
+ CMP_info2("no [%s] section found in config file '%s';"
+ " will thus use just [default] and unnamed section if present",
+ opt_section, configfile);
+ } else {
+ const char *end = opt_section + strlen(opt_section);
+ while ((end = prev_item(opt_section, end)) != NULL) {
+ if (!NCONF_get_section(conf, opt_item)) {
+ CMP_err2("no [%s] section found in config file '%s'",
+ opt_item, configfile);
+ goto err;
+ }
+ }
+ }
+ ret = read_config();
+ if (!set_verbosity(opt_verbosity)) /* just for checking range */
+ ret = -1;
+ if (ret <= 0) {
+ if (ret == -1)
+ BIO_printf(bio_err, "Use -help for summary.\n");
+ goto err;
+ }
+ }
+ }
+ (void)BIO_flush(bio_err); /* prevent interference with opt_help() */
+
+ ret = get_opts(argc, argv);
+ if (ret <= 0)
+ goto err;
+ ret = 0;
+ if (!app_RAND_load())
+ goto err;
+
+ if (opt_batch)
+ set_base_ui_method(UI_null());
+
+ if (opt_engine != NULL) {
+ engine = setup_engine_methods(opt_engine, 0 /* not: ENGINE_METHOD_ALL */, 0);
+ if (engine == NULL) {
+ CMP_err1("cannot load engine %s", opt_engine);
+ goto err;
+ }
+ }
+
+ cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq());
+ if (cmp_ctx == NULL)
+ goto err;
+ OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity);
+ if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) {
+ CMP_err1("cannot set up error reporting and logging for %s", prog);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_SOCK
+ if ((opt_tls_cert != NULL || opt_tls_key != NULL
+ || opt_tls_keypass != NULL || opt_tls_extra != NULL
+ || opt_tls_trusted != NULL || opt_tls_host != NULL)
+ && !opt_tls_used)
+ CMP_warn("Ingnoring TLS options(s) since -tls_used is not given");
+ if (opt_port != NULL) {
+ if (opt_tls_used) {
+ CMP_err("-tls_used option not supported with -port option");
+ goto err;
+ }
+ if (opt_use_mock_srv || opt_server != NULL || opt_rspin != NULL) {
+ CMP_err("cannot use -port with -use_mock_srv, -server, or -rspin options");
+ goto err;
+ }
+ }
+ if (opt_server != NULL && opt_use_mock_srv) {
+ CMP_err("cannot use both -server and -use_mock_srv options");
+ goto err;
+ }
+#endif
+ if (opt_rspin != NULL && opt_use_mock_srv) {
+ CMP_err("cannot use both -rspin and -use_mock_srv options");
+ goto err;
+ }
+
+ if (opt_use_mock_srv
+#ifndef OPENSSL_NO_SOCK
+ || opt_port != NULL
+#endif
+ ) {
+ OSSL_CMP_SRV_CTX *srv_ctx;
+
+ if ((srv_ctx = setup_srv_ctx(engine)) == NULL)
+ goto err;
+ srv_cmp_ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx);
+ OSSL_CMP_CTX_set_transfer_cb_arg(cmp_ctx, srv_ctx);
+ if (!OSSL_CMP_CTX_set_log_cb(srv_cmp_ctx, print_to_bio_err)) {
+ CMP_err1("cannot set up error reporting and logging for %s", prog);
+ goto err;
+ }
+ OSSL_CMP_CTX_set_log_verbosity(srv_cmp_ctx, opt_verbosity);
+ }
+
+#ifndef OPENSSL_NO_SOCK
+ if (opt_tls_used && (opt_use_mock_srv || opt_rspin != NULL)) {
+ CMP_warn("ignoring -tls_used option since -use_mock_srv or -rspin is given");
+ opt_tls_used = 0;
+ }
+
+ if (opt_port != NULL) { /* act as very basic CMP HTTP server */
+ ret = cmp_server(srv_cmp_ctx);
+ goto err;
+ }
+
+ /* act as CMP client, possibly using internal mock server */
+
+ if (opt_server != NULL) {
+ if (opt_rspin != NULL) {
+ CMP_warn("ignoring -server option since -rspin is given");
+ opt_server = NULL;
+ }
+ }
+#endif
+
+ if (!setup_client_ctx(cmp_ctx, engine)) {
+ CMP_err("cannot set up CMP context");
+ goto err;
+ }
+ for (i = 0; i < opt_repeat; i++) {
+ /* everything is ready, now connect and perform the command! */
+ switch (opt_cmd) {
+ case CMP_IR:
+ newcert = OSSL_CMP_exec_IR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_KUR:
+ newcert = OSSL_CMP_exec_KUR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_CR:
+ newcert = OSSL_CMP_exec_CR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_P10CR:
+ newcert = OSSL_CMP_exec_P10CR_ses(cmp_ctx);
+ if (newcert != NULL)
+ ret = 1;
+ break;
+ case CMP_RR:
+ ret = OSSL_CMP_exec_RR_ses(cmp_ctx);
+ break;
+ case CMP_GENM:
+ {
+ STACK_OF(OSSL_CMP_ITAV) *itavs;
+
+ if (opt_infotype != NID_undef) {
+ OSSL_CMP_ITAV *itav =
+ OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL);
+ if (itav == NULL)
+ goto err;
+ OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav);
+ }
+
+ if ((itavs = OSSL_CMP_exec_GENM_ses(cmp_ctx)) != NULL) {
+ print_itavs(itavs);
+ sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
+ ret = 1;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (OSSL_CMP_CTX_get_status(cmp_ctx) < OSSL_CMP_PKISTATUS_accepted)
+ goto err; /* we got no response, maybe even did not send request */
+
+ print_status();
+ if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx),
+ opt_extracertsout, "extra") < 0)
+ ret = 0;
+ if (!ret)
+ goto err;
+ ret = 0;
+ if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_caPubs(cmp_ctx),
+ opt_cacertsout, "CA") < 0)
+ goto err;
+ if (newcert != NULL) {
+ STACK_OF(X509) *certs = sk_X509_new_null();
+
+ if (!X509_add_cert(certs, newcert, X509_ADD_FLAG_UP_REF)) {
+ sk_X509_free(certs);
+ goto err;
+ }
+ if (save_free_certs(cmp_ctx, certs, opt_certout, "enrolled") < 0)
+ goto err;
+ }
+ if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_newChain(cmp_ctx),
+ opt_chainout, "chain") < 0)
+ goto err;
+
+ if (!OSSL_CMP_CTX_reinit(cmp_ctx))
+ goto err;
+ }
+ ret = 1;
+
+ err:
+ /* in case we ended up here on error without proper cleaning */
+ cleanse(opt_keypass);
+ cleanse(opt_newkeypass);
+ cleanse(opt_otherpass);
+#ifndef OPENSSL_NO_SOCK
+ cleanse(opt_tls_keypass);
+#endif
+ cleanse(opt_secret);
+ cleanse(opt_srv_keypass);
+ cleanse(opt_srv_secret);
+
+ if (ret != 1)
+ OSSL_CMP_CTX_print_errors(cmp_ctx);
+
+ if (cmp_ctx != NULL) {
+#ifndef OPENSSL_NO_SOCK
+ APP_HTTP_TLS_INFO *info = OSSL_CMP_CTX_get_http_cb_arg(cmp_ctx);
+
+#endif
+ ossl_cmp_mock_srv_free(OSSL_CMP_CTX_get_transfer_cb_arg(cmp_ctx));
+ X509_STORE_free(OSSL_CMP_CTX_get_certConf_cb_arg(cmp_ctx));
+ /* cannot free info already here, as it may be used indirectly by: */
+ OSSL_CMP_CTX_free(cmp_ctx);
+#ifndef OPENSSL_NO_SOCK
+ APP_HTTP_TLS_INFO_free(info);
+#endif
+ }
+ X509_VERIFY_PARAM_free(vpm);
+ release_engine(engine);
+
+ NCONF_free(conf); /* must not do as long as opt_... variables are used */
+ OSSL_CMP_log_close();
+
+ return ret == 0 ? EXIT_FAILURE : EXIT_SUCCESS; /* ret == -1 for -help */
+}
diff --git a/apps/cms.c b/apps/cms.c
index 71554037d0b7..76c789671937 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -14,43 +14,41 @@
#include "apps.h"
#include "progs.h"
-#ifndef OPENSSL_NO_CMS
-
-# include <openssl/crypto.h>
-# include <openssl/pem.h>
-# include <openssl/err.h>
-# include <openssl/x509_vfy.h>
-# include <openssl/x509v3.h>
-# include <openssl/cms.h>
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+#include <openssl/cms.h>
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(CMS_ContentInfo *cms);
-static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
- *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
- *rr_from);
+static CMS_ReceiptRequest
+*make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
+ STACK_OF(OPENSSL_STRING) *rr_from);
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
STACK_OF(OPENSSL_STRING) *param);
-# define SMIME_OP 0x10
-# define SMIME_IP 0x20
-# define SMIME_SIGNERS 0x40
-# define SMIME_ENCRYPT (1 | SMIME_OP)
-# define SMIME_DECRYPT (2 | SMIME_IP)
-# define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
-# define SMIME_VERIFY (4 | SMIME_IP)
-# define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP)
-# define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
-# define SMIME_DATAOUT (7 | SMIME_IP)
-# define SMIME_DATA_CREATE (8 | SMIME_OP)
-# define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
-# define SMIME_DIGEST_CREATE (10 | SMIME_OP)
-# define SMIME_UNCOMPRESS (11 | SMIME_IP)
-# define SMIME_COMPRESS (12 | SMIME_OP)
-# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
-# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP)
-# define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP)
-# define SMIME_VERIFY_RECEIPT (16 | SMIME_IP)
+#define SMIME_OP 0x100
+#define SMIME_IP 0x200
+#define SMIME_SIGNERS 0x400
+#define SMIME_ENCRYPT (1 | SMIME_OP)
+#define SMIME_DECRYPT (2 | SMIME_IP)
+#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_VERIFY (4 | SMIME_IP)
+#define SMIME_RESIGN (5 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_SIGN_RECEIPT (6 | SMIME_IP | SMIME_OP)
+#define SMIME_VERIFY_RECEIPT (7 | SMIME_IP)
+#define SMIME_DIGEST_CREATE (8 | SMIME_OP)
+#define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
+#define SMIME_COMPRESS (10 | SMIME_OP)
+#define SMIME_UNCOMPRESS (11 | SMIME_IP)
+#define SMIME_ENCRYPTED_ENCRYPT (12 | SMIME_OP)
+#define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
+#define SMIME_DATA_CREATE (14 | SMIME_OP)
+#define SMIME_DATA_OUT (15 | SMIME_IP)
+#define SMIME_CMSOUT (16 | SMIME_IP | SMIME_OP)
static int verify_err = 0;
@@ -63,9 +61,9 @@ struct cms_key_param_st {
};
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
- OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN,
+ OPT_DECRYPT, OPT_SIGN, OPT_CADES, 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,
@@ -75,151 +73,246 @@ typedef enum OPTION_choice {
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_CAPATH, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
+ OPT_CONTENT, OPT_PRINT, OPT_NAMEOPT,
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_3DES_WRAP, OPT_WRAP, OPT_ENGINE,
OPT_R_ENUM,
+ OPT_PROV_ENUM, OPT_CONFIG,
OPT_V_ENUM,
- OPT_CIPHER
+ OPT_CIPHER,
+ OPT_ORIGINATOR
} OPTION_CHOICE;
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"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\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"},
+
+ OPT_SECTION("General"),
{"in", OPT_IN, '<', "Input file"},
{"out", OPT_OUT, '>', "Output file"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Operation"),
{"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, '<'},
+ {"resign", OPT_RESIGN, '-', "Resign a signed message"},
+ {"sign_receipt", OPT_SIGN_RECEIPT, '-',
+ "Generate a signed receipt for a message"},
+ {"verify_receipt", OPT_VERIFY_RECEIPT, '<',
+ "Verify receipts; exit if receipt signatures do not verify"},
+ {"digest_create", OPT_DIGEST_CREATE, '-',
+ "Create a CMS \"DigestedData\" object"},
+ {"digest_verify", OPT_DIGEST_VERIFY, '-',
+ "Verify a CMS \"DigestedData\" object and output it"},
+ {"compress", OPT_COMPRESS, '-', "Create a CMS \"CompressedData\" object"},
+ {"uncompress", OPT_UNCOMPRESS, '-',
+ "Uncompress a CMS \"CompressedData\" object"},
+ {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-',
+ "Create CMS \"EncryptedData\" object using symmetric key"},
+ {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-',
+ "Decrypt CMS \"EncryptedData\" object using symmetric key"},
+ {"data_create", OPT_DATA_CREATE, '-', "Create a CMS \"Data\" object"},
+ {"data_out", OPT_DATA_OUT, '-', "Copy CMS \"Data\" object to output"},
{"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, '-'},
+
+ OPT_SECTION("File format"),
+ {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
+ {"outform", OPT_OUTFORM, 'c',
+ "Output format SMIME (default), PEM or DER"},
+ {"rctform", OPT_RCTFORM, 'F', "Receipt file format"},
{"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"},
+ {"binary", OPT_BINARY, '-',
+ "Treat input as binary: do not translate to canonical form"},
+ {"crlfeol", OPT_CRLFEOL, '-',
+ "Use CRLF as EOL termination instead of CR only" },
+ {"asciicrlf", OPT_ASCIICRLF, '-',
+ "Perform CRLF canonicalisation when signing"},
+
+ OPT_SECTION("Keys and passwords"),
+ {"pwri_password", OPT_PWRI_PASSWORD, 's',
+ "Specific password for recipient"},
+ {"secretkey", OPT_SECRETKEY, 's',
+ "Use specified hex-encoded key to decrypt/encrypt recipients or content"},
+ {"secretkeyid", OPT_SECRETKEYID, 's',
+ "Identity of the -secretkey for CMS \"KEKRecipientInfo\" object"},
+ {"inkey", OPT_INKEY, 's',
+ "Input private key (if not signer or recipient)"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
+ {"keyform", OPT_KEYFORM, 'f',
+ "Input private key format (ENGINE, other values ignored)"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+#endif
+ OPT_PROV_OPTIONS,
+ OPT_R_OPTIONS,
+
+ OPT_SECTION("Encryption and decryption"),
+ {"originator", OPT_ORIGINATOR, 's', "Originator certificate file"},
+ {"recip", OPT_RECIP, '<', "Recipient cert file"},
+ {"cert...", OPT_PARAM, '.',
+ "Recipient certs (optional; used only when encrypting)"},
+ {"", OPT_CIPHER, '-',
+ "The encryption algorithm to use (any supported cipher)"},
+ {"wrap", OPT_WRAP, 's',
+ "Key wrap algorithm to use when encrypting with key agreement"},
+ {"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"},
+ {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
+ {"debug_decrypt", OPT_DEBUG_DECRYPT, '-',
+ "Disable MMA protection, return error if no recipient found (see doc)"},
+
+ OPT_SECTION("Signing"),
+ {"md", OPT_MD, 's', "Digest algorithm to use"},
+ {"signer", OPT_SIGNER, 's', "Signer certificate input file"},
{"certfile", OPT_CERTFILE, '<', "Other certificates file"},
+ {"cades", OPT_CADES, '-',
+ "Include signingCertificate attribute (CAdES-BES)"},
+ {"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
+ {"nocerts", OPT_NOCERTS, '-',
+ "Don't include signer's certificate when signing"},
+ {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
+ {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
+ {"receipt_request_all", OPT_RR_ALL, '-',
+ "When signing, create a receipt request for all recipients"},
+ {"receipt_request_first", OPT_RR_FIRST, '-',
+ "When signing, create a receipt request for first recipient"},
+ {"receipt_request_from", OPT_RR_FROM, 's',
+ "Create signed receipt request with specified email address"},
+ {"receipt_request_to", OPT_RR_TO, 's',
+ "Create signed receipt targeted to specified address"},
+
+ OPT_SECTION("Verification"),
+ {"signer", OPT_DUP, 's', "Signer certificate(s) output file"},
+ {"content", OPT_CONTENT, '<',
+ "Supply or override content for detached signature"},
+ {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-',
+ "Do not verify signed content signatures"},
+ {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-',
+ "Do not verify signed attribute signatures"},
+ {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
+ {"nointern", OPT_NOINTERN, '-',
+ "Don't search certificates in message for signer"},
+ {"cades", OPT_DUP, '-', "Check signingCertificate (CAdES-BES)"},
+ {"verify_retcode", OPT_VERIFY_RETCODE, '-',
+ "Exit non-zero on verification failure"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
- {"CApath", OPT_CAPATH, '/', "trusted certificates directory"},
+ {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"},
+ {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
{"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"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+
+ OPT_SECTION("Output"),
+ {"keyid", OPT_KEYID, '-', "Use subject key identifier"},
+ {"econtent_type", OPT_ECONTENT_TYPE, 's', "OID for external content"},
+ {"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
+ {"certsout", OPT_CERTSOUT, '>', "Certificate output file"},
{"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_SECTION("Printing"),
+ {"noout", OPT_NOOUT, '-',
+ "For the -cmsout operation do not output the parsed CMS structure"},
+ {"print", OPT_PRINT, '-',
+ "For the -cmsout operation print out all fields of the CMS structure"},
+ {"nameopt", OPT_NAMEOPT, 's',
+ "For the -print option specifies various strings printing options"},
+ {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" },
+
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}
};
+static CMS_ContentInfo *load_content_info(int informat, BIO *in, int flags,
+ BIO **indata, const char *name)
+{
+ CMS_ContentInfo *ret, *ci;
+
+ ret = CMS_ContentInfo_new_ex(app_get0_libctx(), app_get0_propq());
+ if (ret == NULL) {
+ BIO_printf(bio_err, "Error allocating CMS_contentinfo\n");
+ return NULL;
+ }
+ switch (informat) {
+ case FORMAT_SMIME:
+ ci = SMIME_read_CMS_ex(in, flags, indata, &ret);
+ break;
+ case FORMAT_PEM:
+ ci = PEM_read_bio_CMS(in, &ret, NULL, NULL);
+ break;
+ case FORMAT_ASN1:
+ ci = d2i_CMS_bio(in, &ret);
+ break;
+ default:
+ BIO_printf(bio_err, "Bad input format for %s\n", name);
+ goto err;
+ }
+ if (ci == NULL) {
+ BIO_printf(bio_err, "Error reading %s Content Info\n", name);
+ goto err;
+ }
+ return ret;
+ err:
+ CMS_ContentInfo_free(ret);
+ return NULL;
+}
+
int cms_main(int argc, char **argv)
{
+ CONF *conf = NULL;
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;
EVP_PKEY *key = NULL;
- const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
- const EVP_MD *sign_md = NULL;
+ EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
+ 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;
+ STACK_OF(X509) *encerts = sk_X509_new_null(), *other = NULL;
+ X509 *cert = NULL, *recip = NULL, *signer = NULL, *originator = NULL;
X509_STORE *store = NULL;
- X509_VERIFY_PARAM *vpm = NULL;
+ X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new();
char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
- const char *CAfile = NULL, *CApath = NULL;
- char *certsoutfile = NULL;
- int noCAfile = 0, noCApath = 0;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
+ char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL;
+ int noCAfile = 0, noCApath = 0, noCAstore = 0;
char *infile = NULL, *outfile = NULL, *rctfile = NULL;
- char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL;
+ char *passinarg = NULL, *passin = NULL, *signerfile = NULL;
+ char *originatorfile = NULL, *recipfile = NULL, *ciphername = 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 flags = CMS_DETACHED, binary_files = 0;
+ int noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1;
- int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
+ int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_UNDEF;
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;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
- if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
- return 1;
+ if (encerts == NULL || vpm == NULL)
+ goto end;
prog = opt_init(argc, argv, cms_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -244,6 +337,7 @@ int cms_main(int argc, char **argv)
case OPT_OUT:
outfile = opt_arg();
break;
+
case OPT_ENCRYPT:
operation = SMIME_ENCRYPT;
break;
@@ -253,49 +347,50 @@ int cms_main(int argc, char **argv)
case OPT_SIGN:
operation = SMIME_SIGN;
break;
- case OPT_SIGN_RECEIPT:
- operation = SMIME_SIGN_RECEIPT;
+ case OPT_VERIFY:
+ operation = SMIME_VERIFY;
break;
case OPT_RESIGN:
operation = SMIME_RESIGN;
break;
- case OPT_VERIFY:
- operation = SMIME_VERIFY;
- break;
- case OPT_VERIFY_RETCODE:
- verify_retcode = 1;
+ case OPT_SIGN_RECEIPT:
+ operation = SMIME_SIGN_RECEIPT;
break;
case OPT_VERIFY_RECEIPT:
operation = SMIME_VERIFY_RECEIPT;
rctfile = opt_arg();
break;
- case OPT_CMSOUT:
- operation = SMIME_CMSOUT;
- break;
- case OPT_DATA_OUT:
- operation = SMIME_DATAOUT;
+ case OPT_VERIFY_RETCODE:
+ verify_retcode = 1;
break;
- case OPT_DATA_CREATE:
- operation = SMIME_DATA_CREATE;
+ case OPT_DIGEST_CREATE:
+ operation = SMIME_DIGEST_CREATE;
break;
case OPT_DIGEST_VERIFY:
operation = SMIME_DIGEST_VERIFY;
break;
- case OPT_DIGEST_CREATE:
- operation = SMIME_DIGEST_CREATE;
- break;
case OPT_COMPRESS:
operation = SMIME_COMPRESS;
break;
case OPT_UNCOMPRESS:
operation = SMIME_UNCOMPRESS;
break;
+ case OPT_ED_ENCRYPT:
+ operation = SMIME_ENCRYPTED_ENCRYPT;
+ break;
case OPT_ED_DECRYPT:
operation = SMIME_ENCRYPTED_DECRYPT;
break;
- case OPT_ED_ENCRYPT:
- operation = SMIME_ENCRYPTED_ENCRYPT;
+ case OPT_DATA_CREATE:
+ operation = SMIME_DATA_CREATE;
+ break;
+ case OPT_DATA_OUT:
+ operation = SMIME_DATA_OUT;
break;
+ case OPT_CMSOUT:
+ operation = SMIME_CMSOUT;
+ break;
+
case OPT_DEBUG_DECRYPT:
flags |= CMS_DEBUG_DECRYPT;
break;
@@ -326,6 +421,9 @@ int cms_main(int argc, char **argv)
case OPT_BINARY:
flags |= CMS_BINARY;
break;
+ case OPT_CADES:
+ flags |= CMS_CADES;
+ break;
case OPT_KEYID:
flags |= CMS_USE_KEYID;
break;
@@ -361,14 +459,9 @@ int cms_main(int argc, char **argv)
rr_allorfirst = 1;
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;
+ if (!opt_format(opt_arg(),
+ OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
+ goto opthelp;
break;
case OPT_CERTFILE:
certfile = opt_arg();
@@ -379,12 +472,18 @@ int cms_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_IN:
infile = opt_arg();
break;
@@ -406,6 +505,10 @@ int cms_main(int argc, char **argv)
case OPT_PRINT:
noout = print = 1;
break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto opthelp;
+ break;
case OPT_SECRETKEY:
if (secret_key != NULL) {
BIO_printf(bio_err, "Invalid key (supplied twice) %s\n",
@@ -466,8 +569,7 @@ int cms_main(int argc, char **argv)
certsoutfile = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_arg(), &sign_md))
- goto end;
+ digestname = opt_arg();
break;
case OPT_SIGNER:
/* If previous -signer argument add signer to list */
@@ -486,6 +588,9 @@ int cms_main(int argc, char **argv)
}
signerfile = opt_arg();
break;
+ case OPT_ORIGINATOR:
+ originatorfile = opt_arg();
+ break;
case OPT_INKEY:
/* If previous -inkey argument add signer to list */
if (keyfile != NULL) {
@@ -511,9 +616,7 @@ int cms_main(int argc, char **argv)
break;
case OPT_RECIP:
if (operation == SMIME_ENCRYPT) {
- if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL)
- goto end;
- cert = load_cert(opt_arg(), FORMAT_PEM,
+ cert = load_cert(opt_arg(), FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
@@ -524,13 +627,12 @@ int cms_main(int argc, char **argv)
}
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &cipher))
- goto end;
+ ciphername = opt_unknown();
break;
case OPT_KEYOPT:
keyidx = -1;
if (operation == SMIME_ENCRYPT) {
- if (encerts != NULL)
+ if (sk_X509_num(encerts) > 0)
keyidx += sk_X509_num(encerts);
} else {
if (keyfile != NULL || signerfile != NULL)
@@ -568,22 +670,43 @@ int cms_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
- case OPT_3DES_WRAP:
-# ifndef OPENSSL_NO_DES
- wrap_cipher = EVP_des_ede3_wrap();
-# endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
break;
- case OPT_AES128_WRAP:
- wrap_cipher = EVP_aes_128_wrap();
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
+ goto end;
break;
- case OPT_AES192_WRAP:
- wrap_cipher = EVP_aes_192_wrap();
+ case OPT_WRAP:
+ wrapname = opt_arg();
break;
+ case OPT_AES128_WRAP:
+ case OPT_AES192_WRAP:
case OPT_AES256_WRAP:
- wrap_cipher = EVP_aes_256_wrap();
+ case OPT_3DES_WRAP:
+ wrapname = opt_flag() + 1;
break;
}
}
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &sign_md))
+ goto end;
+ }
+ if (ciphername != NULL) {
+ if (!opt_cipher_any(ciphername, &cipher))
+ goto end;
+ }
+ if (wrapname != NULL) {
+ if (!opt_cipher_any(wrapname, &wrap_cipher))
+ goto end;
+ }
+
+ /* Remaining args are files to process. */
argc = opt_num_rest();
argv = opt_rest();
@@ -601,6 +724,20 @@ int cms_main(int argc, char **argv)
goto opthelp;
}
+ if ((flags & CMS_CADES) != 0) {
+ if ((flags & CMS_NOATTR) != 0) {
+ BIO_puts(bio_err, "Incompatible options: "
+ "CAdES requires signed attributes\n");
+ goto opthelp;
+ }
+ if (operation == SMIME_VERIFY
+ && (flags & (CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY)) != 0) {
+ BIO_puts(bio_err, "Incompatible options: CAdES validation requires"
+ " certs and signed attributes validations\n");
+ goto opthelp;
+ }
+ }
+
if (operation & SMIME_SIGNERS) {
if (keyfile != NULL && signerfile == NULL) {
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
@@ -633,7 +770,7 @@ int cms_main(int argc, char **argv)
}
} else if (operation == SMIME_ENCRYPT) {
if (*argv == NULL && secret_key == NULL
- && pwri_pass == NULL && encerts == NULL) {
+ && pwri_pass == NULL && sk_X509_num(encerts) <= 0) {
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
goto opthelp;
}
@@ -649,25 +786,36 @@ int cms_main(int argc, char **argv)
ret = 2;
- if (!(operation & SMIME_SIGNERS))
+ if ((operation & SMIME_SIGNERS) == 0) {
+ if ((flags & CMS_DETACHED) == 0)
+ BIO_printf(bio_err,
+ "Warning: -nodetach option is ignored for non-signing operation\n");
+
flags &= ~CMS_DETACHED;
+ }
+ if ((operation & SMIME_IP) == 0 && contfile != NULL)
+ BIO_printf(bio_err,
+ "Warning: -contfile option is ignored for the given operation\n");
- if (!(operation & SMIME_OP))
- if (flags & CMS_BINARY)
+ if ((flags & CMS_BINARY) != 0) {
+ if (!(operation & SMIME_OP))
outformat = FORMAT_BINARY;
-
- if (!(operation & SMIME_IP))
- if (flags & CMS_BINARY)
+ if (!(operation & SMIME_IP))
informat = FORMAT_BINARY;
+ if ((operation & SMIME_SIGNERS) != 0 && (flags & CMS_DETACHED) != 0)
+ binary_files = 1;
+ if ((operation & SMIME_IP) != 0 && contfile == NULL)
+ binary_files = 1;
+ }
if (operation == SMIME_ENCRYPT) {
if (!cipher) {
-# ifndef OPENSSL_NO_DES
- cipher = EVP_des_ede3_cbc();
-# else
+#ifndef OPENSSL_NO_DES
+ cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
+#else
BIO_printf(bio_err, "No cipher selected\n");
goto end;
-# endif
+#endif
}
if (secret_key && !secret_keyid) {
@@ -675,44 +823,54 @@ int cms_main(int argc, char **argv)
goto end;
}
- 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;
- argv++;
+ if (*argv != NULL) {
+ if (operation == SMIME_ENCRYPT) {
+ for (; *argv != NULL; argv++) {
+ cert = load_cert(*argv, FORMAT_UNDEF,
+ "recipient certificate file");
+ if (cert == NULL)
+ goto end;
+ sk_X509_push(encerts, cert);
+ cert = NULL;
+ }
+ } else {
+ BIO_printf(bio_err, "Warning: recipient certificate file parameters ignored for operation other than -encrypt\n");
+ }
}
}
if (certfile != NULL) {
- if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
- "certificate file")) {
+ if (!load_certs(certfile, 0, &other, NULL, "certificate file")) {
ERR_print_errors(bio_err);
goto end;
}
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
- if ((recip = load_cert(recipfile, FORMAT_PEM,
+ if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
+ if (originatorfile != NULL) {
+ if ((originator = load_cert(originatorfile, FORMAT_UNDEF,
+ "originator certificate file")) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
if (operation == SMIME_SIGN_RECEIPT) {
- if ((signer = load_cert(signerfile, FORMAT_PEM,
+ if ((signer = load_cert(signerfile, FORMAT_UNDEF,
"receipt signer certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
- if (operation == SMIME_DECRYPT) {
+ if ((operation == SMIME_DECRYPT) || (operation == SMIME_ENCRYPT)) {
if (keyfile == NULL)
keyfile = recipfile;
} else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
@@ -723,31 +881,20 @@ int cms_main(int argc, char **argv)
}
if (keyfile != NULL) {
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
}
- in = bio_open_default(infile, 'r', informat);
+ in = bio_open_default(infile, 'r',
+ binary_files ? FORMAT_BINARY : informat);
if (in == NULL)
goto end;
if (operation & SMIME_IP) {
- if (informat == FORMAT_SMIME) {
- cms = SMIME_read_CMS(in, &indata);
- } else if (informat == FORMAT_PEM) {
- cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
- } else if (informat == FORMAT_ASN1) {
- cms = d2i_CMS_bio(in, NULL);
- } else {
- BIO_printf(bio_err, "Bad input format for CMS file\n");
- goto end;
- }
-
- if (cms == NULL) {
- BIO_printf(bio_err, "Error reading S/MIME message\n");
+ cms = load_content_info(informat, in, flags, &indata, "SMIME");
+ if (cms == NULL)
goto end;
- }
if (contfile != NULL) {
BIO_free(indata);
if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
@@ -770,34 +917,25 @@ int cms_main(int argc, char **argv)
if (rctfile != NULL) {
char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
+
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) {
- 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) {
- rcms = d2i_CMS_bio(rctin, NULL);
- } else {
- BIO_printf(bio_err, "Bad input format for receipt\n");
- goto end;
- }
-
- if (rcms == NULL) {
- BIO_printf(bio_err, "Error reading receipt\n");
+ rcms = load_content_info(rctformat, rctin, 0, NULL, "receipt");
+ if (rcms == NULL)
goto end;
- }
}
- out = bio_open_default(outfile, 'w', outformat);
+ out = bio_open_default(outfile, 'w',
+ binary_files ? FORMAT_BINARY : outformat);
if (out == NULL)
goto end;
if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, cms_cb);
if (vpmtouched)
@@ -807,39 +945,49 @@ int cms_main(int argc, char **argv)
ret = 3;
if (operation == SMIME_DATA_CREATE) {
- cms = CMS_data_create(in, flags);
+ cms = CMS_data_create_ex(in, flags, libctx, app_get0_propq());
} else if (operation == SMIME_DIGEST_CREATE) {
- cms = CMS_digest_create(in, sign_md, flags);
+ cms = CMS_digest_create_ex(in, sign_md, flags, libctx, app_get0_propq());
} else if (operation == SMIME_COMPRESS) {
cms = CMS_compress(in, -1, flags);
} else if (operation == SMIME_ENCRYPT) {
int i;
flags |= CMS_PARTIAL;
- cms = CMS_encrypt(NULL, in, cipher, flags);
+ cms = CMS_encrypt_ex(NULL, in, cipher, flags, libctx, app_get0_propq());
if (cms == NULL)
goto end;
for (i = 0; i < sk_X509_num(encerts); i++) {
CMS_RecipientInfo *ri;
cms_key_param *kparam;
- int tflags = flags;
+ int tflags = flags | CMS_KEY_PARAM;
+ /* This flag enforces allocating the EVP_PKEY_CTX for the recipient here */
+ EVP_PKEY_CTX *pctx;
X509 *x = sk_X509_value(encerts, i);
+ int res;
+
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
- tflags |= CMS_KEY_PARAM;
break;
}
}
- ri = CMS_add1_recipient_cert(cms, x, tflags);
+ ri = CMS_add1_recipient(cms, x, key, originator, tflags);
if (ri == NULL)
goto end;
+
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (kparam != NULL) {
- EVP_PKEY_CTX *pctx;
- pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (!cms_set_pkey_param(pctx, kparam->param))
goto end;
}
+
+ res = EVP_PKEY_CTX_ctrl(pctx, -1, -1,
+ EVP_PKEY_CTRL_CIPHER,
+ EVP_CIPHER_get_nid(cipher), NULL);
+ if (res <= 0 && res != -2)
+ goto end;
+
if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
- && wrap_cipher) {
+ && wrap_cipher != NULL) {
EVP_CIPHER_CTX *wctx;
wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
@@ -871,8 +1019,8 @@ int cms_main(int argc, char **argv)
goto end;
}
} else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
- cms = CMS_EncryptedData_encrypt(in, cipher,
- secret_key, secret_keylen, flags);
+ cms = CMS_EncryptedData_encrypt_ex(in, cipher, secret_key,
+ secret_keylen, flags, libctx, app_get0_propq());
} else if (operation == SMIME_SIGN_RECEIPT) {
CMS_ContentInfo *srcms = NULL;
@@ -900,19 +1048,17 @@ int cms_main(int argc, char **argv)
flags |= CMS_STREAM;
}
flags |= CMS_PARTIAL;
- cms = CMS_sign(NULL, NULL, other, in, flags);
+ cms = CMS_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq());
if (cms == NULL)
goto end;
if (econtent_type != NULL)
CMS_set1_eContentType(cms, econtent_type);
- if (rr_to != NULL) {
- rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
- if (rr == NULL) {
- BIO_puts(bio_err,
- "Signed Receipt Request Creation Error\n");
- goto end;
- }
+ if (rr_to != NULL
+ && ((rr = make_receipt_request(rr_to, rr_allorfirst, rr_from))
+ == NULL)) {
+ BIO_puts(bio_err, "Signed Receipt Request Creation Error\n");
+ goto end;
}
} else {
flags |= CMS_REUSE_DIGEST;
@@ -924,16 +1070,17 @@ int cms_main(int argc, char **argv)
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
- signer = load_cert(signerfile, FORMAT_PEM, "signer certificate");
+ signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL) {
ret = 2;
goto end;
}
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL) {
ret = 2;
goto end;
}
+
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
tflags |= CMS_KEY_PARAM;
@@ -983,7 +1130,7 @@ int cms_main(int argc, char **argv)
}
if (key != NULL) {
- if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
+ if (!CMS_decrypt_set1_pkey_and_peer(cms, key, recip, originator)) {
BIO_puts(bio_err, "Error decrypting CMS using private key\n");
goto end;
}
@@ -1000,7 +1147,7 @@ int cms_main(int argc, char **argv)
BIO_printf(bio_err, "Error decrypting CMS structure\n");
goto end;
}
- } else if (operation == SMIME_DATAOUT) {
+ } else if (operation == SMIME_DATA_OUT) {
if (!CMS_data(cms, out, flags))
goto end;
} else if (operation == SMIME_UNCOMPRESS) {
@@ -1019,16 +1166,18 @@ int cms_main(int argc, char **argv)
goto end;
} else if (operation == SMIME_VERIFY) {
if (CMS_verify(cms, other, store, indata, out, flags) > 0) {
- BIO_printf(bio_err, "Verification successful\n");
+ BIO_printf(bio_err, "%s Verification successful\n",
+ (flags & CMS_CADES) != 0 ? "CAdES" : "CMS");
} else {
- BIO_printf(bio_err, "Verification failure\n");
+ BIO_printf(bio_err, "%s Verification failure\n",
+ (flags & CMS_CADES) != 0 ? "CAdES" : "CMS");
if (verify_retcode)
ret = verify_err + 32;
goto end;
}
if (signerfile != NULL) {
- STACK_OF(X509) *signers;
- signers = CMS_get0_signers(cms);
+ STACK_OF(X509) *signers = CMS_get0_signers(cms);
+
if (!save_certs(signerfile, signers)) {
BIO_printf(bio_err,
"Error writing signers to %s\n", signerfile);
@@ -1049,8 +1198,19 @@ int cms_main(int argc, char **argv)
}
} else {
if (noout) {
- if (print)
- CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
+ if (print) {
+ ASN1_PCTX *pctx = NULL;
+ if (get_nameopt() != XN_FLAG_ONELINE) {
+ pctx = ASN1_PCTX_new();
+ if (pctx != NULL) { /* Print anyway if malloc failed */
+ ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT);
+ ASN1_PCTX_set_str_flags(pctx, get_nameopt());
+ ASN1_PCTX_set_nm_flags(pctx, get_nameopt());
+ }
+ }
+ CMS_ContentInfo_print_ctx(out, cms, 0, pctx);
+ ASN1_PCTX_free(pctx);
+ }
} else if (outformat == FORMAT_SMIME) {
if (to)
BIO_printf(out, "To: %s%s", to, mime_eol);
@@ -1103,6 +1263,9 @@ int cms_main(int argc, char **argv)
X509_free(recip);
X509_free(signer);
EVP_PKEY_free(key);
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_free(wrap_cipher);
+ EVP_MD_free(sign_md);
CMS_ContentInfo_free(cms);
CMS_ContentInfo_free(rcms);
release_engine(e);
@@ -1111,6 +1274,7 @@ int cms_main(int argc, char **argv)
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
+ NCONF_free(conf);
return ret;
}
@@ -1247,12 +1411,12 @@ static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
return NULL;
}
-static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
- *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
- *rr_from)
+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 = NULL, *rct_from = NULL;
- CMS_ReceiptRequest *rr;
+
rct_to = make_names_stack(rr_to);
if (rct_to == NULL)
goto err;
@@ -1263,9 +1427,8 @@ static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
} else {
rct_from = NULL;
}
- rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
- rct_to);
- return rr;
+ return CMS_ReceiptRequest_create0_ex(NULL, -1, rr_allorfirst, rct_from,
+ rct_to, app_get0_libctx());
err:
sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
return NULL;
@@ -1288,5 +1451,3 @@ static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
}
return 1;
}
-
-#endif
diff --git a/apps/crl.c b/apps/crl.c
index 031fada14c84..2158a107e551 100644
--- a/apps/crl.c
+++ b/apps/crl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -19,22 +19,38 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
+ OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_VERIFY, OPT_DATEOPT, OPT_TEXT, OPT_HASH,
+ OPT_HASH_OLD, OPT_NOOUT, OPT_NAMEOPT, OPT_MD, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS crl_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format; default PEM"},
+ {"verify", OPT_VERIFY, '-', "Verify CRL signature"},
+
+ OPT_SECTION("Input"),
{"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)"},
+ {"inform", OPT_INFORM, 'F', "CRL input format (DER or PEM); has no effect"},
{"key", OPT_KEY, '<', "CRL signing Private key to use"},
+ {"keyform", OPT_KEYFORM, 'F', "Private key file format (DER/PEM/P12); has no effect"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "output file - default stdout"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
+ {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."},
+ {"text", OPT_TEXT, '-', "Print out a text format version"},
+ {"hash", OPT_HASH, '-', "Print hash value"},
+#ifndef OPENSSL_NO_MD5
+ {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"},
+#endif
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
+ {"", OPT_MD, '-', "Any supported digest"},
+
+ OPT_SECTION("CRL"),
{"issuer", OPT_ISSUER, '-', "Print issuer DN"},
{"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"},
{"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"},
@@ -43,20 +59,18 @@ const OPTIONS crl_options[] = {
{"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"},
+
+ OPT_SECTION("Certificate"),
{"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"},
{"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"},
+ {"CAstore", OPT_CASTORE, ':', "Verify CRL using certificates in store URI"},
{"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", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"},
-#endif
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -69,14 +83,16 @@ int crl_main(int argc, char **argv)
X509_LOOKUP *lookup = NULL;
X509_OBJECT *xobj = NULL;
EVP_PKEY *pkey;
- const EVP_MD *digest = EVP_sha1();
+ EVP_MD *digest = (EVP_MD *)EVP_sha1();
char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
- const char *CAfile = NULL, *CApath = NULL, *prog;
+ char *digestname = NULL;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = 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 informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF;
int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0;
- int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0;
+ int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0, noCAstore = 0;
+ unsigned long dateopt = ASN1_DTFLGS_RFC822;
int i;
#ifndef OPENSSL_NO_MD5
int hash_old = 0;
@@ -109,7 +125,7 @@ int crl_main(int argc, char **argv)
outfile = opt_arg();
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_KEY:
@@ -126,12 +142,19 @@ int crl_main(int argc, char **argv)
CAfile = opt_arg();
do_ver = 1;
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ do_ver = 1;
+ break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_HASH_OLD:
#ifndef OPENSSL_NO_MD5
hash_old = ++num;
@@ -140,6 +163,10 @@ int crl_main(int argc, char **argv)
case OPT_VERIFY:
do_ver = 1;
break;
+ case OPT_DATEOPT:
+ if (!set_dateopt(&dateopt, opt_arg()))
+ goto opthelp;
+ break;
case OPT_TEXT:
text = 1;
break;
@@ -156,7 +183,7 @@ int crl_main(int argc, char **argv)
nextupdate = ++num;
break;
case OPT_NOOUT:
- noout = ++num;
+ noout = 1;
break;
case OPT_FINGERPRINT:
fingerprint = ++num;
@@ -172,20 +199,31 @@ int crl_main(int argc, char **argv)
goto opthelp;
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &digest))
- goto opthelp;
+ digestname = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No remaining args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
- x = load_crl(infile, informat);
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &digest))
+ goto opthelp;
+ }
+ x = load_crl(infile, informat, 1, "CRL");
if (x == NULL)
goto end;
if (do_ver) {
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (lookup == NULL)
@@ -204,7 +242,7 @@ int crl_main(int argc, char **argv)
}
pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
X509_OBJECT_free(xobj);
- if (!pkey) {
+ if (pkey == NULL) {
BIO_printf(bio_err, "Error getting CRL issuer public key\n");
goto end;
}
@@ -218,17 +256,17 @@ int crl_main(int argc, char **argv)
BIO_printf(bio_err, "verify OK\n");
}
- if (crldiff) {
+ if (crldiff != NULL) {
X509_CRL *newcrl, *delta;
if (!keyfile) {
BIO_puts(bio_err, "Missing CRL signing key\n");
goto end;
}
- newcrl = load_crl(crldiff, informat);
+ newcrl = load_crl(crldiff, informat, 0, "other CRL");
if (!newcrl)
goto end;
pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key");
- if (!pkey) {
+ if (pkey == NULL) {
X509_CRL_free(newcrl);
goto end;
}
@@ -254,39 +292,54 @@ int crl_main(int argc, char **argv)
if (num) {
for (i = 1; i <= num; i++) {
if (issuer == i) {
- print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
- get_nameopt());
+ print_name(bio_out, "issuer=", X509_CRL_get_issuer(x));
}
if (crlnumber == i) {
ASN1_INTEGER *crlnum;
+
crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
BIO_printf(bio_out, "crlNumber=");
if (crlnum) {
+ BIO_puts(bio_out, "0x");
i2a_ASN1_INTEGER(bio_out, crlnum);
ASN1_INTEGER_free(crlnum);
- } else
+ } else {
BIO_puts(bio_out, "<NONE>");
+ }
BIO_printf(bio_out, "\n");
}
if (hash == i) {
- BIO_printf(bio_out, "%08lx\n",
- X509_NAME_hash(X509_CRL_get_issuer(x)));
+ int ok;
+ unsigned long hash_value =
+ X509_NAME_hash_ex(X509_CRL_get_issuer(x), app_get0_libctx(),
+ app_get0_propq(), &ok);
+
+ if (num > 1)
+ BIO_printf(bio_out, "issuer name hash=");
+ if (ok) {
+ BIO_printf(bio_out, "%08lx\n", hash_value);
+ } else {
+ BIO_puts(bio_out, "<ERROR>");
+ goto end;
+ }
}
#ifndef OPENSSL_NO_MD5
if (hash_old == i) {
+ if (num > 1)
+ BIO_printf(bio_out, "issuer name old hash=");
BIO_printf(bio_out, "%08lx\n",
X509_NAME_hash_old(X509_CRL_get_issuer(x)));
}
#endif
if (lastupdate == i) {
BIO_printf(bio_out, "lastUpdate=");
- ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x));
+ ASN1_TIME_print_ex(bio_out, X509_CRL_get0_lastUpdate(x), dateopt);
BIO_printf(bio_out, "\n");
}
if (nextupdate == i) {
BIO_printf(bio_out, "nextUpdate=");
if (X509_CRL_get0_nextUpdate(x))
- ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x));
+ ASN1_TIME_print_ex(bio_out, X509_CRL_get0_nextUpdate(x), dateopt);
else
BIO_printf(bio_out, "NONE");
BIO_printf(bio_out, "\n");
@@ -301,7 +354,7 @@ int crl_main(int argc, char **argv)
goto end;
}
BIO_printf(bio_out, "%s Fingerprint=",
- OBJ_nid2sn(EVP_MD_type(digest)));
+ EVP_MD_get0_name(digest));
for (j = 0; j < (int)n; j++) {
BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
? '\n' : ':');
@@ -335,6 +388,7 @@ int crl_main(int argc, char **argv)
if (ret != 0)
ERR_print_errors(bio_err);
BIO_free_all(out);
+ EVP_MD_free(digest);
X509_CRL_free(x);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
diff --git a/apps/crl2p7.c b/apps/crl2pkcs7.c
index 3f619bf5278e..fe59e654270d 100644
--- a/apps/crl2p7.c
+++ b/apps/crl2pkcs7.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -22,19 +22,27 @@
static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE
+ OPT_COMMON,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS crl2pkcs7_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
- {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
{"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"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -88,8 +96,14 @@ int crl2pkcs7_main(int argc, char **argv)
if (!sk_OPENSSL_STRING_push(certflst, opt_arg()))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No remaining args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
diff --git a/apps/dgst.c b/apps/dgst.c
index f9b184be4cc1..1042d940f49c 100644
--- a/apps/dgst.c
+++ b/apps/dgst.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -24,7 +24,7 @@
#undef BUFSIZE
#define BUFSIZE 1024*8
-int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
+int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
EVP_PKEY *key, unsigned char *sigin, int siglen,
const char *sig_name, const char *md_name,
const char *file);
@@ -36,49 +36,58 @@ struct doall_dgst_digests {
};
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_LIST,
+ OPT_COMMON,
+ OPT_LIST,
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_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN,
OPT_DIGEST,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
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"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"list", OPT_LIST, '-', "List digests"},
+#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
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
{"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)"},
+ {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
{"hex", OPT_HEX, '-', "Print as hex dump"},
{"binary", OPT_BINARY, '-', "Print in binary form"},
+ {"xoflen", OPT_XOFLEN, 'p', "Output length for XOF algorithms. To obtain the maximum security strength set this to 32 (or greater) for SHAKE128, and 64 (or greater) for SHAKE256"},
{"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"},
+
+ OPT_SECTION("Signing"),
+ {"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"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
{"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"},
+ {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
+ "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
+
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
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"file", 0, 0, "Files to digest (optional; default is stdin)"},
{NULL}
};
@@ -89,21 +98,24 @@ int dgst_main(int argc, char **argv)
EVP_PKEY *sigkey = NULL;
STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
char *hmac_key = NULL;
- char *mac_name = NULL;
+ char *mac_name = NULL, *digestname = NULL;
char *passinarg = NULL, *passin = NULL;
- const EVP_MD *md = NULL, *m;
+ EVP_MD *md = NULL;
const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
const char *sigfile = NULL;
+ const char *md_name = 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;
+ int separator = 0, debug = 0, keyform = FORMAT_UNDEF, siglen = 0;
+ int i, ret = EXIT_FAILURE, out_bin = -1, want_pub = 0, do_verify = 0;
+ int xoflen = 0;
unsigned char *buf = NULL, *sigbuf = NULL;
int engine_impl = 0;
struct doall_dgst_digests dec;
- prog = opt_progname(argv[0]);
buf = app_malloc(BUFSIZE, "I/O buffer");
- md = EVP_get_digestbyname(prog);
+ md = (EVP_MD *)EVP_get_digestbyname(argv[0]);
+ if (md != NULL)
+ digestname = argv[0];
prog = opt_init(argc, argv, dgst_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -115,7 +127,7 @@ int dgst_main(int argc, char **argv)
goto end;
case OPT_HELP:
opt_help(dgst_options);
- ret = 0;
+ ret = EXIT_SUCCESS;
goto end;
case OPT_LIST:
BIO_printf(bio_out, "Supported digests:\n");
@@ -124,7 +136,7 @@ int dgst_main(int argc, char **argv)
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
show_digests, &dec);
BIO_printf(bio_out, "\n");
- ret = 0;
+ ret = EXIT_SUCCESS;
goto end;
case OPT_C:
separator = 1;
@@ -172,6 +184,9 @@ int dgst_main(int argc, char **argv)
case OPT_BINARY:
out_bin = 1;
break;
+ case OPT_XOFLEN:
+ xoflen = atoi(opt_arg());
+ break;
case OPT_DEBUG:
debug = 1;
break;
@@ -197,18 +212,29 @@ int dgst_main(int argc, char **argv)
goto opthelp;
break;
case OPT_DIGEST:
- if (!opt_md(opt_unknown(), &m))
- goto opthelp;
- md = m;
+ digestname = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
break;
}
}
+
+ /* Remaining args are files to digest. */
argc = opt_num_rest();
argv = opt_rest();
if (keyfile != NULL && argc > 1) {
BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog);
goto end;
}
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &md))
+ goto opthelp;
+ }
if (do_verify && sigfile == NULL) {
BIO_printf(bio_err,
@@ -220,13 +246,11 @@ int dgst_main(int argc, char **argv)
in = BIO_new(BIO_s_file());
bmd = BIO_new(BIO_f_md());
- if ((in == NULL) || (bmd == NULL)) {
- ERR_print_errors(bio_err);
+ if (in == NULL || bmd == NULL)
goto end;
- }
if (debug) {
- BIO_set_callback(in, BIO_debug_callback);
+ BIO_set_callback_ex(in, BIO_debug_callback_ex);
/* needed for windows 3.1 */
BIO_set_callback_arg(in, (char *)bio_err);
}
@@ -248,7 +272,7 @@ int dgst_main(int argc, char **argv)
goto end;
if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) {
- BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
+ BIO_printf(bio_err, "MAC and signing key cannot both be specified\n");
goto end;
}
@@ -256,16 +280,16 @@ int dgst_main(int argc, char **argv)
int type;
if (want_pub)
- sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file");
+ sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
else
- sigkey = load_key(keyfile, keyform, 0, passin, e, "key file");
+ sigkey = load_key(keyfile, keyform, 0, passin, e, "private key");
if (sigkey == NULL) {
/*
* load_[pub]key() has already printed an appropriate message
*/
goto end;
}
- type = EVP_PKEY_id(sigkey);
+ type = EVP_PKEY_get_id(sigkey);
if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) {
/*
* We implement PureEdDSA for these which doesn't have a separate
@@ -278,36 +302,34 @@ int dgst_main(int argc, char **argv)
if (mac_name != NULL) {
EVP_PKEY_CTX *mac_ctx = NULL;
- int r = 0;
- if (!init_gen_str(&mac_ctx, mac_name, impl, 0))
- goto mac_end;
+
+ if (!init_gen_str(&mac_ctx, mac_name, impl, 0, NULL, NULL))
+ goto end;
if (macopts != NULL) {
- char *macopt;
for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
- macopt = sk_OPENSSL_STRING_value(macopts, i);
+ char *macopt = sk_OPENSSL_STRING_value(macopts, i);
+
if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
- BIO_printf(bio_err,
- "MAC parameter error \"%s\"\n", macopt);
- ERR_print_errors(bio_err);
- goto mac_end;
+ EVP_PKEY_CTX_free(mac_ctx);
+ BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt);
+ goto end;
}
}
}
- if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
- BIO_puts(bio_err, "Error generating key\n");
- ERR_print_errors(bio_err);
- goto mac_end;
- }
- r = 1;
- mac_end:
+
+ sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */);
+ /* Verbose output would make external-tests gost-engine fail */
EVP_PKEY_CTX_free(mac_ctx);
- if (r == 0)
- goto end;
}
if (hmac_key != NULL) {
+ if (md == NULL) {
+ md = (EVP_MD *)EVP_sha256();
+ digestname = SN_sha256;
+ }
sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl,
- (unsigned char *)hmac_key, -1);
+ (unsigned char *)hmac_key,
+ strlen(hmac_key));
if (sigkey == NULL)
goto end;
}
@@ -315,28 +337,37 @@ int dgst_main(int argc, char **argv)
if (sigkey != NULL) {
EVP_MD_CTX *mctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
- int r;
+ int res;
+
if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
BIO_printf(bio_err, "Error getting context\n");
- ERR_print_errors(bio_err);
goto end;
}
if (do_verify)
- r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
+ if (impl == NULL)
+ res = EVP_DigestVerifyInit_ex(mctx, &pctx, digestname,
+ app_get0_libctx(),
+ app_get0_propq(), sigkey, NULL);
+ else
+ res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
else
- r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
- if (!r) {
+ if (impl == NULL)
+ res = EVP_DigestSignInit_ex(mctx, &pctx, digestname,
+ app_get0_libctx(),
+ app_get0_propq(), sigkey, NULL);
+ else
+ res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
+ if (res == 0) {
BIO_printf(bio_err, "Error setting context\n");
- ERR_print_errors(bio_err);
goto end;
}
if (sigopts != NULL) {
- char *sigopt;
for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
- sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+ char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+
if (pkey_ctrl_string(pctx, sigopt) <= 0) {
- BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Signature parameter error \"%s\"\n",
+ sigopt);
goto end;
}
}
@@ -347,32 +378,29 @@ int dgst_main(int argc, char **argv)
EVP_MD_CTX *mctx = NULL;
if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
BIO_printf(bio_err, "Error getting context\n");
- ERR_print_errors(bio_err);
goto end;
}
if (md == NULL)
- md = EVP_sha256();
+ md = (EVP_MD *)EVP_sha256();
if (!EVP_DigestInit_ex(mctx, md, impl)) {
BIO_printf(bio_err, "Error setting digest\n");
- ERR_print_errors(bio_err);
goto end;
}
}
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;
}
- siglen = EVP_PKEY_size(sigkey);
+ siglen = EVP_PKEY_get_size(sigkey);
sigbuf = app_malloc(siglen, "signature buffer");
siglen = BIO_read(sigbio, sigbuf, siglen);
BIO_free(sigbio);
if (siglen <= 0) {
BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
- ERR_print_errors(bio_err);
goto end;
}
}
@@ -380,48 +408,62 @@ int dgst_main(int argc, char **argv)
if (md == NULL) {
EVP_MD_CTX *tctx;
+
BIO_get_md_ctx(bmd, &tctx);
- md = EVP_MD_CTX_md(tctx);
+ md = EVP_MD_CTX_get1_md(tctx);
+ }
+ if (md != NULL)
+ md_name = EVP_MD_get0_name(md);
+
+ if (xoflen > 0) {
+ if (!(EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF)) {
+ BIO_printf(bio_err, "Length can only be specified for XOF\n");
+ goto end;
+ }
+ /*
+ * Signing using XOF is not supported by any algorithms currently since
+ * each algorithm only calls EVP_DigestFinal_ex() in their sign_final
+ * and verify_final methods.
+ */
+ if (sigkey != NULL) {
+ BIO_printf(bio_err, "Signing key cannot be specified for XOF\n");
+ goto end;
+ }
}
if (argc == 0) {
BIO_set_fp(in, stdin, BIO_NOCLOSE);
- ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
- siglen, NULL, NULL, "stdin");
+ ret = do_fp(out, buf, inp, separator, out_bin, xoflen, sigkey, sigbuf,
+ siglen, NULL, md_name, "stdin");
} else {
- const char *md_name = NULL, *sig_name = NULL;
- if (!out_bin) {
- 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 != NULL)
- md_name = EVP_MD_name(md);
+ const char *sig_name = NULL;
+
+ if (out_bin == 0) {
+ if (sigkey != NULL)
+ sig_name = EVP_PKEY_get0_type_name(sigkey);
}
- ret = 0;
+ ret = EXIT_SUCCESS;
for (i = 0; i < argc; i++) {
- int r;
if (BIO_read_filename(in, argv[i]) <= 0) {
perror(argv[i]);
- ret++;
+ ret = EXIT_FAILURE;
continue;
} else {
- r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
- siglen, sig_name, md_name, argv[i]);
+ if (do_fp(out, buf, inp, separator, out_bin, xoflen,
+ sigkey, sigbuf, siglen, sig_name, md_name, argv[i]))
+ ret = EXIT_FAILURE;
}
- if (r)
- ret = r;
(void)BIO_reset(bmd);
}
}
end:
+ if (ret != EXIT_SUCCESS)
+ ERR_print_errors(bio_err);
OPENSSL_clear_free(buf, BUFSIZE);
BIO_free(in);
OPENSSL_free(passin);
BIO_free_all(out);
+ EVP_MD_free(md);
EVP_PKEY_free(sigkey);
sk_OPENSSL_STRING_free(sigopts);
sk_OPENSSL_STRING_free(macopts);
@@ -444,7 +486,7 @@ static void show_digests(const OBJ_NAME *name, void *arg)
return;
/* Filter out message digests that we cannot use */
- md = EVP_get_digestbyname(name->name);
+ md = EVP_MD_fetch(app_get0_libctx(), name->name, app_get0_propq());
if (md == NULL)
return;
@@ -496,20 +538,19 @@ static const char *newline_escape_filename(const char *file, int * backslash)
}
-int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
+int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
EVP_PKEY *key, unsigned char *sigin, int siglen,
const char *sig_name, const char *md_name,
const char *file)
{
size_t len = BUFSIZE;
- int i, backslash = 0, ret = 1;
- unsigned char *sigbuf = NULL;
+ int i, backslash = 0, ret = EXIT_FAILURE;
+ unsigned char *allocated_buf = NULL;
while (BIO_pending(bp) || !BIO_eof(bp)) {
i = BIO_read(bp, (char *)buf, BUFSIZE);
if (i < 0) {
- BIO_printf(bio_err, "Read Error in %s\n", file);
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Read error in %s\n", file);
goto end;
}
if (i == 0)
@@ -522,37 +563,52 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
if (i > 0) {
BIO_printf(out, "Verified OK\n");
} else if (i == 0) {
- BIO_printf(out, "Verification Failure\n");
+ BIO_printf(out, "Verification failure\n");
goto end;
} else {
- BIO_printf(bio_err, "Error Verifying Data\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error verifying data\n");
goto end;
}
- ret = 0;
+ ret = EXIT_SUCCESS;
goto end;
}
if (key != NULL) {
EVP_MD_CTX *ctx;
- int pkey_len;
+ size_t tmplen;
+
BIO_get_md_ctx(bp, &ctx);
- pkey_len = EVP_PKEY_size(key);
- if (pkey_len > BUFSIZE) {
- len = pkey_len;
- sigbuf = app_malloc(len, "Signature buffer");
- buf = sigbuf;
+ if (!EVP_DigestSignFinal(ctx, NULL, &tmplen)) {
+ BIO_printf(bio_err, "Error getting maximum length of signed data\n");
+ goto end;
+ }
+ if (tmplen > BUFSIZE) {
+ len = tmplen;
+ allocated_buf = app_malloc(len, "Signature buffer");
+ buf = allocated_buf;
}
if (!EVP_DigestSignFinal(ctx, buf, &len)) {
- BIO_printf(bio_err, "Error Signing Data\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error signing data\n");
+ goto end;
+ }
+ } else if (xoflen > 0) {
+ EVP_MD_CTX *ctx;
+
+ len = xoflen;
+ if (len > BUFSIZE) {
+ allocated_buf = app_malloc(len, "Digest buffer");
+ buf = allocated_buf;
+ }
+
+ BIO_get_md_ctx(bp, &ctx);
+
+ if (!EVP_DigestFinalXOF(ctx, buf, len)) {
+ BIO_printf(bio_err, "Error Digesting Data\n");
goto end;
}
} else {
len = BIO_gets(bp, (char *)buf, BUFSIZE);
- if ((int)len < 0) {
- ERR_print_errors(bio_err);
+ if ((int)len < 0)
goto end;
- }
}
if (binout) {
@@ -587,10 +643,10 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
BIO_printf(out, "\n");
}
- ret = 0;
+ ret = EXIT_SUCCESS;
end:
- if (sigbuf != NULL)
- OPENSSL_clear_free(sigbuf, len);
+ if (allocated_buf != NULL)
+ OPENSSL_clear_free(allocated_buf, len);
return ret;
}
diff --git a/apps/dh1024.pem b/apps/dh1024.pem
deleted file mode 100644
index 813e8a4a4822..000000000000
--- a/apps/dh1024.pem
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
-Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
-/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
------END DH PARAMETERS-----
-
-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
deleted file mode 100644
index 288a20997e5a..000000000000
--- a/apps/dh2048.pem
+++ /dev/null
@@ -1,14 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb
-IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft
-awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT
-mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh
-fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq
-5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==
------END DH PARAMETERS-----
-
-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
deleted file mode 100644
index 08560e1284e2..000000000000
--- a/apps/dh4096.pem
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN DH PARAMETERS-----
-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 "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/dhparam.c b/apps/dhparam.c
index 98c73214b53e..43906cea5649 100644
--- a/apps/dhparam.c
+++ b/apps/dhparam.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -17,61 +18,73 @@
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
+#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
-
-#ifndef OPENSSL_NO_DSA
-# include <openssl/dsa.h>
-#endif
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/param_build.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
#define DEFBITS 2048
-static int dh_cb(int p, int n, BN_GENCB *cb);
+static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh);
+static int gendh_cb(EVP_PKEY_CTX *ctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_DSAPARAM, OPT_2, OPT_3, OPT_5,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dhparam_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [flags] [numbits]\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"},
+
+ OPT_SECTION("General"),
{"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
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_DEPRECATED_3_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
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"},
+ {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"},
+ {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"},
+ {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"},
+ {"3", OPT_3, '-', "Generate parameters using 3 as the generator value"},
+ {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"numbits", 0, 0, "Number of bits if generating parameters (optional)"},
{NULL}
};
int dhparam_main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL;
- DH *dh = NULL;
+ EVP_PKEY *pkey = NULL, *tmppkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
char *infile = NULL, *outfile = NULL, *prog;
ENGINE *e = NULL;
-#ifndef OPENSSL_NO_DSA
int dsaparam = 0;
-#endif
- int i, text = 0, C = 0, ret = 1, num = 0, g = 0;
+ int text = 0, ret = 1, num = 0, g = 0;
int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0;
OPTION_CHOICE o;
@@ -111,16 +124,14 @@ int dhparam_main(int argc, char **argv)
text = 1;
break;
case OPT_DSAPARAM:
-#ifndef OPENSSL_NO_DSA
dsaparam = 1;
-#endif
- break;
- case OPT_C:
- C = 1;
break;
case OPT_2:
g = 2;
break;
+ case OPT_3:
+ g = 3;
+ break;
case OPT_5:
g = 5;
break;
@@ -131,24 +142,33 @@ int dhparam_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* One optional argument, bitsize to generate. */
argc = opt_num_rest();
argv = opt_rest();
-
- if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0))
+ if (argc == 1) {
+ if (!opt_int(argv[0], &num) || num <= 0)
+ goto opthelp;
+ } else if (argc != 0) {
+ goto opthelp;
+ }
+ if (!app_RAND_load())
goto end;
if (g && !num)
num = DEFBITS;
-#ifndef OPENSSL_NO_DSA
if (dsaparam && g) {
BIO_printf(bio_err,
- "generator may not be chosen for DSA parameters\n");
+ "Error, generator may not be chosen for DSA parameters\n");
goto end;
}
-#endif
out = bio_open_default(outfile, 'w', outformat);
if (out == NULL)
@@ -159,216 +179,238 @@ int dhparam_main(int argc, char **argv)
g = 2;
if (num) {
+ const char *alg = dsaparam ? "DSA" : "DH";
+
+ if (infile != NULL) {
+ BIO_printf(bio_err, "Warning, input file %s ignored\n", infile);
+ }
- BN_GENCB *cb;
- cb = BN_GENCB_new();
- if (cb == NULL) {
- ERR_print_errors(bio_err);
+ ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), alg, app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err,
+ "Error, %s param generation context allocation failed\n",
+ alg);
goto end;
}
+ EVP_PKEY_CTX_set_cb(ctx, gendh_cb);
+ EVP_PKEY_CTX_set_app_data(ctx, bio_err);
+ BIO_printf(bio_err,
+ "Generating %s parameters, %d bit long %sprime\n",
+ alg, num, dsaparam ? "" : "safe ");
- BN_GENCB_set(cb, dh_cb, bio_err);
+ if (EVP_PKEY_paramgen_init(ctx) <= 0) {
+ BIO_printf(bio_err,
+ "Error, unable to initialise %s parameters\n",
+ alg);
+ goto end;
+ }
-#ifndef OPENSSL_NO_DSA
if (dsaparam) {
- DSA *dsa = DSA_new();
-
- BIO_printf(bio_err,
- "Generating DSA parameters, %d bit long prime\n", num);
- if (dsa == NULL
- || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL,
- cb)) {
- DSA_free(dsa);
- BN_GENCB_free(cb);
- ERR_print_errors(bio_err);
+ if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num) <= 0) {
+ BIO_printf(bio_err, "Error, unable to set DSA prime length\n");
goto end;
}
-
- dh = DSA_dup_DH(dsa);
- DSA_free(dsa);
- if (dh == NULL) {
- BN_GENCB_free(cb);
- ERR_print_errors(bio_err);
+ } else {
+ if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, num) <= 0) {
+ BIO_printf(bio_err, "Error, unable to set DH prime length\n");
goto end;
}
- } else
-#endif
- {
- dh = DH_new();
- 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 == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) {
- BN_GENCB_free(cb);
- ERR_print_errors(bio_err);
+ if (EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, g) <= 0) {
+ BIO_printf(bio_err, "Error, unable to set generator\n");
goto end;
}
}
- BN_GENCB_free(cb);
+ tmppkey = app_paramgen(ctx, alg);
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+ if (dsaparam) {
+ pkey = dsa_to_dh(tmppkey);
+ if (pkey == NULL)
+ goto end;
+ EVP_PKEY_free(tmppkey);
+ } else {
+ pkey = tmppkey;
+ }
+ tmppkey = NULL;
} else {
+ OSSL_DECODER_CTX *decoderctx = NULL;
+ const char *keytype = "DH";
+ int done;
in = bio_open_default(infile, 'r', informat);
if (in == NULL)
goto end;
-#ifndef OPENSSL_NO_DSA
- if (dsaparam) {
- DSA *dsa;
-
- if (informat == FORMAT_ASN1)
- dsa = d2i_DSAparams_bio(in, NULL);
- else /* informat == FORMAT_PEM */
- dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
-
- if (dsa == NULL) {
- BIO_printf(bio_err, "unable to load DSA parameters\n");
- ERR_print_errors(bio_err);
- goto end;
- }
-
- dh = DSA_dup_DH(dsa);
- DSA_free(dsa);
- if (dh == NULL) {
- ERR_print_errors(bio_err);
- goto end;
- }
- } else
-#endif
- {
- if (informat == FORMAT_ASN1) {
+ do {
+ /*
+ * We assume we're done unless we explicitly want to retry and set
+ * this to 0 below.
+ */
+ done = 1;
+ /*
+ * We set NULL for the keytype to allow any key type. We don't know
+ * if we're going to get DH or DHX (or DSA in the event of dsaparam).
+ * We check that we got one of those key types afterwards.
+ */
+ decoderctx
+ = OSSL_DECODER_CTX_new_for_pkey(&tmppkey,
+ (informat == FORMAT_ASN1)
+ ? "DER" : "PEM",
+ NULL,
+ (informat == FORMAT_ASN1)
+ ? keytype : NULL,
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ NULL, NULL);
+
+ if (decoderctx != NULL
+ && !OSSL_DECODER_from_bio(decoderctx, in)
+ && informat == FORMAT_ASN1
+ && strcmp(keytype, "DH") == 0) {
+ /*
+ * When reading DER we explicitly state the expected keytype
+ * because, unlike PEM, there is no header to declare what
+ * the contents of the DER file are. The decoders just try
+ * and guess. Unfortunately with DHX key types they may guess
+ * wrong and think we have a DSA keytype. Therefore we try
+ * both DH and DHX sequentially.
+ */
+ keytype = "DHX";
/*
- * We have no PEM header to determine what type of DH params it
- * is. We'll just try both.
+ * BIO_reset() returns 0 for success for file BIOs only!!!
+ * This won't work for stdin (and never has done)
*/
- dh = d2i_DHparams_bio(in, NULL);
- /* BIO_reset() returns 0 for success for file BIOs only!!! */
- if (dh == NULL && BIO_reset(in) == 0)
- dh = d2i_DHxparams_bio(in, NULL);
- } else {
- /* informat == FORMAT_PEM */
- dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
+ if (BIO_reset(in) == 0)
+ done = 0;
}
+ OSSL_DECODER_CTX_free(decoderctx);
+ } while (!done);
+ if (tmppkey == NULL) {
+ BIO_printf(bio_err, "Error, unable to load parameters\n");
+ goto end;
+ }
- if (dh == NULL) {
- BIO_printf(bio_err, "unable to load DH parameters\n");
- ERR_print_errors(bio_err);
+ if (dsaparam) {
+ if (!EVP_PKEY_is_a(tmppkey, "DSA")) {
+ BIO_printf(bio_err, "Error, unable to load DSA parameters\n");
goto end;
}
+ pkey = dsa_to_dh(tmppkey);
+ if (pkey == NULL)
+ goto end;
+ } else {
+ if (!EVP_PKEY_is_a(tmppkey, "DH")
+ && !EVP_PKEY_is_a(tmppkey, "DHX")) {
+ BIO_printf(bio_err, "Error, unable to load DH parameters\n");
+ goto end;
+ }
+ pkey = tmppkey;
+ tmppkey = NULL;
}
-
- /* dh != NULL */
}
- if (text) {
- DHparams_print(out, dh);
- }
+ if (text)
+ EVP_PKEY_print_params(out, pkey, 4, NULL);
if (check) {
- if (!DH_check(dh, &i)) {
- ERR_print_errors(bio_err);
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "Error, failed to check DH parameters\n");
goto end;
}
- if (i & DH_CHECK_P_NOT_PRIME)
- BIO_printf(bio_err, "WARNING: p value is not prime\n");
- if (i & DH_CHECK_P_NOT_SAFE_PRIME)
- 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)
- BIO_printf(bio_err,
- "WARNING: unable to check the generator value\n");
- if (i & DH_NOT_SUITABLE_GENERATOR)
- BIO_printf(bio_err, "WARNING: the g value is not a generator\n");
- if (i == 0)
- 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");
+ if (EVP_PKEY_param_check(ctx) <= 0) {
+ BIO_printf(bio_err, "Error, invalid parameters generated\n");
goto end;
}
- }
- if (C) {
- unsigned char *data;
- int len, bits;
- const BIGNUM *pbn, *gbn;
-
- len = DH_size(dh);
- bits = DH_bits(dh);
- DH_get0_pqg(dh, &pbn, NULL, &gbn);
- data = app_malloc(len, "print a BN");
-
- 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);
+ BIO_printf(bio_err, "DH parameters appear to be ok.\n");
}
if (!noout) {
- const BIGNUM *q;
- DH_get0_pqg(dh, NULL, &q, NULL);
- if (outformat == FORMAT_ASN1) {
- if (q != NULL)
- i = i2d_DHxparams_bio(out, dh);
- else
- i = i2d_DHparams_bio(out, dh);
- } else if (q != NULL) {
- i = PEM_write_bio_DHxparams(out, dh);
- } else {
- i = PEM_write_bio_DHparams(out, dh);
- }
- if (!i) {
- BIO_printf(bio_err, "unable to write DH parameters\n");
- ERR_print_errors(bio_err);
+ OSSL_ENCODER_CTX *ectx =
+ OSSL_ENCODER_CTX_new_for_pkey(pkey,
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ outformat == FORMAT_ASN1
+ ? "DER" : "PEM",
+ NULL, NULL);
+
+ if (ectx == NULL || !OSSL_ENCODER_to_bio(ectx, out)) {
+ OSSL_ENCODER_CTX_free(ectx);
+ BIO_printf(bio_err, "Error, unable to write DH parameters\n");
goto end;
}
+ OSSL_ENCODER_CTX_free(ectx);
}
ret = 0;
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
BIO_free(in);
BIO_free_all(out);
- DH_free(dh);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(tmppkey);
+ EVP_PKEY_CTX_free(ctx);
release_engine(e);
return ret;
}
-static int dh_cb(int p, int n, BN_GENCB *cb)
+/*
+ * Historically we had the low level call DSA_dup_DH() to do this.
+ * That is now deprecated with no replacement. Since we still need to do this
+ * for backwards compatibility reasons, we do it "manually".
+ */
+static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh)
+{
+ OSSL_PARAM_BLD *tmpl = NULL;
+ OSSL_PARAM *params = NULL;
+ BIGNUM *bn_p = NULL, *bn_q = NULL, *bn_g = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ if (!EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_P, &bn_p)
+ || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_Q, &bn_q)
+ || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_G, &bn_g)) {
+ BIO_printf(bio_err, "Error, failed to set DH parameters\n");
+ goto err;
+ }
+
+ if ((tmpl = OSSL_PARAM_BLD_new()) == NULL
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P,
+ bn_p)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q,
+ bn_q)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G,
+ bn_g)
+ || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
+ BIO_printf(bio_err, "Error, failed to set DH parameters\n");
+ goto err;
+ }
+
+ ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DHX", app_get0_propq());
+ if (ctx == NULL
+ || EVP_PKEY_fromdata_init(ctx) <= 0
+ || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEY_PARAMETERS, params) <= 0) {
+ BIO_printf(bio_err, "Error, failed to set DH parameters\n");
+ goto err;
+ }
+
+ err:
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(tmpl);
+ BN_free(bn_p);
+ BN_free(bn_q);
+ BN_free(bn_g);
+ return pkey;
+}
+
+static int gendh_cb(EVP_PKEY_CTX *ctx)
{
+ int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+ BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
static const char symbols[] = ".+*\n";
char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
- BIO_write(BN_GENCB_get_arg(cb), &c, 1);
- (void)BIO_flush(BN_GENCB_get_arg(cb));
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
return 1;
}
diff --git a/apps/dsa.c b/apps/dsa.c
index c7884df166b7..51c02843539f 100644
--- a/apps/dsa.c
+++ b/apps/dsa.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -21,29 +22,29 @@
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
+#include <openssl/encoder.h>
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+
+#ifndef OPENSSL_NO_RC4
+# define DEFAULT_PVK_ENCR_STRENGTH 2
+#else
+# define DEFAULT_PVK_ENCR_STRENGTH 0
+#endif
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dsa_options[] = {
+ OPT_SECTION("General"),
{"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)"},
@@ -53,24 +54,43 @@ const OPTIONS dsa_options[] = {
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
#endif
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, 's', "Input key"},
+ {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/PVK); has no effect"},
+ {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"},
+ {"noout", OPT_NOOUT, '-', "Don't print key out"},
+ {"text", OPT_TEXT, '-', "Print the key in text"},
+ {"modulus", OPT_MODULUS, '-', "Print the DSA public value"},
+ {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
int dsa_main(int argc, char **argv)
{
BIO *out = NULL;
- DSA *dsa = NULL;
ENGINE *e = NULL;
- const EVP_CIPHER *enc = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_CIPHER *enc = NULL;
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;
-#endif
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, noout = 0;
+ int modulus = 0, pubin = 0, pubout = 0, ret = 1;
+ int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH;
int private = 0;
+ const char *output_type = NULL, *ciphername = NULL;
+ const char *output_structure = NULL;
+ int selection = 0;
+ OSSL_ENCODER_CTX *ectx = NULL;
prog = opt_init(argc, argv, dsa_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -131,15 +151,24 @@ int dsa_main(int argc, char **argv)
pubout = 1;
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
+ ciphername = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
goto end;
break;
}
}
+
+ /* No extra args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto end;
+ }
private = pubin || pubout ? 0 : 1;
if (text && !pubin)
private = 1;
@@ -150,24 +179,20 @@ int dsa_main(int argc, char **argv)
}
BIO_printf(bio_err, "read DSA key\n");
- {
- 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 (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) {
- dsa = EVP_PKEY_get1_DSA(pkey);
- EVP_PKEY_free(pkey);
- }
- }
- if (dsa == NULL) {
+ if (pkey == NULL) {
BIO_printf(bio_err, "unable to load Key\n");
ERR_print_errors(bio_err);
goto end;
}
+ if (!EVP_PKEY_is_a(pkey, "DSA")) {
+ BIO_printf(bio_err, "Not a DSA key\n");
+ goto end;
+ }
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
@@ -175,7 +200,8 @@ int dsa_main(int argc, char **argv)
if (text) {
assert(pubin || private);
- if (!DSA_print(out, dsa, 0)) {
+ if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
+ || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) {
perror(outfile);
ERR_print_errors(bio_err);
goto end;
@@ -183,11 +209,16 @@ int dsa_main(int argc, char **argv)
}
if (modulus) {
- const BIGNUM *pub_key = NULL;
- DSA_get0_key(dsa, &pub_key, NULL);
+ BIGNUM *pub_key = NULL;
+
+ if (!EVP_PKEY_get_bn_param(pkey, "pub", &pub_key)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
BIO_printf(out, "Public Key=");
BN_print(out, pub_key);
BIO_printf(out, "\n");
+ BN_free(pub_key);
}
if (noout) {
@@ -196,63 +227,83 @@ int dsa_main(int argc, char **argv)
}
BIO_printf(bio_err, "writing DSA key\n");
if (outformat == FORMAT_ASN1) {
- if (pubin || pubout) {
- i = i2d_DSA_PUBKEY_bio(out, dsa);
- } else {
- assert(private);
- i = i2d_DSAPrivateKey_bio(out, dsa);
- }
+ output_type = "DER";
} else if (outformat == FORMAT_PEM) {
- if (pubin || pubout) {
- i = PEM_write_bio_DSA_PUBKEY(out, dsa);
- } else {
- assert(private);
- i = PEM_write_bio_DSAPrivateKey(out, dsa, enc,
- NULL, 0, NULL, passout);
- }
-#ifndef OPENSSL_NO_RSA
- } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
- EVP_PKEY *pk;
- pk = EVP_PKEY_new();
- if (pk == NULL)
- goto end;
-
- EVP_PKEY_set1_DSA(pk, dsa);
- 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);
+ output_type = "PEM";
+ } else if (outformat == FORMAT_MSBLOB) {
+ output_type = "MSBLOB";
+ } else if (outformat == FORMAT_PVK) {
+ if (pubin) {
+ BIO_printf(bio_err, "PVK form impossible with public key input\n");
goto end;
-# else
- i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
-# endif
- } else if (pubin || pubout) {
- i = i2b_PublicKey_bio(out, pk);
- } else {
- assert(private);
- i = i2b_PrivateKey_bio(out, pk);
}
- EVP_PKEY_free(pk);
-#endif
+ output_type = "PVK";
} else {
BIO_printf(bio_err, "bad output format specified for outfile\n");
goto end;
}
- if (i <= 0) {
- BIO_printf(bio_err, "unable to write private key\n");
- ERR_print_errors(bio_err);
+
+ if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) {
+ if (pubout || pubin)
+ output_structure = "SubjectPublicKeyInfo";
+ else
+ output_structure = "type-specific";
+ }
+
+ /* Select what you want in the output */
+ if (pubout || pubin) {
+ selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ } else {
+ assert(private);
+ selection = (OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
+ }
+
+ /* Perform the encoding */
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, output_type,
+ output_structure, NULL);
+ if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) {
+ BIO_printf(bio_err, "%s format not supported\n", output_type);
+ goto end;
+ }
+
+ /* Passphrase setup */
+ if (enc != NULL)
+ OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL);
+
+ /* Default passphrase prompter */
+ if (enc != NULL || outformat == FORMAT_PVK) {
+ OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL);
+ if (passout != NULL)
+ /* When passout given, override the passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase(ectx,
+ (const unsigned char *)passout,
+ strlen(passout));
+ }
+
+ /* PVK requires a bit more */
+ if (outformat == FORMAT_PVK) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr);
+ if (!OSSL_ENCODER_CTX_set_params(ectx, params)) {
+ BIO_printf(bio_err, "invalid PVK encryption level\n");
+ goto end;
+ }
+ }
+
+ if (!OSSL_ENCODER_to_bio(ectx, out)) {
+ BIO_printf(bio_err, "unable to write key\n");
goto end;
}
ret = 0;
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ OSSL_ENCODER_CTX_free(ectx);
BIO_free_all(out);
- DSA_free(dsa);
+ EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(enc);
release_engine(e);
OPENSSL_free(passin);
OPENSSL_free(passout);
diff --git a/apps/dsaparam.c b/apps/dsaparam.c
index 75589ac6bc4e..b5555282be6e 100644
--- a/apps/dsaparam.c
+++ b/apps/dsaparam.c
@@ -1,15 +1,17 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
#include <stdlib.h>
+#include "apps.h"
#include <time.h>
#include <string.h>
#include "apps.h"
@@ -21,39 +23,54 @@
#include <openssl/x509.h>
#include <openssl/pem.h>
-static int dsa_cb(int p, int n, BN_GENCB *cb);
+static int verbose = 0;
+
+static int gendsa_cb(EVP_PKEY_CTX *ctx);
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
+ OPT_COMMON,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT,
+ OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_VERBOSE,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dsaparam_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
- {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+
+ OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
{"text", OPT_TEXT, '-', "Print as text"},
- {"C", OPT_C, '-', "Output C code"},
{"noout", OPT_NOOUT, '-', "No output"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose 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
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"numbits", 0, 0, "Number of bits if generating parameters (optional)"},
{NULL}
};
int dsaparam_main(int argc, char **argv)
{
ENGINE *e = NULL;
- DSA *dsa = NULL;
- BIO *in = NULL, *out = NULL;
- BN_GENCB *cb = NULL;
+ BIO *out = NULL;
+ EVP_PKEY *params = NULL, *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
int numbits = -1, num = 0, genkey = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, noout = 0;
int ret = 1, i, text = 0, private = 0;
char *infile = NULL, *outfile = NULL, *prog;
OPTION_CHOICE o;
@@ -90,9 +107,6 @@ int dsaparam_main(int argc, char **argv)
case OPT_TEXT:
text = 1;
break;
- case OPT_C:
- C = 1;
- break;
case OPT_GENKEY:
genkey = 1;
break;
@@ -100,29 +114,45 @@ int dsaparam_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_NOOUT:
noout = 1;
break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
}
}
+
+ /* Optional arg is bitsize. */
argc = opt_num_rest();
argv = opt_rest();
-
if (argc == 1) {
if (!opt_int(argv[0], &num) || num < 0)
- goto end;
- /* generate a key */
- numbits = num;
+ goto opthelp;
+ } else if (argc != 0) {
+ goto opthelp;
}
+ if (!app_RAND_load())
+ goto end;
+
+ /* generate a key */
+ numbits = num;
private = genkey ? 1 : 0;
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
goto end;
+ ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DSA", app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err,
+ "Error, DSA parameter generation context allocation failed\n");
+ goto end;
+ }
if (numbits > 0) {
if (numbits > OPENSSL_DSA_MAX_MODULUS_BITS)
BIO_printf(bio_err,
@@ -130,74 +160,34 @@ int dsaparam_main(int argc, char **argv)
" 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;
+ EVP_PKEY_CTX_set_cb(ctx, gendsa_cb);
+ EVP_PKEY_CTX_set_app_data(ctx, bio_err);
+ if (verbose) {
+ BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n",
+ num);
+ BIO_printf(bio_err, "This could take some time\n");
}
- BN_GENCB_set(cb, dsa_cb, bio_err);
- dsa = DSA_new();
- if (dsa == NULL) {
- BIO_printf(bio_err, "Error allocating DSA object\n");
+ if (EVP_PKEY_paramgen_init(ctx) <= 0) {
+ BIO_printf(bio_err,
+ "Error, DSA key generation paramgen init failed\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");
- 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");
+ if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num) <= 0) {
+ BIO_printf(bio_err,
+ "Error, DSA key generation setting bit length failed\n");
goto end;
}
- } else if (informat == FORMAT_ASN1) {
- dsa = d2i_DSAparams_bio(in, NULL);
+ params = app_paramgen(ctx, "DSA");
} else {
- dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
+ params = load_keyparams(infile, informat, 1, "DSA", "DSA parameters");
}
- if (dsa == NULL) {
- BIO_printf(bio_err, "unable to load DSA parameters\n");
- ERR_print_errors(bio_err);
+ if (params == NULL) {
+ /* Error message should already have been displayed */
goto end;
}
if (text) {
- DSAparams_print(out, dsa);
- }
-
- if (C) {
- const BIGNUM *p = NULL, *q = NULL, *g = NULL;
- unsigned char *data;
- int len, bits_p;
-
- DSA_get0_pqg(dsa, &p, &q, &g);
- len = BN_num_bytes(p);
- bits_p = BN_num_bits(p);
-
- data = app_malloc(len + 20, "BN space");
-
- 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);
+ EVP_PKEY_print_params(out, params, 0, NULL);
}
if (outformat == FORMAT_ASN1 && genkey)
@@ -205,49 +195,62 @@ int dsaparam_main(int argc, char **argv)
if (!noout) {
if (outformat == FORMAT_ASN1)
- i = i2d_DSAparams_bio(out, dsa);
+ i = i2d_KeyParams_bio(out, params);
else
- i = PEM_write_bio_DSAparams(out, dsa);
+ i = PEM_write_bio_Parameters(out, params);
if (!i) {
- BIO_printf(bio_err, "unable to write DSA parameters\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error, unable to write DSA parameters\n");
goto end;
}
}
if (genkey) {
- DSA *dsakey;
-
- if ((dsakey = DSAparams_dup(dsa)) == NULL)
+ EVP_PKEY_CTX_free(ctx);
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params,
+ app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err,
+ "Error, DSA key generation context allocation failed\n");
goto end;
- if (!DSA_generate_key(dsakey)) {
- ERR_print_errors(bio_err);
- DSA_free(dsakey);
+ }
+ if (EVP_PKEY_keygen_init(ctx) <= 0) {
+ BIO_printf(bio_err,
+ "Error, unable to initialise for key generation\n");
goto end;
}
+ pkey = app_keygen(ctx, "DSA", numbits, verbose);
assert(private);
if (outformat == FORMAT_ASN1)
- i = i2d_DSAPrivateKey_bio(out, dsakey);
+ i = i2d_PrivateKey_bio(out, pkey);
else
- i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL,
- NULL);
- DSA_free(dsakey);
+ i = PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, NULL);
}
ret = 0;
end:
- BN_GENCB_free(cb);
- BIO_free(in);
+ if (ret != 0)
+ ERR_print_errors(bio_err);
BIO_free_all(out);
- DSA_free(dsa);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(params);
release_engine(e);
return ret;
}
-static int dsa_cb(int p, int n, BN_GENCB *cb)
+static int gendsa_cb(EVP_PKEY_CTX *ctx)
{
static const char symbols[] = ".+*\n";
- char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
+ int p;
+ char c;
+ BIO *b;
+
+ if (!verbose)
+ return 1;
+
+ b = EVP_PKEY_CTX_get_app_data(ctx);
+ p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+ c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
- BIO_write(BN_GENCB_get_arg(cb), &c, 1);
- (void)BIO_flush(BN_GENCB_get_arg(cb));
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
return 1;
}
diff --git a/apps/ec.c b/apps/ec.c
index 0c8ed750cc17..e2dd6f2b48f3 100644
--- a/apps/ec.c
+++ b/apps/ec.c
@@ -1,84 +1,84 @@
/*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include "apps.h"
-#include "progs.h"
-#include <openssl/bio.h>
-#include <openssl/err.h>
+#include <openssl/opensslconf.h>
#include <openssl/evp.h>
-#include <openssl/pem.h>
-
-static OPT_PAIR conv_forms[] = {
- {"compressed", POINT_CONVERSION_COMPRESSED},
- {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
- {"hybrid", POINT_CONVERSION_HYBRID},
- {NULL}
-};
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
-static OPT_PAIR param_enc[] = {
- {"named_curve", OPENSSL_EC_NAMED_CURVE},
- {"explicit", 0},
- {NULL}
-};
+#include "apps.h"
+#include "progs.h"
+#include "ec_common.h"
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_NO_PUBLIC, OPT_CHECK, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ec_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input file"},
- {"inform", OPT_INFORM, 'f', "Input format - DER or PEM"},
+ {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"},
+ {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"check", OPT_CHECK, '-', "check key consistency"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+ {"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_SECTION("Output"),
{"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
+
+ OPT_PROV_OPTIONS,
{NULL}
};
int ec_main(int argc, char **argv)
{
- BIO *in = NULL, *out = NULL;
+ OSSL_ENCODER_CTX *ectx = NULL;
+ OSSL_DECODER_CTX *dctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *eckey = NULL;
+ BIO *out = NULL;
ENGINE *e = NULL;
- EC_KEY *eckey = NULL;
- const EC_GROUP *group;
- const EVP_CIPHER *enc = NULL;
- point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
- char *infile = NULL, *outfile = NULL, *prog;
+ EVP_CIPHER *enc = NULL;
+ char *infile = NULL, *outfile = NULL, *ciphername = 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;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, noout = 0;
+ int pubin = 0, pubout = 0, param_out = 0, ret = 1, private = 0;
+ int check = 0;
+ char *asn1_encoding = NULL;
+ char *point_format = NULL;
+ int no_public = 0;
prog = opt_init(argc, argv, ec_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -131,20 +131,17 @@ int ec_main(int argc, char **argv)
e = setup_engine(opt_arg(), 0);
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto opthelp;
+ ciphername = opt_unknown();
break;
case OPT_CONV_FORM:
- if (!opt_pair(opt_arg(), conv_forms, &i))
+ point_format = opt_arg();
+ if (!opt_string(point_format, point_format_options))
goto opthelp;
- new_form = 1;
- form = i;
break;
case OPT_PARAM_ENC:
- if (!opt_pair(opt_arg(), param_enc, &i))
+ asn1_encoding = opt_arg();
+ if (!opt_string(asn1_encoding, asn1_encoding_options))
goto opthelp;
- new_asn1_flag = 1;
- asn1_flag = i;
break;
case OPT_NO_PUBLIC:
no_public = 1;
@@ -152,12 +149,22 @@ int ec_main(int argc, char **argv)
case OPT_CHECK:
check = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto opthelp;
+ }
private = param_out || pubin || pubout ? 0 : 1;
if (text && !pubin)
private = 1;
@@ -167,37 +174,15 @@ int ec_main(int argc, char **argv)
goto end;
}
- if (informat != FORMAT_ENGINE) {
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
- }
-
BIO_printf(bio_err, "read EC key\n");
- if (informat == FORMAT_ASN1) {
- if (pubin)
- eckey = d2i_EC_PUBKEY_bio(in, NULL);
- else
- eckey = d2i_ECPrivateKey_bio(in, NULL);
- } 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);
- }
+
+ if (pubin)
+ eckey = load_pubkey(infile, informat, 1, passin, e, "public key");
+ else
+ eckey = load_key(infile, informat, 1, passin, e, "private key");
+
if (eckey == NULL) {
BIO_printf(bio_err, "unable to load Key\n");
- ERR_print_errors(bio_err);
goto end;
}
@@ -205,74 +190,105 @@ int ec_main(int argc, char **argv)
if (out == NULL)
goto end;
- group = EC_KEY_get0_group(eckey);
-
- if (new_form)
- EC_KEY_set_conv_form(eckey, form);
+ if (point_format
+ && !EVP_PKEY_set_utf8_string_param(
+ eckey, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format)) {
+ BIO_printf(bio_err, "unable to set point conversion format\n");
+ goto end;
+ }
- if (new_asn1_flag)
- EC_KEY_set_asn1_flag(eckey, asn1_flag);
+ if (asn1_encoding != NULL
+ && !EVP_PKEY_set_utf8_string_param(
+ eckey, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
+ BIO_printf(bio_err, "unable to set asn1 encoding format\n");
+ goto end;
+ }
- if (no_public)
- EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
+ if (no_public) {
+ if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0)) {
+ BIO_printf(bio_err, "unable to disable public key encoding\n");
+ goto end;
+ }
+ } else {
+ if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 1)) {
+ BIO_printf(bio_err, "unable to enable public key encoding\n");
+ goto end;
+ }
+ }
if (text) {
assert(pubin || private);
- if (!EC_KEY_print(out, eckey, 0)) {
- perror(outfile);
- ERR_print_errors(bio_err);
+ if ((pubin && EVP_PKEY_print_public(out, eckey, 0, NULL) <= 0)
+ || (!pubin && EVP_PKEY_print_private(out, eckey, 0, NULL) <= 0)) {
+ BIO_printf(bio_err, "unable to print EC key\n");
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);
+ pctx = EVP_PKEY_CTX_new_from_pkey(NULL, eckey, NULL);
+ if (pctx == NULL) {
+ BIO_printf(bio_err, "unable to check EC key\n");
+ goto end;
}
+ if (EVP_PKEY_check(pctx) <= 0)
+ BIO_printf(bio_err, "EC Key Invalid!\n");
+ else
+ BIO_printf(bio_err, "EC Key valid.\n");
+ ERR_print_errors(bio_err);
}
- if (noout) {
- ret = 0;
- goto end;
- }
+ if (!noout) {
+ int selection;
+ const char *output_type = outformat == FORMAT_ASN1 ? "DER" : "PEM";
+ const char *output_structure = "type-specific";
- BIO_printf(bio_err, "writing EC key\n");
- if (outformat == FORMAT_ASN1) {
+ BIO_printf(bio_err, "writing EC key\n");
if (param_out) {
- i = i2d_ECPKParameters_bio(out, group);
+ selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
} else if (pubin || pubout) {
- i = i2d_EC_PUBKEY_bio(out, eckey);
+ selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
+ | OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ output_structure = "SubjectPublicKeyInfo";
} else {
+ selection = OSSL_KEYMGMT_SELECT_ALL;
assert(private);
- i = i2d_ECPrivateKey_bio(out, eckey);
}
- } else {
- if (param_out) {
- i = PEM_write_bio_ECPKParameters(out, group);
- } else if (pubin || pubout) {
- i = PEM_write_bio_EC_PUBKEY(out, eckey);
- } else {
- assert(private);
- i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
- NULL, 0, NULL, passout);
+
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(eckey, selection,
+ output_type, output_structure,
+ NULL);
+ if (enc != NULL) {
+ OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL);
+ /* Default passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL);
+ if (passout != NULL)
+ /* When passout given, override the passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase(ectx,
+ (const unsigned char *)passout,
+ strlen(passout));
+ }
+ if (!OSSL_ENCODER_to_bio(ectx, out)) {
+ BIO_printf(bio_err, "unable to write EC key\n");
+ goto end;
}
}
- if (!i) {
- BIO_printf(bio_err, "unable to write private key\n");
+ ret = 0;
+end:
+ if (ret != 0)
ERR_print_errors(bio_err);
- } else {
- ret = 0;
- }
- end:
- BIO_free(in);
BIO_free_all(out);
- EC_KEY_free(eckey);
+ EVP_PKEY_free(eckey);
+ EVP_CIPHER_free(enc);
+ OSSL_ENCODER_CTX_free(ectx);
+ OSSL_DECODER_CTX_free(dctx);
+ EVP_PKEY_CTX_free(pctx);
release_engine(e);
- OPENSSL_free(passin);
- OPENSSL_free(passout);
+ if (passin != NULL)
+ OPENSSL_clear_free(passin, strlen(passin));
+ if (passout != NULL)
+ OPENSSL_clear_free(passout, strlen(passout));
return ret;
}
diff --git a/apps/ecparam.c b/apps/ecparam.c
index 58fbeb95c9ce..9e9ad136837b 100644
--- a/apps/ecparam.c
+++ b/apps/ecparam.c
@@ -1,92 +1,115 @@
/*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 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
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
-#include <stdlib.h>
-#include <time.h>
#include <string.h>
+#include <openssl/opensslconf.h>
+#include <openssl/evp.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include <openssl/core_names.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
#include "apps.h"
#include "progs.h"
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/bn.h>
-#include <openssl/ec.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
+#include "ec_common.h"
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_COMMON,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT,
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
+ OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, OPT_CHECK_NAMED,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ecparam_options[] = {
+ OPT_SECTION("General"),
{"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"},
+ {"list_curves", OPT_LIST_CURVES, '-',
+ "Prints a list of all curve 'short names'"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ {"genkey", OPT_GENKEY, '-', "Generate ec key"},
{"in", OPT_IN, '<', "Input file - default stdin"},
+ {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
{"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
+
+ OPT_SECTION("Output"),
{"text", OPT_TEXT, '-', "Print the ec parameters in text form"},
- {"C", OPT_C, '-', "Print a 'C' function creating the parameters"},
+ {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"},
+ {"param_enc", OPT_PARAM_ENC, 's',
+ "Specifies the way the ec parameters are encoded"},
+
+ OPT_SECTION("Parameter"),
{"check", OPT_CHECK, '-', "Validate the ec parameters"},
- {"list_curves", OPT_LIST_CURVES, '-',
- "Prints a list of all curve 'short names'"},
+ {"check_named", OPT_CHECK_NAMED, '-',
+ "Check that named EC curve parameters have not been modified"},
{"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
+ OPT_PROV_OPTIONS,
{NULL}
};
-static OPT_PAIR forms[] = {
- {"compressed", POINT_CONVERSION_COMPRESSED},
- {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
- {"hybrid", POINT_CONVERSION_HYBRID},
- {NULL}
-};
+static int list_builtin_curves(BIO *out)
+{
+ int ret = 0;
+ EC_builtin_curve *curves = NULL;
+ size_t n, crv_len = EC_get_builtin_curves(NULL, 0);
-static OPT_PAIR encodings[] = {
- {"named_curve", OPENSSL_EC_NAMED_CURVE},
- {"explicit", 0},
- {NULL}
-};
+ curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
+ if (!EC_get_builtin_curves(curves, crv_len))
+ goto end;
+
+ for (n = 0; n < crv_len; n++) {
+ const char *comment = curves[n].comment;
+ const char *sname = OBJ_nid2sn(curves[n].nid);
+
+ if (comment == NULL)
+ comment = "CURVE DESCRIPTION NOT AVAILABLE";
+ if (sname == NULL)
+ sname = "";
+
+ BIO_printf(out, " %-10s: ", sname);
+ BIO_printf(out, "%s\n", comment);
+ }
+ ret = 1;
+end:
+ OPENSSL_free(curves);
+ return ret;
+}
int ecparam_main(int argc, char **argv)
{
+ EVP_PKEY_CTX *gctx_params = NULL, *gctx_key = NULL, *pctx = NULL;
+ EVP_PKEY *params_key = NULL, *key = NULL;
+ OSSL_ENCODER_CTX *ectx_key = NULL, *ectx_params = NULL;
+ OSSL_DECODER_CTX *dctx_params = NULL;
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;
+ BIO *out = NULL;
char *curve_name = NULL;
+ char *asn1_encoding = NULL;
+ char *point_format = NULL;
char *infile = NULL, *outfile = NULL, *prog;
- 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 informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0;
int ret = 1, private = 0;
- int list_curves = 0, no_seed = 0, check = 0, new_form = 0;
- int text = 0, i, genkey = 0;
+ int no_seed = 0, check = 0, check_named = 0, text = 0, genkey = 0;
+ int list_curves = 0;
prog = opt_init(argc, argv, ecparam_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -117,12 +140,12 @@ int ecparam_main(int argc, char **argv)
case OPT_TEXT:
text = 1;
break;
- case OPT_C:
- C = 1;
- break;
case OPT_CHECK:
check = 1;
break;
+ case OPT_CHECK_NAMED:
+ check_named = 1;
+ break;
case OPT_LIST_CURVES:
list_curves = 1;
break;
@@ -136,15 +159,14 @@ int ecparam_main(int argc, char **argv)
curve_name = opt_arg();
break;
case OPT_CONV_FORM:
- if (!opt_pair(opt_arg(), forms, &new_form))
+ point_format = opt_arg();
+ if (!opt_string(point_format, point_format_options))
goto opthelp;
- form = new_form;
- new_form = 1;
break;
case OPT_PARAM_ENC:
- if (!opt_pair(opt_arg(), encodings, &asn1_flag))
+ asn1_encoding = opt_arg();
+ if (!opt_string(asn1_encoding, asn1_encoding_options))
goto opthelp;
- new_asn1_flag = 1;
break;
case OPT_GENKEY:
genkey = 1;
@@ -153,292 +175,178 @@ int ecparam_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
}
}
+
+ /* No extra args. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
private = genkey ? 1 : 0;
- 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 (list_curves) {
- EC_builtin_curve *curves = NULL;
- 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;
- }
-
- for (n = 0; n < crv_len; n++) {
- const char *comment;
- const char *sname;
- comment = curves[n].comment;
- sname = OBJ_nid2sn(curves[n].nid);
- if (comment == NULL)
- comment = "CURVE DESCRIPTION NOT AVAILABLE";
- if (sname == NULL)
- sname = "";
-
- BIO_printf(out, " %-10s: ", sname);
- BIO_printf(out, "%s\n", comment);
- }
-
- OPENSSL_free(curves);
- ret = 0;
+ if (list_builtin_curves(out))
+ ret = 0;
goto end;
}
if (curve_name != NULL) {
- int nid;
+ OSSL_PARAM params[4];
+ OSSL_PARAM *p = params;
- /*
- * workaround for the SECG curve names secp192r1 and secp256r1 (which
- * are the same as the curves prime192v1 and prime256v1 defined in
- * X9.62)
- */
if (strcmp(curve_name, "secp192r1") == 0) {
- BIO_printf(bio_err, "using curve name prime192v1 "
- "instead of secp192r1\n");
- nid = NID_X9_62_prime192v1;
+ BIO_printf(bio_err,
+ "using curve name prime192v1 instead of secp192r1\n");
+ curve_name = SN_X9_62_prime192v1;
} 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 {
- nid = OBJ_sn2nid(curve_name);
+ BIO_printf(bio_err,
+ "using curve name prime256v1 instead of secp256r1\n");
+ curve_name = SN_X9_62_prime256v1;
}
-
- if (nid == 0)
- nid = EC_curve_nist2nid(curve_name);
-
- if (nid == 0) {
- BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ curve_name, 0);
+ if (asn1_encoding != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
+ asn1_encoding, 0);
+ if (point_format != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format, 0);
+ *p = OSSL_PARAM_construct_end();
+
+ if (OPENSSL_strcasecmp(curve_name, "SM2") == 0)
+ gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "sm2",
+ app_get0_propq());
+ else
+ gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "ec",
+ app_get0_propq());
+ if (gctx_params == NULL
+ || EVP_PKEY_keygen_init(gctx_params) <= 0
+ || EVP_PKEY_CTX_set_params(gctx_params, params) <= 0
+ || EVP_PKEY_keygen(gctx_params, &params_key) <= 0) {
+ BIO_printf(bio_err, "unable to generate key\n");
+ goto end;
+ }
+ } else {
+ params_key = load_keyparams(infile, informat, 1, "EC", "EC parameters");
+ if (params_key == NULL || !EVP_PKEY_is_a(params_key, "EC"))
+ goto end;
+ if (point_format
+ && !EVP_PKEY_set_utf8_string_param(
+ params_key, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format)) {
+ BIO_printf(bio_err, "unable to set point conversion format\n");
goto end;
}
- group = EC_GROUP_new_by_curve_name(nid);
- if (group == NULL) {
- BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name);
+ if (asn1_encoding != NULL
+ && !EVP_PKEY_set_utf8_string_param(
+ params_key, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
+ BIO_printf(bio_err, "unable to set asn1 encoding format\n");
goto end;
}
- EC_GROUP_set_asn1_flag(group, asn1_flag);
- EC_GROUP_set_point_conversion_form(group, form);
- } else if (informat == FORMAT_ASN1) {
- group = d2i_ECPKParameters_bio(in, NULL);
- } else {
- 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);
- goto end;
- }
-
- if (new_form)
- EC_GROUP_set_point_conversion_form(group, form);
- if (new_asn1_flag)
- EC_GROUP_set_asn1_flag(group, asn1_flag);
-
- if (no_seed) {
- EC_GROUP_set_seed(group, NULL, 0);
+ if (no_seed
+ && !EVP_PKEY_set_octet_string_param(params_key, OSSL_PKEY_PARAM_EC_SEED,
+ NULL, 0)) {
+ BIO_printf(bio_err, "unable to clear seed\n");
+ goto end;
}
- if (text) {
- if (!ECPKParameters_print(out, group, 0))
- goto end;
+ if (text
+ && !EVP_PKEY_print_params(out, params_key, 0, NULL)) {
+ BIO_printf(bio_err, "unable to print params\n");
+ goto end;
}
- if (check) {
+ if (check || check_named) {
BIO_printf(bio_err, "checking elliptic curve parameters: ");
- if (!EC_GROUP_check(group, NULL)) {
- BIO_printf(bio_err, "failed\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- BIO_printf(bio_err, "ok\n");
-
- }
-
- if (C) {
- size_t buf_len = 0, tmp_len = 0;
- const EC_POINT *point;
- 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("Can't allocate BN");
- goto end;
+ if (check_named
+ && !EVP_PKEY_set_utf8_string_param(params_key,
+ OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
+ OSSL_PKEY_EC_GROUP_CHECK_NAMED)) {
+ BIO_printf(bio_err, "unable to set check_type\n");
+ goto end;
}
-
- is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field);
- if (!is_prime) {
- BIO_printf(bio_err, "Can only handle X9.62 prime fields\n");
+ pctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key,
+ app_get0_propq());
+ if (pctx == NULL || EVP_PKEY_param_check(pctx) <= 0) {
+ BIO_printf(bio_err, "failed\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,
- EC_GROUP_get_point_conversion_form(group),
- ec_gen, NULL))
- goto end;
- if (!EC_GROUP_get_order(group, ec_order, NULL))
- goto end;
- if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL))
- goto end;
-
- if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor)
- goto end;
-
- len = BN_num_bits(ec_order);
-
- if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len)
- buf_len = tmp_len;
- if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len)
- buf_len = tmp_len;
-
- buffer = app_malloc(buf_len, "BN 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, " 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");
+ BIO_printf(bio_err, "ok\n");
}
if (outformat == FORMAT_ASN1 && genkey)
noout = 1;
if (!noout) {
- if (outformat == FORMAT_ASN1)
- i = i2d_ECPKParameters_bio(out, group);
- else
- i = PEM_write_bio_ECPKParameters(out, group);
- if (!i) {
- BIO_printf(bio_err, "unable to write elliptic "
- "curve parameters\n");
- ERR_print_errors(bio_err);
+ ectx_params = OSSL_ENCODER_CTX_new_for_pkey(
+ params_key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
+ if (!OSSL_ENCODER_to_bio(ectx_params, out)) {
+ BIO_printf(bio_err, "unable to write elliptic curve parameters\n");
goto end;
}
}
if (genkey) {
- EC_KEY *eckey = EC_KEY_new();
-
- if (eckey == NULL)
- goto end;
-
- 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)) {
+ /*
+ * NOTE: EC keygen does not normally need to pass in the param_key
+ * for named curves. This can be achieved using:
+ * gctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+ * EVP_PKEY_keygen_init(gctx);
+ * EVP_PKEY_CTX_set_group_name(gctx, curvename);
+ * EVP_PKEY_keygen(gctx, &key) <= 0)
+ */
+ gctx_key = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key,
+ app_get0_propq());
+ if (EVP_PKEY_keygen_init(gctx_key) <= 0
+ || EVP_PKEY_keygen(gctx_key, &key) <= 0) {
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
- i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,
- NULL, 0, NULL, NULL);
- EC_KEY_free(eckey);
+ ectx_key = OSSL_ENCODER_CTX_new_for_pkey(
+ key, OSSL_KEYMGMT_SELECT_ALL,
+ outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
+ if (!OSSL_ENCODER_to_bio(ectx_key, out)) {
+ BIO_printf(bio_err, "unable to write elliptic "
+ "curve parameters\n");
+ goto end;
+ }
}
ret = 0;
- end:
- 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);
+end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
release_engine(e);
- BIO_free(in);
+ EVP_PKEY_free(params_key);
+ EVP_PKEY_free(key);
+ EVP_PKEY_CTX_free(pctx);
+ EVP_PKEY_CTX_free(gctx_params);
+ EVP_PKEY_CTX_free(gctx_key);
+ OSSL_DECODER_CTX_free(dctx_params);
+ OSSL_ENCODER_CTX_free(ectx_params);
+ OSSL_ENCODER_CTX_free(ectx_key);
BIO_free_all(out);
return ret;
}
diff --git a/apps/enc.c b/apps/enc.c
index 65710771a089..3dd609856304 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -39,38 +39,51 @@ struct doall_enc_ciphers {
};
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS enc_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"list", OPT_LIST, '-', "List ciphers"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
{"ciphers", OPT_LIST, '-', "Alias for -list"},
- {"in", OPT_IN, '<', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
- {"pass", OPT_PASS, 's', "Passphrase source"},
+#endif
{"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"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+ {"k", OPT_K, 's', "Passphrase"},
+ {"kfile", OPT_KFILE, '<', "Read passphrase from file"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"pass", OPT_PASS, 's', "Passphrase source"},
{"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"},
+
+ OPT_SECTION("Encryption"),
+ {"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"},
+
{"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"},
@@ -78,14 +91,13 @@ const OPTIONS enc_options[] = {
{"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, '-', "Compress or decompress encrypted data using zlib"},
#endif
-#ifndef OPENSSL_NO_ENGINE
- {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -97,11 +109,13 @@ int enc_main(int argc, char **argv)
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;
+ EVP_CIPHER *cipher = NULL;
+ EVP_MD *dgst = NULL;
+ const char *digestname = NULL;
char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p;
char *infile = NULL, *outfile = NULL, *prog;
char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL;
+ const char *ciphername = NULL;
char mbuf[sizeof(magic) - 1];
OPTION_CHOICE o;
int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0;
@@ -119,21 +133,15 @@ int enc_main(int argc, char **argv)
BIO *bzl = NULL;
#endif
- /* first check the program name */
- prog = opt_progname(argv[0]);
- if (strcmp(prog, "base64") == 0) {
+ /* first check the command name */
+ if (strcmp(argv[0], "base64") == 0)
base64 = 1;
#ifdef ZLIB
- } else if (strcmp(prog, "zlib") == 0) {
+ else if (strcmp(argv[0], "zlib") == 0)
do_zlib = 1;
#endif
- } 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;
- }
- }
+ else if (strcmp(argv[0], "enc") != 0)
+ ciphername = argv[0];
prog = opt_init(argc, argv, enc_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -252,17 +260,13 @@ int enc_main(int argc, char **argv)
hiv = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_arg(), &dgst))
- goto opthelp;
+ digestname = opt_arg();
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &c))
- goto opthelp;
- cipher = c;
+ ciphername = opt_unknown();
break;
case OPT_ITER:
- if (!opt_int(opt_arg(), &iter))
- goto opthelp;
+ iter = opt_int_arg();
pbkdf2 = 1;
break;
case OPT_PBKDF2:
@@ -277,25 +281,31 @@ int enc_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
- 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, "%s: AEAD ciphers not supported\n", prog);
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+ if (!app_RAND_load())
goto end;
- }
- if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) {
- BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog);
- goto end;
+ /* Get the cipher name, either from progname (if set) or flag. */
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &cipher))
+ goto opthelp;
+ }
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &dgst))
+ goto opthelp;
}
-
if (dgst == NULL)
- dgst = EVP_sha256();
+ dgst = (EVP_MD *)EVP_sha256();
if (iter == 0)
iter = 1;
@@ -342,7 +352,7 @@ int enc_main(int argc, char **argv)
char prompt[200];
BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:",
- OBJ_nid2ln(EVP_CIPHER_nid(cipher)),
+ EVP_CIPHER_get0_name(cipher),
(enc) ? "encryption" : "decryption");
strbuf[0] = '\0';
i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc);
@@ -371,8 +381,8 @@ int enc_main(int argc, char **argv)
goto end;
if (debug) {
- BIO_set_callback(in, BIO_debug_callback);
- BIO_set_callback(out, BIO_debug_callback);
+ BIO_set_callback_ex(in, BIO_debug_callback_ex);
+ BIO_set_callback_ex(out, BIO_debug_callback_ex);
BIO_set_callback_arg(in, (char *)bio_err);
BIO_set_callback_arg(out, (char *)bio_err);
}
@@ -385,7 +395,7 @@ int enc_main(int argc, char **argv)
if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
goto end;
if (debug) {
- BIO_set_callback(bzl, BIO_debug_callback);
+ BIO_set_callback_ex(bzl, BIO_debug_callback_ex);
BIO_set_callback_arg(bzl, (char *)bio_err);
}
if (enc)
@@ -399,7 +409,7 @@ int enc_main(int argc, char **argv)
if ((b64 = BIO_new(BIO_f_base64())) == NULL)
goto end;
if (debug) {
- BIO_set_callback(b64, BIO_debug_callback);
+ BIO_set_callback_ex(b64, BIO_debug_callback_ex);
BIO_set_callback_arg(b64, (char *)bio_err);
}
if (olb64)
@@ -411,14 +421,11 @@ int enc_main(int argc, char **argv)
}
if (cipher != NULL) {
- /*
- * Note that str is NULL if a key was passed on the command line, so
- * we get no salt in that case. Is this a bug?
- */
- if (str != NULL) {
+ if (str != NULL) { /* a passphrase is available */
/*
- * Salt handling: if encrypting generate a salt and write to
- * output BIO. If decrypting read salt from input BIO.
+ * Salt handling: if encrypting generate a salt if not supplied,
+ * and write to output BIO. If decrypting use salt from input BIO
+ * if not given with args
*/
unsigned char *sptr;
size_t str_len = strlen(str);
@@ -426,36 +433,47 @@ int enc_main(int argc, char **argv)
if (nosalt) {
sptr = NULL;
} else {
- if (enc) {
- if (hsalt) {
- if (!set_hex(hsalt, salt, sizeof(salt))) {
- BIO_printf(bio_err, "invalid hex salt value\n");
+ if (hsalt != NULL && !set_hex(hsalt, salt, sizeof(salt))) {
+ BIO_printf(bio_err, "invalid hex salt value\n");
+ goto end;
+ }
+ if (enc) { /* encryption */
+ if (hsalt == NULL) {
+ if (RAND_bytes(salt, sizeof(salt)) <= 0) {
+ BIO_printf(bio_err, "RAND_bytes failed\n");
+ goto end;
+ }
+ /*
+ * If -P option then don't bother writing.
+ * If salt is given, shouldn't either ?
+ */
+ if ((printkey != 2)
+ && (BIO_write(wbio, magic,
+ sizeof(magic) - 1) != sizeof(magic) - 1
+ || BIO_write(wbio,
+ (char *)salt,
+ sizeof(salt)) != sizeof(salt))) {
+ BIO_printf(bio_err, "error writing output file\n");
goto end;
}
- } else if (RAND_bytes(salt, sizeof(salt)) <= 0) {
- goto end;
}
- /*
- * If -P option then don't bother writing
- */
- if ((printkey != 2)
- && (BIO_write(wbio, magic,
- sizeof(magic) - 1) != sizeof(magic) - 1
- || BIO_write(wbio,
- (char *)salt,
- sizeof(salt)) != sizeof(salt))) {
- BIO_printf(bio_err, "error writing output file\n");
- goto end;
+ } else { /* decryption */
+ if (hsalt == NULL) {
+ if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
+ BIO_printf(bio_err, "error reading input file\n");
+ goto end;
+ }
+ if (memcmp(mbuf, magic, sizeof(mbuf)) == 0) { /* file IS salted */
+ if (BIO_read(rbio, salt,
+ sizeof(salt)) != sizeof(salt)) {
+ BIO_printf(bio_err, "error reading input file\n");
+ goto end;
+ }
+ } else { /* file is NOT salted, NO salt available */
+ BIO_printf(bio_err, "bad magic number\n");
+ goto end;
+ }
}
- } else if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)
- || BIO_read(rbio,
- (unsigned char *)salt,
- sizeof(salt)) != sizeof(salt)) {
- BIO_printf(bio_err, "error reading input file\n");
- goto end;
- } else if (memcmp(mbuf, magic, sizeof(magic) - 1)) {
- BIO_printf(bio_err, "bad magic number\n");
- goto end;
}
sptr = salt;
}
@@ -466,8 +484,8 @@ int enc_main(int argc, char **argv)
* 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);
+ int iklen = EVP_CIPHER_get_key_length(cipher);
+ int ivlen = EVP_CIPHER_get_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,
@@ -499,7 +517,7 @@ int enc_main(int argc, char **argv)
OPENSSL_cleanse(str, str_len);
}
if (hiv != NULL) {
- int siz = EVP_CIPHER_iv_length(cipher);
+ int siz = EVP_CIPHER_get_iv_length(cipher);
if (siz == 0) {
BIO_printf(bio_err, "warning: iv not used by this cipher\n");
} else if (!set_hex(hiv, iv, siz)) {
@@ -508,7 +526,7 @@ int enc_main(int argc, char **argv)
}
}
if ((hiv == NULL) && (str == NULL)
- && EVP_CIPHER_iv_length(cipher) != 0) {
+ && EVP_CIPHER_get_iv_length(cipher) != 0) {
/*
* No IV was explicitly set and no IV was generated.
* Hence the IV is undefined, making correct decryption impossible.
@@ -517,12 +535,12 @@ int enc_main(int argc, char **argv)
goto end;
}
if (hkey != NULL) {
- if (!set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) {
+ if (!set_hex(hkey, key, EVP_CIPHER_get_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));
+ cleanse(hkey);
}
if ((benc = BIO_new(BIO_f_cipher())) == NULL)
@@ -535,9 +553,9 @@ int enc_main(int argc, char **argv)
BIO_get_cipher_ctx(benc, &ctx);
- if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) {
+ if (!EVP_CipherInit_ex(ctx, cipher, e, NULL, NULL, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
- EVP_CIPHER_name(cipher));
+ EVP_CIPHER_get0_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
@@ -547,13 +565,13 @@ int enc_main(int argc, char **argv)
if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
- EVP_CIPHER_name(cipher));
+ EVP_CIPHER_get0_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
if (debug) {
- BIO_set_callback(benc, BIO_debug_callback);
+ BIO_set_callback_ex(benc, BIO_debug_callback_ex);
BIO_set_callback_arg(benc, (char *)bio_err);
}
@@ -564,15 +582,15 @@ int enc_main(int argc, char **argv)
printf("%02X", salt[i]);
printf("\n");
}
- if (EVP_CIPHER_key_length(cipher) > 0) {
+ if (EVP_CIPHER_get_key_length(cipher) > 0) {
printf("key=");
- for (i = 0; i < EVP_CIPHER_key_length(cipher); i++)
+ for (i = 0; i < EVP_CIPHER_get_key_length(cipher); i++)
printf("%02X", key[i]);
printf("\n");
}
- if (EVP_CIPHER_iv_length(cipher) > 0) {
+ if (EVP_CIPHER_get_iv_length(cipher) > 0) {
printf("iv =");
- for (i = 0; i < EVP_CIPHER_iv_length(cipher); i++)
+ for (i = 0; i < EVP_CIPHER_get_iv_length(cipher); i++)
printf("%02X", iv[i]);
printf("\n");
}
@@ -614,6 +632,8 @@ int enc_main(int argc, char **argv)
BIO_free_all(out);
BIO_free(benc);
BIO_free(b64);
+ EVP_MD_free(dgst);
+ EVP_CIPHER_free(cipher);
#ifdef ZLIB
BIO_free(bzl);
#endif
@@ -632,9 +652,9 @@ static void show_ciphers(const OBJ_NAME *name, void *arg)
/* 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)
+ if (cipher == NULL
+ || (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0
+ || EVP_CIPHER_get_mode(cipher) == EVP_CIPH_XTS_MODE)
return;
BIO_printf(dec->bio, "-%-25s", name->name);
diff --git a/apps/engine.c b/apps/engine.c
index 746cace354b2..1b0f64309c6f 100644
--- a/apps/engine.c
+++ b/apps/engine.c
@@ -1,13 +1,17 @@
/*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
*/
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/opensslconf.h>
+
#include "apps.h"
#include "progs.h"
#include <stdio.h>
@@ -19,27 +23,32 @@
#include <openssl/store.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST,
OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV
} OPTION_CHOICE;
const OPTIONS engine_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"},
- {OPT_HELP_STR, 1, '-',
- " engine... Engines to load\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"t", OPT_T, '-', "Check that specified engine is available"},
+ {"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_SECTION("Output"),
{"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\""},
+
+ OPT_PARAMETERS(),
+ {"engine", 0, 0, "ID of engine(s) to load"},
{NULL}
};
@@ -351,7 +360,7 @@ int engine_main(int argc, char **argv)
}
}
- /* Allow any trailing parameters as engine names. */
+ /* Any remaining arguments are engine names. */
argc = opt_num_rest();
argv = opt_rest();
for ( ; *argv; argv++) {
diff --git a/apps/errstr.c b/apps/errstr.c
index 3ef01f076a8c..782705a78a33 100644
--- a/apps/errstr.c
+++ b/apps/errstr.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -22,8 +22,12 @@ typedef enum OPTION_choice {
const OPTIONS errstr_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] errnum...\n"},
- {OPT_HELP_STR, 1, '-', " errnum Error number\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_PARAMETERS(),
+ {"errnum", 0, 0, "Error number(s) to decode"},
{NULL}
};
@@ -48,16 +52,19 @@ int errstr_main(int argc, char **argv)
}
}
+ /*
+ * 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);
+
+ /* All remaining arg are error code. */
ret = 0;
- for (argv = opt_rest(); *argv; argv++) {
+ for (argv = opt_rest(); *argv != NULL; 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);
}
diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c
new file mode 100644
index 000000000000..d0efdf7643bd
--- /dev/null
+++ b/apps/fipsinstall.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/provider.h>
+#include <openssl/params.h>
+#include <openssl/fips_names.h>
+#include <openssl/core_names.h>
+#include <openssl/self_test.h>
+#include <openssl/fipskey.h>
+#include "apps.h"
+#include "progs.h"
+
+#define BUFSIZE 4096
+
+/* Configuration file values */
+#define VERSION_KEY "version"
+#define VERSION_VAL "1"
+#define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"
+
+static OSSL_CALLBACK self_test_events;
+static char *self_test_corrupt_desc = NULL;
+static char *self_test_corrupt_type = NULL;
+static int self_test_log = 1;
+static int quiet = 0;
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_IN, OPT_OUT, OPT_MODULE,
+ OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY,
+ OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG,
+ OPT_NO_CONDITIONAL_ERRORS,
+ OPT_NO_SECURITY_CHECKS,
+ OPT_SELF_TEST_ONLOAD
+} OPTION_CHOICE;
+
+const OPTIONS fipsinstall_options[] = {
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"verify", OPT_VERIFY, '-',
+ "Verify a config file instead of generating one"},
+ {"module", OPT_MODULE, '<', "File name of the provider module"},
+ {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"},
+ {"section_name", OPT_SECTION_NAME, 's',
+ "FIPS Provider config section name (optional)"},
+ {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-',
+ "Disable the ability of the fips module to enter an error state if"
+ " any conditional self tests fail"},
+ {"no_security_checks", OPT_NO_SECURITY_CHECKS, '-',
+ "Disable the run-time FIPS security checks in the module"},
+ {"self_test_onload", OPT_SELF_TEST_ONLOAD, '-',
+ "Forces self tests to always run on module load"},
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input config file, used when verifying"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output config file, used when generating"},
+ {"mac_name", OPT_MAC_NAME, 's', "MAC name"},
+ {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
+ "See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
+ {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"},
+ {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"},
+ {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"},
+ {"config", OPT_CONFIG, '<', "The parent config to verify"},
+ {"quiet", OPT_QUIET, '-', "No messages, just exit status"},
+ {NULL}
+};
+
+static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in,
+ unsigned char *out, size_t *out_len)
+{
+ int ret = 0;
+ int i;
+ size_t outsz = *out_len;
+
+ if (!EVP_MAC_init(ctx, NULL, 0, NULL))
+ goto err;
+ if (EVP_MAC_CTX_get_mac_size(ctx) > outsz)
+ goto end;
+ while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) {
+ if (i < 0 || !EVP_MAC_update(ctx, tmp, i))
+ goto err;
+ }
+end:
+ if (!EVP_MAC_final(ctx, out, out_len, outsz))
+ goto err;
+ ret = 1;
+err:
+ return ret;
+}
+
+static int load_fips_prov_and_run_self_test(const char *prov_name)
+{
+ int ret = 0;
+ OSSL_PROVIDER *prov = NULL;
+
+ prov = OSSL_PROVIDER_load(NULL, prov_name);
+ if (prov == NULL) {
+ BIO_printf(bio_err, "Failed to load FIPS module\n");
+ goto end;
+ }
+ ret = 1;
+end:
+ OSSL_PROVIDER_unload(prov);
+ return ret;
+}
+
+static int print_mac(BIO *bio, const char *label, const unsigned char *mac,
+ size_t len)
+{
+ int ret;
+ char *hexstr = NULL;
+
+ hexstr = OPENSSL_buf2hexstr(mac, (long)len);
+ if (hexstr == NULL)
+ return 0;
+ ret = BIO_printf(bio, "%s = %s\n", label, hexstr);
+ OPENSSL_free(hexstr);
+ return ret;
+}
+
+static int write_config_header(BIO *out, const char *prov_name,
+ const char *section)
+{
+ return BIO_printf(out, "openssl_conf = openssl_init\n\n")
+ && BIO_printf(out, "[openssl_init]\n")
+ && BIO_printf(out, "providers = provider_section\n\n")
+ && BIO_printf(out, "[provider_section]\n")
+ && BIO_printf(out, "%s = %s\n\n", prov_name, section);
+}
+
+/*
+ * Outputs a fips related config file that contains entries for the fips
+ * module checksum, installation indicator checksum and the options
+ * conditional_errors and security_checks.
+ *
+ * Returns 1 if the config file is written otherwise it returns 0 on error.
+ */
+static int write_config_fips_section(BIO *out, const char *section,
+ unsigned char *module_mac,
+ size_t module_mac_len,
+ int conditional_errors,
+ int security_checks,
+ unsigned char *install_mac,
+ size_t install_mac_len)
+{
+ int ret = 0;
+
+ if (BIO_printf(out, "[%s]\n", section) <= 0
+ || BIO_printf(out, "activate = 1\n") <= 0
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
+ VERSION_VAL) <= 0
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,
+ conditional_errors ? "1" : "0") <= 0
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
+ security_checks ? "1" : "0") <= 0
+ || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
+ module_mac_len))
+ goto end;
+
+ if (install_mac != NULL && install_mac_len > 0) {
+ if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac,
+ install_mac_len)
+ || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
+ INSTALL_STATUS_VAL) <= 0)
+ goto end;
+ }
+ ret = 1;
+end:
+ return ret;
+}
+
+static CONF *generate_config_and_load(const char *prov_name,
+ const char *section,
+ unsigned char *module_mac,
+ size_t module_mac_len,
+ int conditional_errors,
+ int security_checks)
+{
+ BIO *mem_bio = NULL;
+ CONF *conf = NULL;
+
+ mem_bio = BIO_new(BIO_s_mem());
+ if (mem_bio == NULL)
+ return 0;
+ if (!write_config_header(mem_bio, prov_name, section)
+ || !write_config_fips_section(mem_bio, section,
+ module_mac, module_mac_len,
+ conditional_errors,
+ security_checks,
+ NULL, 0))
+ goto end;
+
+ conf = app_load_config_bio(mem_bio, NULL);
+ if (conf == NULL)
+ goto end;
+
+ if (CONF_modules_load(conf, NULL, 0) <= 0)
+ goto end;
+ BIO_free(mem_bio);
+ return conf;
+end:
+ NCONF_free(conf);
+ BIO_free(mem_bio);
+ return NULL;
+}
+
+static void free_config_and_unload(CONF *conf)
+{
+ if (conf != NULL) {
+ NCONF_free(conf);
+ CONF_modules_unload(1);
+ }
+}
+
+static int verify_module_load(const char *parent_config_file)
+{
+ return OSSL_LIB_CTX_load_config(NULL, parent_config_file);
+}
+
+/*
+ * Returns 1 if the config file entries match the passed in module_mac and
+ * install_mac values, otherwise it returns 0.
+ */
+static int verify_config(const char *infile, const char *section,
+ unsigned char *module_mac, size_t module_mac_len,
+ unsigned char *install_mac, size_t install_mac_len)
+{
+ int ret = 0;
+ char *s = NULL;
+ unsigned char *buf1 = NULL, *buf2 = NULL;
+ long len;
+ CONF *conf = NULL;
+
+ /* read in the existing values and check they match the saved values */
+ conf = app_load_config(infile);
+ if (conf == NULL)
+ goto end;
+
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_VERSION);
+ if (s == NULL || strcmp(s, VERSION_VAL) != 0) {
+ BIO_printf(bio_err, "version not found\n");
+ goto end;
+ }
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_MODULE_MAC);
+ if (s == NULL) {
+ BIO_printf(bio_err, "Module integrity MAC not found\n");
+ goto end;
+ }
+ buf1 = OPENSSL_hexstr2buf(s, &len);
+ if (buf1 == NULL
+ || (size_t)len != module_mac_len
+ || memcmp(module_mac, buf1, module_mac_len) != 0) {
+ BIO_printf(bio_err, "Module integrity mismatch\n");
+ goto end;
+ }
+ if (install_mac != NULL && install_mac_len > 0) {
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_STATUS);
+ if (s == NULL || strcmp(s, INSTALL_STATUS_VAL) != 0) {
+ BIO_printf(bio_err, "install status not found\n");
+ goto end;
+ }
+ s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_MAC);
+ if (s == NULL) {
+ BIO_printf(bio_err, "Install indicator MAC not found\n");
+ goto end;
+ }
+ buf2 = OPENSSL_hexstr2buf(s, &len);
+ if (buf2 == NULL
+ || (size_t)len != install_mac_len
+ || memcmp(install_mac, buf2, install_mac_len) != 0) {
+ BIO_printf(bio_err, "Install indicator status mismatch\n");
+ goto end;
+ }
+ }
+ ret = 1;
+end:
+ OPENSSL_free(buf1);
+ OPENSSL_free(buf2);
+ NCONF_free(conf);
+ return ret;
+}
+
+int fipsinstall_main(int argc, char **argv)
+{
+ int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, self_test_onload = 0;
+ int enable_conditional_errors = 1, enable_security_checks = 1;
+ const char *section_name = "fips_sect";
+ const char *mac_name = "HMAC";
+ const char *prov_name = "fips";
+ BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL;
+ char *in_fname = NULL, *out_fname = NULL, *prog;
+ char *module_fname = NULL, *parent_config = NULL, *module_path = NULL;
+ const char *tail;
+ EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL;
+ STACK_OF(OPENSSL_STRING) *opts = NULL;
+ OPTION_CHOICE o;
+ unsigned char *read_buffer = NULL;
+ unsigned char module_mac[EVP_MAX_MD_SIZE];
+ size_t module_mac_len = EVP_MAX_MD_SIZE;
+ unsigned char install_mac[EVP_MAX_MD_SIZE];
+ size_t install_mac_len = EVP_MAX_MD_SIZE;
+ EVP_MAC *mac = NULL;
+ CONF *conf = NULL;
+
+ if ((opts = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+
+ prog = opt_init(argc, argv, fipsinstall_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 cleanup;
+ case OPT_HELP:
+ opt_help(fipsinstall_options);
+ ret = 0;
+ goto end;
+ case OPT_IN:
+ in_fname = opt_arg();
+ break;
+ case OPT_OUT:
+ out_fname = opt_arg();
+ break;
+ case OPT_NO_CONDITIONAL_ERRORS:
+ enable_conditional_errors = 0;
+ break;
+ case OPT_NO_SECURITY_CHECKS:
+ enable_security_checks = 0;
+ break;
+ case OPT_QUIET:
+ quiet = 1;
+ /* FALLTHROUGH */
+ case OPT_NO_LOG:
+ self_test_log = 0;
+ break;
+ case OPT_CORRUPT_DESC:
+ self_test_corrupt_desc = opt_arg();
+ break;
+ case OPT_CORRUPT_TYPE:
+ self_test_corrupt_type = opt_arg();
+ break;
+ case OPT_PROV_NAME:
+ prov_name = opt_arg();
+ break;
+ case OPT_MODULE:
+ module_fname = opt_arg();
+ break;
+ case OPT_SECTION_NAME:
+ section_name = opt_arg();
+ break;
+ case OPT_MAC_NAME:
+ mac_name = opt_arg();
+ break;
+ case OPT_CONFIG:
+ parent_config = opt_arg();
+ break;
+ case OPT_MACOPT:
+ if (!sk_OPENSSL_STRING_push(opts, opt_arg()))
+ goto opthelp;
+ if (strncmp(opt_arg(), "hexkey:", 7) == 0)
+ gotkey = 1;
+ else if (strncmp(opt_arg(), "digest:", 7) == 0)
+ gotdigest = 1;
+ break;
+ case OPT_VERIFY:
+ verify = 1;
+ break;
+ case OPT_SELF_TEST_ONLOAD:
+ self_test_onload = 1;
+ break;
+ }
+ }
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0 || (verify && in_fname == NULL))
+ goto opthelp;
+
+ if (parent_config != NULL) {
+ /* Test that a parent config can load the module */
+ if (verify_module_load(parent_config)) {
+ ret = OSSL_PROVIDER_available(NULL, prov_name) ? 0 : 1;
+ if (!quiet)
+ BIO_printf(bio_err, "FIPS provider is %s\n",
+ ret == 0 ? "available" : " not available");
+ }
+ goto end;
+ }
+ if (module_fname == NULL)
+ goto opthelp;
+
+ tail = opt_path_end(module_fname);
+ if (tail != NULL) {
+ module_path = OPENSSL_strdup(module_fname);
+ if (module_path == NULL)
+ goto end;
+ module_path[tail - module_fname] = '\0';
+ if (!OSSL_PROVIDER_set_default_search_path(NULL, module_path))
+ goto end;
+ }
+
+ if (self_test_log
+ || self_test_corrupt_desc != NULL
+ || self_test_corrupt_type != NULL)
+ OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL);
+
+ /* Use the default FIPS HMAC digest and key if not specified. */
+ if (!gotdigest && !sk_OPENSSL_STRING_push(opts, "digest:SHA256"))
+ goto end;
+ if (!gotkey && !sk_OPENSSL_STRING_push(opts, "hexkey:" FIPS_KEY_STRING))
+ goto end;
+
+ module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
+ if (module_bio == NULL) {
+ BIO_printf(bio_err, "Failed to open module file\n");
+ goto end;
+ }
+
+ read_buffer = app_malloc(BUFSIZE, "I/O buffer");
+ if (read_buffer == NULL)
+ goto end;
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), mac_name, app_get0_propq());
+ if (mac == NULL) {
+ BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name);
+ goto end;
+ }
+
+ ctx = EVP_MAC_CTX_new(mac);
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "Unable to create MAC CTX for module check\n");
+ goto end;
+ }
+
+ if (opts != NULL) {
+ int ok = 1;
+ OSSL_PARAM *params =
+ app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac));
+
+ if (params == NULL)
+ goto end;
+
+ if (!EVP_MAC_CTX_set_params(ctx, params)) {
+ BIO_printf(bio_err, "MAC parameter error\n");
+ ERR_print_errors(bio_err);
+ ok = 0;
+ }
+ app_params_free(params);
+ if (!ok)
+ goto end;
+ }
+
+ ctx2 = EVP_MAC_CTX_dup(ctx);
+ if (ctx2 == NULL) {
+ BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n");
+ goto end;
+ }
+
+ if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))
+ goto end;
+
+ if (self_test_onload == 0) {
+ mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,
+ strlen(INSTALL_STATUS_VAL));
+ if (mem_bio == NULL) {
+ BIO_printf(bio_err, "Unable to create memory BIO\n");
+ goto end;
+ }
+ if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
+ goto end;
+ } else {
+ install_mac_len = 0;
+ }
+
+ if (verify) {
+ if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
+ install_mac, install_mac_len))
+ goto end;
+ if (!quiet)
+ BIO_printf(bio_err, "VERIFY PASSED\n");
+ } else {
+
+ conf = generate_config_and_load(prov_name, section_name, module_mac,
+ module_mac_len,
+ enable_conditional_errors,
+ enable_security_checks);
+ if (conf == NULL)
+ goto end;
+ if (!load_fips_prov_and_run_self_test(prov_name))
+ goto end;
+
+ fout =
+ out_fname == NULL ? dup_bio_out(FORMAT_TEXT)
+ : bio_open_default(out_fname, 'w', FORMAT_TEXT);
+ if (fout == NULL) {
+ BIO_printf(bio_err, "Failed to open file\n");
+ goto end;
+ }
+ if (!write_config_fips_section(fout, section_name,
+ module_mac, module_mac_len,
+ enable_conditional_errors,
+ enable_security_checks,
+ install_mac, install_mac_len))
+ goto end;
+ if (!quiet)
+ BIO_printf(bio_err, "INSTALL PASSED\n");
+ }
+
+ ret = 0;
+end:
+ if (ret == 1) {
+ if (!quiet)
+ BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL");
+ ERR_print_errors(bio_err);
+ }
+
+cleanup:
+ OPENSSL_free(module_path);
+ BIO_free(fout);
+ BIO_free(mem_bio);
+ BIO_free(module_bio);
+ sk_OPENSSL_STRING_free(opts);
+ EVP_MAC_free(mac);
+ EVP_MAC_CTX_free(ctx2);
+ EVP_MAC_CTX_free(ctx);
+ OPENSSL_free(read_buffer);
+ free_config_and_unload(conf);
+ return ret;
+}
+
+static int self_test_events(const OSSL_PARAM params[], void *arg)
+{
+ const OSSL_PARAM *p = NULL;
+ const char *phase = NULL, *type = NULL, *desc = NULL;
+ int ret = 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ phase = (const char *)p->data;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ desc = (const char *)p->data;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
+ if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ type = (const char *)p->data;
+
+ if (self_test_log) {
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
+ BIO_printf(bio_err, "%s : (%s) : ", desc, type);
+ else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
+ || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
+ BIO_printf(bio_err, "%s\n", phase);
+ }
+ /*
+ * The self test code will internally corrupt the KAT test result if an
+ * error is returned during the corrupt phase.
+ */
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
+ && (self_test_corrupt_desc != NULL
+ || self_test_corrupt_type != NULL)) {
+ if (self_test_corrupt_desc != NULL
+ && strcmp(self_test_corrupt_desc, desc) != 0)
+ goto end;
+ if (self_test_corrupt_type != NULL
+ && strcmp(self_test_corrupt_type, type) != 0)
+ goto end;
+ BIO_printf(bio_err, "%s ", phase);
+ goto err;
+ }
+end:
+ ret = 1;
+err:
+ return ret;
+}
diff --git a/apps/gendsa.c b/apps/gendsa.c
index ec57c92a9492..27feb793fed2 100644
--- a/apps/gendsa.c
+++ b/apps/gendsa.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
#include <string.h>
#include <sys/types.h>
@@ -22,22 +23,30 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER,
- OPT_R_ENUM
+ OPT_COMMON,
+ OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, OPT_VERBOSE,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS gendsa_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [args] dsaparam-file\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] dsaparam-file\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output the key to the specified file"},
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
OPT_R_OPTIONS,
+ OPT_PROV_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
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+
+ OPT_PARAMETERS(),
+ {"dsaparam-file", 0, 0, "File containing DSA parameters"},
{NULL}
};
@@ -45,13 +54,13 @@ int gendsa_main(int argc, char **argv)
{
ENGINE *e = NULL;
BIO *out = NULL, *in = NULL;
- DSA *dsa = NULL;
- const EVP_CIPHER *enc = NULL;
- char *dsaparams = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_CIPHER *enc = NULL;
+ char *dsaparams = NULL, *ciphername = NULL;
char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog;
OPTION_CHOICE o;
- int ret = 1, private = 0;
- const BIGNUM *p = NULL;
+ int ret = 1, private = 0, verbose = 0, nbits;
prog = opt_init(argc, argv, gendsa_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -78,55 +87,71 @@ int gendsa_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
- case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
goto end;
break;
+ case OPT_CIPHER:
+ ciphername = opt_unknown();
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
}
}
+
+ /* One argument, the params file. */
argc = opt_num_rest();
argv = opt_rest();
- private = 1;
-
if (argc != 1)
goto opthelp;
- dsaparams = *argv;
+ dsaparams = argv[0];
- if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
- BIO_printf(bio_err, "Error getting password\n");
+ if (!app_RAND_load())
goto end;
- }
- in = bio_open_default(dsaparams, 'r', FORMAT_PEM);
- if (in == NULL)
- goto end2;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto end;
+ }
+ private = 1;
- if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) {
- BIO_printf(bio_err, "unable to load DSA parameter file\n");
+ if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
+ BIO_printf(bio_err, "Error getting password\n");
goto end;
}
- BIO_free(in);
- in = NULL;
+
+ pkey = load_keyparams(dsaparams, FORMAT_UNDEF, 1, "DSA", "DSA parameters");
out = bio_open_owner(outfile, FORMAT_PEM, private);
if (out == NULL)
goto end2;
- DSA_get0_pqg(dsa, &p, NULL, NULL);
-
- if (BN_num_bits(p) > OPENSSL_DSA_MAX_MODULUS_BITS)
+ nbits = EVP_PKEY_get_bits(pkey);
+ if (nbits > 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, BN_num_bits(p));
+ OPENSSL_DSA_MAX_MODULUS_BITS, EVP_PKEY_get_bits(pkey));
- BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p));
- if (!DSA_generate_key(dsa))
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq());
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "unable to create PKEY context\n");
goto end;
+ }
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ if (EVP_PKEY_keygen_init(ctx) <= 0) {
+ BIO_printf(bio_err, "unable to set up for key generation\n");
+ goto end;
+ }
+ pkey = app_keygen(ctx, "DSA", nbits, verbose);
assert(private);
- if (!PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout))
+ if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) {
+ BIO_printf(bio_err, "unable to output generated key\n");
goto end;
+ }
ret = 0;
end:
if (ret != 0)
@@ -134,7 +159,9 @@ int gendsa_main(int argc, char **argv)
end2:
BIO_free(in);
BIO_free_all(out);
- DSA_free(dsa);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_CIPHER_free(enc);
release_engine(e);
OPENSSL_free(passout);
return ret;
diff --git a/apps/genpkey.c b/apps/genpkey.c
index 3fe87e853c57..d00754eeaca0 100644
--- a/apps/genpkey.c
+++ b/apps/genpkey.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -14,34 +14,44 @@
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
-#ifndef OPENSSL_NO_ENGINE
-# include <openssl/engine.h>
-#endif
-static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e);
+static int quiet;
+
+static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e,
+ OSSL_LIB_CTX *libctx, const char *propq);
static int genpkey_cb(EVP_PKEY_CTX *ctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE,
- OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER
+ OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER,
+ OPT_QUIET, OPT_CONFIG,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS genpkey_options[] = {
+ OPT_SECTION("General"),
{"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"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
{"paramfile", OPT_PARAMFILE, '<', "Parameters file"},
{"algorithm", OPT_ALGORITHM, 's', "The public key algorithm"},
+ {"quiet", OPT_QUIET, '-', "Do not output status while generating keys"},
{"pkeyopt", OPT_PKEYOPT, 's',
"Set the public key algorithm option as opt:value"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"},
+ {"pass", OPT_PASS, 's', "Output file pass phrase source"},
{"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
+
+ OPT_PROV_OPTIONS,
+
/* This is deliberately last. */
{OPT_HELP_STR, 1, 1,
"Order of options may be important! See the documentation.\n"},
@@ -50,17 +60,24 @@ const OPTIONS genpkey_options[] = {
int genpkey_main(int argc, char **argv)
{
+ CONF *conf = NULL;
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
- char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog;
- const EVP_CIPHER *cipher = NULL;
+ char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog, *p;
+ const char *ciphername = NULL, *paramfile = NULL, *algname = NULL;
+ EVP_CIPHER *cipher = NULL;
OPTION_CHOICE o;
int outformat = FORMAT_PEM, text = 0, ret = 1, rv, do_param = 0;
- int private = 0;
+ int private = 0, i;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ STACK_OF(OPENSSL_STRING) *keyopt = NULL;
prog = opt_init(argc, argv, genpkey_options);
+ keyopt = sk_OPENSSL_STRING_new_null();
+ if (keyopt == NULL)
+ goto end;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
@@ -88,56 +105,70 @@ int genpkey_main(int argc, char **argv)
case OPT_PARAMFILE:
if (do_param == 1)
goto opthelp;
- if (!init_keygen_file(&ctx, opt_arg(), e))
- goto end;
+ paramfile = opt_arg();
break;
case OPT_ALGORITHM:
- if (!init_gen_str(&ctx, opt_arg(), e, do_param))
- goto end;
+ algname = opt_arg();
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);
+ if (!sk_OPENSSL_STRING_push(keyopt, opt_arg()))
goto end;
- }
+ break;
+ case OPT_QUIET:
+ quiet = 1;
break;
case OPT_GENPARAM:
- if (ctx != NULL)
- goto opthelp;
do_param = 1;
break;
case OPT_TEXT:
text = 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);
+ ciphername = opt_unknown();
+ break;
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
goto end;
- }
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
- private = do_param ? 0 : 1;
-
+ /* Fetch cipher, etc. */
+ if (paramfile != NULL) {
+ if (!init_keygen_file(&ctx, paramfile, e, libctx, app_get0_propq()))
+ goto end;
+ }
+ if (algname != NULL) {
+ if (!init_gen_str(&ctx, algname, e, do_param, libctx, app_get0_propq()))
+ goto end;
+ }
if (ctx == NULL)
goto opthelp;
+ for (i = 0; i < sk_OPENSSL_STRING_num(keyopt); i++) {
+ p = sk_OPENSSL_STRING_value(keyopt, i);
+ if (pkey_ctrl_string(ctx, p) <= 0) {
+ BIO_printf(bio_err, "%s: Error setting %s parameter:\n", prog, p);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (ciphername != NULL)
+ if (!opt_cipher(ciphername, &cipher) || do_param == 1)
+ goto opthelp;
+
+ private = do_param ? 0 : 1;
+
if (!app_passwd(passarg, NULL, &pass, NULL)) {
BIO_puts(bio_err, "Error getting password\n");
goto end;
@@ -150,19 +181,8 @@ int genpkey_main(int argc, char **argv)
EVP_PKEY_CTX_set_cb(ctx, genpkey_cb);
EVP_PKEY_CTX_set_app_data(ctx, bio_err);
- if (do_param) {
- if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) {
- BIO_puts(bio_err, "Error generating parameters\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- } else {
- if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
- BIO_puts(bio_err, "Error generating key\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- }
+ pkey = do_param ? app_paramgen(ctx, algname)
+ : app_keygen(ctx, algname, 0, 0 /* not verbose */);
if (do_param) {
rv = PEM_write_bio_Parameters(out, pkey);
@@ -181,7 +201,6 @@ int genpkey_main(int argc, char **argv)
if (rv <= 0) {
BIO_puts(bio_err, "Error writing key\n");
- ERR_print_errors(bio_err);
ret = 1;
}
@@ -193,22 +212,27 @@ int genpkey_main(int argc, char **argv)
if (rv <= 0) {
BIO_puts(bio_err, "Error printing key\n");
- ERR_print_errors(bio_err);
ret = 1;
}
}
end:
+ sk_OPENSSL_STRING_free(keyopt);
+ if (ret != 0)
+ ERR_print_errors(bio_err);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
+ EVP_CIPHER_free(cipher);
BIO_free_all(out);
BIO_free(in);
release_engine(e);
OPENSSL_free(pass);
+ NCONF_free(conf);
return ret;
}
-static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e)
+static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
BIO *pbio;
EVP_PKEY *pkey = NULL;
@@ -219,20 +243,23 @@ static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e)
}
pbio = BIO_new_file(file, "r");
- if (!pbio) {
+ if (pbio == NULL) {
BIO_printf(bio_err, "Can't open parameter file %s\n", file);
return 0;
}
- pkey = PEM_read_bio_Parameters(pbio, NULL);
+ pkey = PEM_read_bio_Parameters_ex(pbio, NULL, libctx, propq);
BIO_free(pbio);
- if (!pkey) {
+ if (pkey == NULL) {
BIO_printf(bio_err, "Error reading parameter file %s\n", file);
return 0;
}
- ctx = EVP_PKEY_CTX_new(pkey, e);
+ if (e != NULL)
+ ctx = EVP_PKEY_CTX_new(pkey, e);
+ else
+ ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
if (ctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(ctx) <= 0)
@@ -251,11 +278,10 @@ static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e)
}
int init_gen_str(EVP_PKEY_CTX **pctx,
- const char *algname, ENGINE *e, int do_param)
+ const char *algname, ENGINE *e, int do_param,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_PKEY_CTX *ctx = NULL;
- const EVP_PKEY_ASN1_METHOD *ameth;
- ENGINE *tmpeng = NULL;
int pkey_id;
if (*pctx) {
@@ -263,27 +289,13 @@ int init_gen_str(EVP_PKEY_CTX **pctx,
return 0;
}
- ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);
-
-#ifndef OPENSSL_NO_ENGINE
- if (!ameth && e)
- ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1);
-#endif
-
- if (!ameth) {
- BIO_printf(bio_err, "Algorithm %s not found\n", algname);
- return 0;
- }
-
- ERR_clear_error();
+ pkey_id = get_legacy_pkey_id(libctx, algname, e);
+ if (pkey_id != NID_undef)
+ ctx = EVP_PKEY_CTX_new_id(pkey_id, e);
+ else
+ ctx = EVP_PKEY_CTX_new_from_name(libctx, algname, propq);
- EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(tmpeng);
-#endif
- ctx = EVP_PKEY_CTX_new_id(pkey_id, e);
-
- if (!ctx)
+ if (ctx == NULL)
goto err;
if (do_param) {
if (EVP_PKEY_paramgen_init(ctx) <= 0)
@@ -308,16 +320,22 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx)
{
char c = '*';
BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
- int p;
- p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
- if (p == 0)
+
+ if (quiet)
+ return 1;
+
+ switch (EVP_PKEY_CTX_get_keygen_info(ctx, 0)) {
+ case 0:
c = '.';
- if (p == 1)
+ break;
+ case 1:
c = '+';
- if (p == 2)
- c = '*';
- if (p == 3)
+ break;
+ case 3:
c = '\n';
+ break;
+ }
+
BIO_write(b, &c, 1);
(void)BIO_flush(b);
return 1;
diff --git a/apps/genrsa.c b/apps/genrsa.c
index e34a2f7ab9e8..4436b7fa1745 100644
--- a/apps/genrsa.c
+++ b/apps/genrsa.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
#include <string.h>
#include <sys/types.h>
@@ -26,52 +27,72 @@
#define DEFBITS 2048
#define DEFPRIMES 2
-static int genrsa_cb(int p, int n, BN_GENCB *cb);
+static int verbose = 0;
+
+static int genrsa_cb(EVP_PKEY_CTX *ctx);
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
+ OPT_COMMON,
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ OPT_3,
+#endif
+ OPT_F4, OPT_ENGINE,
+ OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE,
+ OPT_R_ENUM, OPT_PROV_ENUM, OPT_TRADITIONAL
} OPTION_CHOICE;
const OPTIONS genrsa_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] numbits\n"},
+
+ OPT_SECTION("General"),
{"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
+
+ OPT_SECTION("Input"),
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"3", OPT_3, '-', "(deprecated) Use 3 for the E value"},
+#endif
+ {"F4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
+ {"f4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output the key to specified file"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"primes", OPT_PRIMES, 'p', "Specify number of primes"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+ {"traditional", OPT_TRADITIONAL, '-',
+ "Use traditional format for private keys"},
+ {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"numbits", 0, 0, "Size of key in bits"},
{NULL}
};
int genrsa_main(int argc, char **argv)
{
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;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ 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;
+ char *prog, *hexe, *dece, *ciphername = NULL;
OPTION_CHOICE o;
+ int traditional = 0;
if (bn == NULL || cb == NULL)
goto end;
- BN_GENCB_set(cb, genrsa_cb, bio_err);
-
prog = opt_init(argc, argv, genrsa_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
@@ -84,9 +105,11 @@ opthelp:
ret = 0;
opt_help(genrsa_options);
goto end;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
case OPT_3:
- f4 = 3;
+ f4 = RSA_3;
break;
+#endif
case OPT_F4:
f4 = RSA_F4;
break;
@@ -100,19 +123,29 @@ opthelp:
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_PASSOUT:
passoutarg = opt_arg();
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto end;
+ ciphername = opt_unknown();
break;
case OPT_PRIMES:
- if (!opt_int(opt_arg(), &primes))
- goto end;
+ primes = opt_int_arg();
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
+ case OPT_TRADITIONAL:
+ traditional = 1;
break;
}
}
+
+ /* One optional argument, the bitsize. */
argc = opt_num_rest();
argv = opt_rest();
@@ -129,7 +162,14 @@ opthelp:
goto opthelp;
}
+ if (!app_RAND_load())
+ goto end;
+
private = 1;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto end;
+ }
if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
@@ -139,37 +179,65 @@ opthelp:
if (out == NULL)
goto end;
- 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)
+ if (!init_gen_str(&ctx, "RSA", eng, 0, app_get0_libctx(),
+ app_get0_propq()))
goto end;
- if (!BN_set_word(bn, f4)
- || !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb))
- goto end;
+ EVP_PKEY_CTX_set_cb(ctx, genrsa_cb);
+ EVP_PKEY_CTX_set_app_data(ctx, bio_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);
+ if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, num) <= 0) {
+ BIO_printf(bio_err, "Error setting RSA length\n");
+ goto end;
+ }
+ if (!BN_set_word(bn, f4)) {
+ BIO_printf(bio_err, "Error allocating RSA public exponent\n");
+ goto end;
+ }
+ if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bn) <= 0) {
+ BIO_printf(bio_err, "Error setting RSA public exponent\n");
+ goto end;
}
- 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))
+ if (EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) <= 0) {
+ BIO_printf(bio_err, "Error setting number of primes\n");
goto end;
+ }
+ pkey = app_keygen(ctx, "RSA", num, verbose);
+
+ if (verbose) {
+ BIGNUM *e = NULL;
+
+ /* Every RSA key has an 'e' */
+ EVP_PKEY_get_bn_param(pkey, "e", &e);
+ if (e == NULL) {
+ BIO_printf(bio_err, "Error cannot access RSA e\n");
+ goto end;
+ }
+ 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);
+ BN_free(e);
+ }
+ if (traditional) {
+ if (!PEM_write_bio_PrivateKey_traditional(out, pkey, enc, NULL, 0,
+ NULL, passout))
+ goto end;
+ } else {
+ if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout))
+ goto end;
+ }
ret = 0;
end:
BN_free(bn);
BN_GENCB_free(cb);
- RSA_free(rsa);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(enc);
BIO_free_all(out);
release_engine(eng);
OPENSSL_free(passout);
@@ -178,9 +246,14 @@ opthelp:
return ret;
}
-static int genrsa_cb(int p, int n, BN_GENCB *cb)
+static int genrsa_cb(EVP_PKEY_CTX *ctx)
{
char c = '*';
+ BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
+ int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+
+ if (!verbose)
+ return 1;
if (p == 0)
c = '.';
@@ -190,7 +263,7 @@ static int genrsa_cb(int p, int n, BN_GENCB *cb)
c = '*';
if (p == 3)
c = '\n';
- BIO_write(BN_GENCB_get_arg(cb), &c, 1);
- (void)BIO_flush(BN_GENCB_get_arg(cb));
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
return 1;
}
diff --git a/apps/include/__DECC_INCLUDE_EPILOGUE.H b/apps/include/__DECC_INCLUDE_EPILOGUE.H
new file mode 100644
index 000000000000..2ab493330675
--- /dev/null
+++ b/apps/include/__DECC_INCLUDE_EPILOGUE.H
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* restore state. Must correspond to the save in __decc_include_prologue.h */
+# pragma names restore
+#endif
diff --git a/apps/include/__DECC_INCLUDE_PROLOGUE.H b/apps/include/__DECC_INCLUDE_PROLOGUE.H
new file mode 100644
index 000000000000..8e95fa975488
--- /dev/null
+++ b/apps/include/__DECC_INCLUDE_PROLOGUE.H
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/*
+ * This file is only used by HP C/C++ on VMS, and is included automatically
+ * after each header file from this directory
+ */
+
+/*
+ * The C++ compiler doesn't understand these pragmas, even though it
+ * understands the corresponding command line qualifier.
+ */
+#ifndef __cplusplus
+/* save state */
+# pragma names save
+/* have the compiler shorten symbols larger than 31 chars to 23 chars
+ * followed by a 8 hex char CRC
+ */
+# pragma names as_is,shortened
+#endif
diff --git a/apps/include/app_libctx.h b/apps/include/app_libctx.h
new file mode 100644
index 000000000000..17c0afc713d2
--- /dev/null
+++ b/apps/include/app_libctx.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_LIBCTX_H
+# define OSSL_APPS_LIBCTX_H
+
+# include <openssl/types.h>
+
+OSSL_LIB_CTX *app_create_libctx(void);
+OSSL_LIB_CTX *app_get0_libctx(void);
+int app_set_propq(const char *arg);
+const char *app_get0_propq(void);
+
+#endif
diff --git a/apps/include/app_params.h b/apps/include/app_params.h
new file mode 100644
index 000000000000..79f8f58b3122
--- /dev/null
+++ b/apps/include/app_params.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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/core.h>
+
+int print_param_types(const char *thing, const OSSL_PARAM *pdefs, int indent);
+void print_param_value(const OSSL_PARAM *p, int indent);
+
diff --git a/apps/include/apps.h b/apps/include/apps.h
new file mode 100644
index 000000000000..baacd0025d68
--- /dev/null
+++ b/apps/include/apps.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_H
+# define OSSL_APPS_H
+
+# include "e_os.h" /* struct timeval for DTLS */
+# include "internal/nelem.h"
+# include "internal/sockets.h" /* for openssl_fdset() */
+# include "internal/cryptlib.h" /* ossl_assert() */
+# include <assert.h>
+
+# include <stdarg.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/types.h>
+# include <openssl/bio.h>
+# include <openssl/x509.h>
+# include <openssl/conf.h>
+# include <openssl/txt_db.h>
+# include <openssl/engine.h>
+# include <openssl/ocsp.h>
+# include <openssl/http.h>
+# include <signal.h>
+# include "apps_ui.h"
+# include "opt.h"
+# include "fmt.h"
+# include "platform.h"
+# include "engine_loader.h"
+# include "app_libctx.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);
+int app_RAND_write(void);
+int app_RAND_load(void);
+
+extern char *default_config_file; /* may be "" */
+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 *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);
+#define app_load_config(filename) app_load_config_internal(filename, 0)
+#define app_load_config_quiet(filename) app_load_config_internal(filename, 1)
+CONF *app_load_config_internal(const char *filename, int quiet);
+CONF *app_load_config_verbose(const char *filename, int verbose);
+int app_load_modules(const CONF *config);
+CONF *app_load_config_modules(const char *configfile);
+void unbuffer(FILE *fp);
+void wait_for_async(SSL *s);
+# if defined(OPENSSL_SYS_MSDOS)
+int has_stdin_waiting(void);
+# endif
+
+void corrupt_signature(const ASN1_STRING *signature);
+int set_cert_times(X509 *x, const char *startdate, const char *enddate,
+ int days);
+int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate);
+int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate,
+ long days, long hours, long secs);
+
+typedef struct args_st {
+ int size;
+ int argc;
+ char **argv;
+} ARGS;
+
+/* We need both wrap and the "real" function because libcrypto uses both. */
+int wrap_password_callback(char *buf, int bufsiz, int verify, void *cb_data);
+
+int chopup_args(ARGS *arg, char *buf);
+void dump_cert_text(BIO *out, X509 *x);
+void print_name(BIO *out, const char *title, const X509_NAME *nm);
+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_dateopt(unsigned long *dateopt, const char *arg);
+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);
+char *get_passwd(const char *pass, const char *desc);
+int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2);
+int add_oid_section(CONF *conf);
+X509_REQ *load_csr(const char *file, int format, const char *desc);
+X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc);
+#define load_cert(uri, format, desc) load_cert_pass(uri, format, 1, NULL, desc)
+X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
+ const char *desc);
+void cleanse(char *str);
+void clear_free(char *str);
+EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *desc);
+EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *desc);
+EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc);
+EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc,
+ int suppress_decode_errors);
+char *next_item(char *opt); /* in list separated by comma and/or space */
+int load_cert_certs(const char *uri,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ int exclude_http, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm);
+STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
+ const char *desc, X509_VERIFY_PARAM *vpm);
+X509_STORE *load_certstore(char *input, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm);
+int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
+ const char *pass, const char *desc);
+int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
+ const char *pass, const char *desc);
+int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls);
+int load_key_cert_crl(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ X509 **pcert, X509_CRL **pcrl);
+X509_STORE *setup_verify(const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore);
+__owur int ctx_set_verify_locations(SSL_CTX *ctx,
+ const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore);
+
+# 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_methods(const char *id, unsigned int methods, int debug);
+# define setup_engine(e, debug) setup_engine_methods(e, (unsigned int)-1, debug)
+void release_engine(ENGINE *e);
+int init_engine(ENGINE *e);
+int finish_engine(ENGINE *e);
+char *make_engine_uri(ENGINE *e, const char *key_id, const char *desc);
+
+int get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e);
+const EVP_MD *get_digest_from_engine(const char *name);
+const EVP_CIPHER *get_cipher_from_engine(const char *name);
+
+# ifndef OPENSSL_NO_OCSP
+OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host,
+ const char *port, const char *path,
+ const char *proxy, const char *no_proxy,
+ int use_ssl, STACK_OF(CONF_VALUE) *headers,
+ int req_timeout);
+# endif
+
+/* 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);
+
+# define DB_type 0
+# define DB_exp_date 1
+# define DB_rev_date 2
+# define DB_serial 3 /* index - unique */
+# define DB_file 4
+# define DB_name 5 /* index - unique when active and not
+ * disabled */
+# define DB_NUMBER 6
+
+# 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;
+} DB_ATTR;
+typedef struct ca_db_st {
+ DB_ATTR attributes;
+ TXT_DB *db;
+ char *dbfname;
+# ifndef OPENSSL_NO_POSIX_IO
+ struct stat dbst;
+# endif
+} CA_DB;
+
+void app_bail_out(char *fmt, ...);
+void *app_malloc(size_t sz, const char *what);
+
+/* load_serial, save_serial, and rotate_serial are also used for CRL numbers */
+BIGNUM *load_serial(const char *serialfile, int *exists, int create,
+ ASN1_INTEGER **retai);
+int save_serial(const char *serialfile, const char *suffix,
+ const BIGNUM *serial, ASN1_INTEGER **retai);
+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(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,
+ const char *old_suffix);
+void free_index(CA_DB *db);
+# define index_name_cmp_noconst(a, b) \
+ index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
+ (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
+int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
+int parse_yesno(const char *str, int def);
+
+X509_NAME *parse_name(const char *str, int chtype, int multirdn,
+ const char *desc);
+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 x509_ctrl_string(X509 *x, const char *value);
+int x509_req_ctrl_string(X509_REQ *x, const char *value);
+int init_gen_str(EVP_PKEY_CTX **pctx,
+ const char *algname, ENGINE *e, int do_param,
+ OSSL_LIB_CTX *libctx, const char *propq);
+int do_X509_sign(X509 *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx);
+int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts);
+int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *vfyopts);
+int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+
+extern char *psk_key;
+
+
+unsigned char *next_protos_parse(size_t *outlen, const char *in);
+
+void print_cert_checks(BIO *bio, X509 *x,
+ const char *checkhost,
+ const char *checkemail, const char *checkip);
+
+void store_setup_crl_download(X509_STORE *st);
+
+typedef struct app_http_tls_info_st {
+ const char *server;
+ const char *port;
+ int use_proxy;
+ long timeout;
+ SSL_CTX *ssl_ctx;
+} APP_HTTP_TLS_INFO;
+BIO *app_http_tls_cb(BIO *hbio, /* APP_HTTP_TLS_INFO */ void *arg,
+ int connect, int detail);
+void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info);
+# ifndef OPENSSL_NO_SOCK
+ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
+ const char *no_proxy, SSL_CTX *ssl_ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ long timeout, const char *expected_content_type,
+ const ASN1_ITEM *it);
+ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
+ const char *path, const char *proxy,
+ const char *no_proxy, SSL_CTX *ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type,
+ ASN1_VALUE *req, const ASN1_ITEM *req_it,
+ const char *expected_content_type,
+ long timeout, const ASN1_ITEM *rsp_it);
+# endif
+
+# define EXT_COPY_NONE 0
+# define EXT_COPY_ADD 1
+# define EXT_COPY_ALL 2
+
+# define NETSCAPE_CERT_HDR "certificate"
+
+# define APP_PASS_LEN 1024
+
+/*
+ * 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);
+int raw_write_stdout(const void *, int);
+
+# define TM_START 0
+# define TM_STOP 1
+double app_tminterval(int stop, int usertime);
+
+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;
+
+OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts,
+ const OSSL_PARAM *paramdefs);
+void app_params_free(OSSL_PARAM *params);
+int app_provider_load(OSSL_LIB_CTX *libctx, const char *provider_name);
+void app_providers_cleanup(void);
+
+EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose);
+EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg);
+
+#endif
diff --git a/apps/include/apps_ui.h b/apps/include/apps_ui.h
new file mode 100644
index 000000000000..6875b7c372d9
--- /dev/null
+++ b/apps/include/apps_ui.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_UI_H
+# define OSSL_APPS_UI_H
+
+
+# define PW_MIN_LENGTH 4
+typedef struct pw_cb_data {
+ const void *password;
+ const char *prompt_info;
+} PW_CB_DATA;
+
+int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data);
+
+int setup_ui_method(void);
+void destroy_ui_method(void);
+int set_base_ui_method(const UI_METHOD *ui_method);
+const UI_METHOD *get_ui_method(void);
+
+extern BIO *bio_err;
+
+#endif
diff --git a/apps/include/cmp_mock_srv.h b/apps/include/cmp_mock_srv.h
new file mode 100644
index 000000000000..6beba1473590
--- /dev/null
+++ b/apps/include/cmp_mock_srv.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Siemens AG 2018-2020
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_CMP_MOCK_SRV_H
+# define OSSL_APPS_CMP_MOCK_SRV_H
+
+# include <openssl/opensslconf.h>
+# ifndef OPENSSL_NO_CMP
+
+# include <openssl/cmp.h>
+
+OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx,
+ const char *propq);
+void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
+
+int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
+int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *chain);
+int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *caPubs);
+int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
+ int fail_info, const char *text);
+int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count);
+int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec);
+
+# endif /* !defined(OPENSSL_NO_CMP) */
+#endif /* !defined(OSSL_APPS_CMP_MOCK_SRV_H) */
diff --git a/apps/include/ec_common.h b/apps/include/ec_common.h
new file mode 100644
index 000000000000..f5711657a299
--- /dev/null
+++ b/apps/include/ec_common.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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_EC
+static const char *point_format_options[] = {
+ "uncompressed",
+ "compressed",
+ "hybrid",
+ NULL
+};
+
+static const char *asn1_encoding_options[] = {
+ "named_curve",
+ "explicit",
+ NULL
+};
+#endif
diff --git a/apps/include/engine_loader.h b/apps/include/engine_loader.h
new file mode 100644
index 000000000000..fa80fc96567c
--- /dev/null
+++ b/apps/include/engine_loader.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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_ENGINE_LOADER_H
+# define HEADER_ENGINE_LOADER_H
+
+# include <openssl/store.h>
+
+/* this is a private URI scheme */
+# define ENGINE_SCHEME "org.openssl.engine"
+# define ENGINE_SCHEME_COLON (ENGINE_SCHEME ":")
+
+int setup_engine_loader(void);
+void destroy_engine_loader(void);
+
+#endif
diff --git a/apps/include/fmt.h b/apps/include/fmt.h
new file mode 100644
index 000000000000..98dfed7dc0a2
--- /dev/null
+++ b/apps/include/fmt.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/*
+ * Options are shared by apps (see apps.h) and the test system
+ * (see test/testutil.h').
+ * In order to remove the dependency between apps and options, the following
+ * shared fields have been moved into this file.
+ */
+
+#ifndef OSSL_APPS_FMT_H
+#define OSSL_APPS_FMT_H
+
+/*
+ * 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_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 RSAPublicKey format */
+# define FORMAT_ASN1RSA 10 /* DER RSAPublicKey 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 */
+
+int FMT_istext(int format);
+
+#endif /* OSSL_APPS_FMT_H_ */
diff --git a/apps/include/function.h b/apps/include/function.h
new file mode 100644
index 000000000000..14e8dd388670
--- /dev/null
+++ b/apps/include/function.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_FUNCTION_H
+# define OSSL_APPS_FUNCTION_H
+
+# include <openssl/lhash.h>
+# include "opt.h"
+
+#define DEPRECATED_NO_ALTERNATIVE "unknown"
+
+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;
+ const char *deprecated_alternative;
+ const char *deprecated_version;
+} FUNCTION;
+
+DEFINE_LHASH_OF(FUNCTION);
+
+/* 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;
+
+void calculate_columns(FUNCTION *functions, DISPLAY_COLUMNS *dc);
+
+#endif
diff --git a/apps/include/http_server.h b/apps/include/http_server.h
new file mode 100644
index 000000000000..8c339660a65e
--- /dev/null
+++ b/apps/include/http_server.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_HTTP_SERVER_H
+# define OSSL_HTTP_SERVER_H
+
+# include "apps.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 HAVE_FORK
+# undef NO_FORK
+# else
+# define NO_FORK
+# endif
+
+# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \
+ && !defined(OPENSSL_NO_POSIX_IO)
+# define HTTP_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_DEBUG
+# undef LOG_INFO
+# undef LOG_WARNING
+# undef LOG_ERR
+# define LOG_DEBUG 7
+# define LOG_INFO 6
+# define LOG_WARNING 4
+# define LOG_ERR 3
+# endif
+
+/*-
+ * Log a message to syslog if multi-threaded HTTP_DAEMON, else to bio_err
+ * prog: the name of the current app
+ * level: the severity of the message, e.g., LOG_ERR
+ * fmt: message with potential extra parameters like with printf()
+ * returns nothing
+ */
+void log_message(const char *prog, int level, const char *fmt, ...);
+
+# ifndef OPENSSL_NO_SOCK
+/*-
+ * Initialize an HTTP server by setting up its listening BIO
+ * prog: the name of the current app
+ * port: the port to listen on
+ * returns a BIO for accepting requests, NULL on error
+ */
+BIO *http_server_init_bio(const char *prog, const char *port);
+
+/*-
+ * Accept an ASN.1-formatted HTTP request
+ * it: the expected request ASN.1 type
+ * preq: pointer to variable where to place the parsed request
+ * ppath: pointer to variable where to place the request path, or NULL
+ * pcbio: pointer to variable where to place the BIO for sending the response to
+ * acbio: the listening bio (typically as returned by http_server_init_bio())
+ * found_keep_alive: for returning flag if client requests persistent connection
+ * prog: the name of the current app, for diagnostics only
+ * port: the local port listening to, for diagnostics only
+ * accept_get: whether to accept GET requests (in addition to POST requests)
+ * timeout: connection timeout (in seconds), or 0 for none/infinite
+ * returns 0 in case caller should retry, then *preq == *ppath == *pcbio == NULL
+ * returns -1 on fatal error; also then holds *preq == *ppath == *pcbio == NULL
+ * returns 1 otherwise. In this case it is guaranteed that *pcbio != NULL while
+ * *ppath == NULL and *preq == NULL if and only if the request is invalid,
+ * On return value 1 the caller is responsible for sending an HTTP response,
+ * using http_server_send_asn1_resp() or http_server_send_status().
+ * The caller must free any non-NULL *preq, *ppath, and *pcbio pointers.
+ */
+int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
+ char **ppath, BIO **pcbio, BIO *acbio,
+ int *found_keep_alive,
+ const char *prog, const char *port,
+ int accept_get, int timeout);
+
+/*-
+ * Send an ASN.1-formatted HTTP response
+ * cbio: destination BIO (typically as returned by http_server_get_asn1_req())
+ * note: cbio should not do an encoding that changes the output length
+ * keep_alive: grant persistent connnection
+ * content_type: string identifying the type of the response
+ * it: the response ASN.1 type
+ * resp: the response to send
+ * returns 1 on success, 0 on failure
+ */
+int http_server_send_asn1_resp(BIO *cbio, int keep_alive,
+ const char *content_type,
+ const ASN1_ITEM *it, const ASN1_VALUE *resp);
+
+/*-
+ * Send a trivial HTTP response, typically to report an error or OK
+ * cbio: destination BIO (typically as returned by http_server_get_asn1_req())
+ * status: the status code to send
+ * reason: the corresponding human-readable string
+ * returns 1 on success, 0 on failure
+ */
+int http_server_send_status(BIO *cbio, int status, const char *reason);
+
+# endif
+
+# ifdef HTTP_DAEMON
+extern int multi;
+extern int acfd;
+
+void socket_timeout(int signum);
+void spawn_loop(const char *prog);
+# endif
+
+#endif
diff --git a/apps/include/names.h b/apps/include/names.h
new file mode 100644
index 000000000000..f4d6f6a9a333
--- /dev/null
+++ b/apps/include/names.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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/safestack.h>
+
+/* Standard comparing function for names */
+int name_cmp(const char * const *a, const char * const *b);
+/* collect_names is meant to be used with EVP_{type}_doall_names */
+void collect_names(const char *name, void *vdata);
+/* Sorts and prints a stack of names to |out| */
+void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names);
diff --git a/apps/apps.h b/apps/include/opt.h
index 3e8f50fda87b..4f83a0ed53c9 100644
--- a/apps/apps.h
+++ b/apps/include/opt.h
@@ -1,92 +1,20 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_OPT_H
+#define OSSL_APPS_OPT_H
-#ifndef OSSL_APPS_H
-# define OSSL_APPS_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/conf.h>
-# include <openssl/txt_db.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
+#include <sys/types.h>
+#include <openssl/e_os2.h>
+#include <openssl/types.h>
+#include <stdarg.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
-
-void corrupt_signature(const ASN1_STRING *signature);
-int set_cert_times(X509 *x, const char *startdate, const char *enddate,
- int days);
+#define OPT_COMMON OPT_ERR = -1, OPT_EOF = 0, OPT_HELP
/*
* Common verification options.
@@ -106,6 +34,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
OPT_V__LAST
# define OPT_V_OPTIONS \
+ OPT_SECTION("Validation"), \
{ "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \
{ "purpose", OPT_V_PURPOSE, 's', \
"certificate chain purpose"}, \
@@ -198,15 +127,16 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
OPT_X__LAST
# define OPT_X_OPTIONS \
+ OPT_SECTION("Extended certificate"), \
{ "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 " }, \
+ "format of Extended certificate (PEM/DER/P12); has no effect" }, \
{ "xkeyform", OPT_X_KEYFORM, 'F', \
- "format of Extended certificate's key (PEM or DER) PEM default"}
+ "format of Extended certificate's key (DER/PEM/P12); has no effect"}
# define OPT_X_CASES \
OPT_X__FIRST: case OPT_X__LAST: break; \
@@ -225,16 +155,18 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
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_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_CLIENTRENEG, \
+ 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
+ OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S_NO_ETM, OPT_S__LAST
# define OPT_S_OPTIONS \
+ OPT_SECTION("TLS/SSL"), \
{"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" }, \
@@ -248,6 +180,8 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
{"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \
{"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \
"Enable use of legacy renegotiation (dangerous)"}, \
+ {"client_renegotiation", OPT_S_CLIENTRENEG, '-', \
+ "Allow client-initiated renegotiation" }, \
{"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \
"Disable all renegotiation."}, \
{"legacy_server_connect", OPT_S_LEGACYCONN, '-', \
@@ -282,7 +216,9 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
{"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" }
+ "Disable TLSv1.3 middlebox compat mode" }, \
+ {"no_etm", OPT_S_NO_ETM, '-', \
+ "Disable Encrypt-then-Mac extension"}
# define OPT_S_CASES \
OPT_S__FIRST: case OPT_S__LAST: break; \
@@ -297,6 +233,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
case OPT_S_NOTICKET: \
case OPT_S_SERVERPREF: \
case OPT_S_LEGACYRENEG: \
+ case OPT_S_CLIENTRENEG: \
case OPT_S_LEGACYCONN: \
case OPT_S_ONRESUMP: \
case OPT_S_NOLEGACYCONN: \
@@ -315,7 +252,8 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
case OPT_S_MINPROTO: \
case OPT_S_MAXPROTO: \
case OPT_S_DEBUGBROKE: \
- case OPT_S_NO_MIDDLEBOX
+ case OPT_S_NO_MIDDLEBOX: \
+ case OPT_S_NO_ETM
#define IS_NO_PROT_FLAG(o) \
(o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \
@@ -328,7 +266,8 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST
# define OPT_R_OPTIONS \
- {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \
+ OPT_SECTION("Random state"), \
+ {"rand", OPT_R_RAND, 's', "Load the given file(s) into the random number generator"}, \
{"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"}
# define OPT_R_CASES \
@@ -336,10 +275,36 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
case OPT_R_RAND: case OPT_R_WRITERAND
/*
+ * Provider options.
+ */
+# define OPT_PROV_ENUM \
+ OPT_PROV__FIRST=1600, \
+ OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, OPT_PROV_PROPQUERY, \
+ OPT_PROV__LAST
+
+# define OPT_CONFIG_OPTION \
+ { "config", OPT_CONFIG, '<', "Load a configuration file (this may load modules)" }
+
+# define OPT_PROV_OPTIONS \
+ OPT_SECTION("Provider"), \
+ { "provider-path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path (must be before 'provider' argument if required)" }, \
+ { "provider", OPT_PROV_PROVIDER, 's', "Provider to load (can be specified multiple times)" }, \
+ { "propquery", OPT_PROV_PROPQUERY, 's', "Property query used when fetching algorithms" }
+
+# define OPT_PROV_CASES \
+ OPT_PROV__FIRST: case OPT_PROV__LAST: break; \
+ case OPT_PROV_PROVIDER: \
+ case OPT_PROV_PROVIDER_PATH: \
+ case OPT_PROV_PROPQUERY
+
+/*
* Option parsing.
*/
extern const char OPT_HELP_STR[];
extern const char OPT_MORE_STR[];
+extern const char OPT_SECTION_STR[];
+extern const char OPT_PARAM_STR[];
+
typedef struct options_st {
const char *name;
int retval;
@@ -352,6 +317,9 @@ typedef struct options_st {
int valtype;
const char *helpstr;
} OPTIONS;
+/* Special retval values: */
+#define OPT_PARAM 0 /* same as OPT_EOF usually defined in apps */
+#define OPT_DUP -2 /* marks duplicate occurrence of option in help output */
/*
* A string/int pairing; widely use for option value lookup, hence the
@@ -381,255 +349,52 @@ typedef struct string_int_pair_st {
OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \
OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK)
+/* Divide options into sections when displaying usage */
+#define OPT_SECTION(sec) { OPT_SECTION_STR, 1, '-', sec " options:\n" }
+#define OPT_PARAMETERS() { OPT_PARAM_STR, 1, '-', "Parameters:\n" }
+
+const char *opt_path_end(const char *filename);
+char *opt_init(int ac, char **av, const OPTIONS * o);
char *opt_progname(const char *argv0);
+char *opt_appname(const char *argv0);
char *opt_getprog(void);
-char *opt_init(int ac, char **av, const OPTIONS * o);
+void opt_help(const OPTIONS * list);
+
+void opt_begin(void);
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_arg(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);
+int opt_cipher(const char *name, EVP_CIPHER **cipherp);
+int opt_cipher_any(const char *name, EVP_CIPHER **cipherp);
+int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp);
+int opt_md(const char *name, EVP_MD **mdp);
+int opt_md_silent(const char *name, EVP_MD **mdp);
-typedef struct args_st {
- 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;
- const char *prompt_info;
-} PW_CB_DATA;
-
-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 chopup_args(ARGS *arg, char *buf);
-int dump_cert_text(BIO *out, X509 *x);
-void print_name(BIO *out, const char *title, X509_NAME *nm,
- unsigned long lflags);
-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(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);
-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(const char *file, int format, int maybe_stdin,
- const char *pass, ENGINE *e, const char *key_descrip);
-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(const char *engine, int debug);
-void release_engine(ENGINE *e);
-
-# ifndef OPENSSL_NO_OCSP
-OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
- const char *host, const char *path,
- const char *port, int use_ssl,
- STACK_OF(CONF_VALUE) *headers,
- int req_timeout);
-# endif
-
-/* 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);
-
-# define DB_type 0
-# define DB_exp_date 1
-# define DB_rev_date 2
-# define DB_serial 3 /* index - unique */
-# define DB_file 4
-# define DB_name 5 /* index - unique when active and not
- * disabled */
-# define DB_NUMBER 6
-
-# 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;
-} DB_ATTR;
-typedef struct ca_db_st {
- DB_ATTR attributes;
- TXT_DB *db;
- char *dbfname;
-# ifndef OPENSSL_NO_POSIX_IO
- struct stat dbst;
-# endif
-} CA_DB;
-
-void* app_malloc(int sz, const char *what);
-
-/* load_serial, save_serial, and rotate_serial are also used for CRL numbers */
-BIGNUM *load_serial(const char *serialfile, int *exists, int create,
- ASN1_INTEGER **retai);
-int save_serial(const char *serialfile, const char *suffix,
- const BIGNUM *serial, ASN1_INTEGER **retai);
-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(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,
- const char *old_suffix);
-void free_index(CA_DB *db);
-# define index_name_cmp_noconst(a, b) \
- index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
- (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
-int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
-int parse_yesno(const char *str, int def);
-
-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(EVP_PKEY_CTX **pctx,
- const char *algname, ENGINE *e, int do_param);
-int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts);
-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(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
- STACK_OF(OPENSSL_STRING) *sigopts);
-
-extern char *psk_key;
-
-
-unsigned char *next_protos_parse(size_t *outlen, const char *in);
-
-void print_cert_checks(BIO *bio, X509 *x,
- const char *checkhost,
- const char *checkemail, const char *checkip);
-
-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_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
-# define EXT_COPY_ALL 2
-
-# define NETSCAPE_CERT_HDR "certificate"
-
-# define APP_PASS_LEN 1024
-
-/*
- * 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 opt_int(const char *arg, int *result);
+int opt_int_arg(void);
+int opt_long(const char *arg, long *result);
+int opt_ulong(const char *arg, unsigned long *result);
+int opt_intmax(const char *arg, ossl_intmax_t *result);
+int opt_uintmax(const char *arg, ossl_uintmax_t *result);
-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);
-int raw_write_stdout(const void *, int);
+int opt_isdir(const char *name);
+int opt_format(const char *s, unsigned long flags, int *result);
+void print_format_error(int format, unsigned long flags);
+int opt_printf_stderr(const char *fmt, ...);
+int opt_string(const char *name, const char **options);
+int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result);
-# define TM_START 0
-# define TM_STOP 1
-double app_tminterval(int stop, int usertime);
+int opt_verify(int i, X509_VERIFY_PARAM *vpm);
+int opt_rand(int i);
+int opt_provider(int i);
+int opt_provider_option_given(void);
-void make_uppercase(char *string);
+char **opt_rest(void);
+int opt_num_rest(void);
-typedef struct verify_options_st {
- int depth;
- int quiet;
- int error;
- int return_error;
-} VERIFY_CB_ARGS;
+/* Returns non-zero if legacy paths are still available */
+int opt_legacy_okay(void);
-extern VERIFY_CB_ARGS verify_args;
-#endif
+#endif /* OSSL_APPS_OPT_H */
diff --git a/apps/include/platform.h b/apps/include/platform.h
new file mode 100644
index 000000000000..491559df3152
--- /dev/null
+++ b/apps/include/platform.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_PLATFORM_H
+# define OSSL_APPS_PLATFORM_H
+
+# include <openssl/e_os2.h>
+
+# if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+/*
+ * 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[]);
+# endif
+
+# ifdef _WIN32
+/*
+ * 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[]);
+# endif
+
+#endif
diff --git a/apps/s_apps.h b/apps/include/s_apps.h
index f94e659e71e3..d610df40be3f 100644
--- a/apps/s_apps.h
+++ b/apps/include/s_apps.h
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -10,11 +10,13 @@
#include <openssl/opensslconf.h>
#include <openssl/ssl.h>
+#include <openssl/srp.h>
#define PORT "4433"
#define PROTOCOL "tcp"
typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context);
+int report_server_accept(BIO *out, int asock, int with_address, int with_pid);
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);
@@ -32,9 +34,10 @@ 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);
+void do_ssl_shutdown(SSL *ssl);
-long 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, size_t len,
+ int argi, long argl, int ret, size_t *processed);
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,
@@ -69,9 +72,37 @@ 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,
+ const char *vfyCAfile, const char *vfyCAstore,
+ const char *chCApath, const char *chCAfile,
+ const char *chCAstore, 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);
+
+#ifndef OPENSSL_NO_SRP
+/* The client side SRP context that we pass to all SRP related callbacks */
+typedef struct srp_arg_st {
+ char *srppassin;
+ char *srplogin;
+ int msg; /* copy from c_msg */
+ int debug; /* copy from c_debug */
+ int amp; /* allow more groups */
+ int strength; /* minimal size for N */
+} SRP_ARG;
+
+int set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg,
+ int c_debug);
+void set_up_dummy_srp(SSL_CTX *ctx);
+
+/* The server side SRP context that we pass to all SRP related callbacks */
+typedef struct srpsrvparm_st {
+ char *login;
+ SRP_VBASE *vb;
+ SRP_user_pwd *user;
+} srpsrvparm;
+
+int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm,
+ char *srpuserseed, char *srp_verifier_file);
+void lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out);
+#endif /* OPENSSL_NO_SRP */
diff --git a/apps/include/vms_term_sock.h b/apps/include/vms_term_sock.h
new file mode 100644
index 000000000000..eae37b1af931
--- /dev/null
+++ b/apps/include/vms_term_sock.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016 VMS Software, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 OSSL_APPS_VMS_TERM_SOCK_H
+# define OSSL_APPS_VMS_TERM_SOCK_H
+
+/*
+** Terminal Socket Function Codes
+*/
+# define TERM_SOCK_CREATE 1
+# define TERM_SOCK_DELETE 2
+
+/*
+** Terminal Socket Status Codes
+*/
+# define TERM_SOCK_FAILURE 0
+# define TERM_SOCK_SUCCESS 1
+
+/*
+** Terminal Socket Prototype
+*/
+int TerminalSocket (int FunctionCode, int *ReturnSocket);
+
+#endif
diff --git a/apps/info.c b/apps/info.c
new file mode 100644
index 000000000000..c68603652f21
--- /dev/null
+++ b/apps/info.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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/crypto.h>
+#include "apps.h"
+#include "progs.h"
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_CONFIGDIR, OPT_ENGINESDIR, OPT_MODULESDIR, OPT_DSOEXT, OPT_DIRNAMESEP,
+ OPT_LISTSEP, OPT_SEEDS, OPT_CPUSETTINGS
+} OPTION_CHOICE;
+
+const OPTIONS info_options[] = {
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
+ {"configdir", OPT_CONFIGDIR, '-', "Default configuration file directory"},
+ {"enginesdir", OPT_ENGINESDIR, '-', "Default engine module directory"},
+ {"modulesdir", OPT_MODULESDIR, '-',
+ "Default module directory (other than engine modules)"},
+ {"dsoext", OPT_DSOEXT, '-', "Configured extension for modules"},
+ {"dirnamesep", OPT_DIRNAMESEP, '-', "Directory-filename separator"},
+ {"listsep", OPT_LISTSEP, '-', "List separator character"},
+ {"seeds", OPT_SEEDS, '-', "Seed sources"},
+ {"cpusettings", OPT_CPUSETTINGS, '-', "CPU settings info"},
+ {NULL}
+};
+
+int info_main(int argc, char **argv)
+{
+ int ret = 1, dirty = 0, type = 0;
+ char *prog;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, info_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ default:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(info_options);
+ ret = 0;
+ goto end;
+ case OPT_CONFIGDIR:
+ type = OPENSSL_INFO_CONFIG_DIR;
+ dirty++;
+ break;
+ case OPT_ENGINESDIR:
+ type = OPENSSL_INFO_ENGINES_DIR;
+ dirty++;
+ break;
+ case OPT_MODULESDIR:
+ type = OPENSSL_INFO_MODULES_DIR;
+ dirty++;
+ break;
+ case OPT_DSOEXT:
+ type = OPENSSL_INFO_DSO_EXTENSION;
+ dirty++;
+ break;
+ case OPT_DIRNAMESEP:
+ type = OPENSSL_INFO_DIR_FILENAME_SEPARATOR;
+ dirty++;
+ break;
+ case OPT_LISTSEP:
+ type = OPENSSL_INFO_LIST_SEPARATOR;
+ dirty++;
+ break;
+ case OPT_SEEDS:
+ type = OPENSSL_INFO_SEED_SOURCE;
+ dirty++;
+ break;
+ case OPT_CPUSETTINGS:
+ type = OPENSSL_INFO_CPU_SETTINGS;
+ dirty++;
+ break;
+ }
+ }
+ if (opt_num_rest() != 0)
+ goto opthelp;
+ if (dirty > 1) {
+ BIO_printf(bio_err, "%s: Only one item allowed\n", prog);
+ goto opthelp;
+ }
+ if (dirty == 0) {
+ BIO_printf(bio_err, "%s: No items chosen\n", prog);
+ goto opthelp;
+ }
+
+ BIO_printf(bio_out, "%s\n", OPENSSL_info(type));
+ ret = 0;
+ end:
+ return ret;
+}
diff --git a/apps/insta.ca.crt b/apps/insta.ca.crt
new file mode 100644
index 000000000000..6aea6d4f9794
--- /dev/null
+++ b/apps/insta.ca.crt
Binary files differ
diff --git a/apps/kdf.c b/apps/kdf.c
new file mode 100644
index 000000000000..89ee1f69c766
--- /dev/null
+++ b/apps/kdf.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/params.h>
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT,
+ OPT_CIPHER, OPT_DIGEST, OPT_MAC,
+ OPT_PROV_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS kdf_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] kdf_name\n"},
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"kdfopt", OPT_KDFOPT, 's', "KDF algorithm control parameters in n:v form"},
+ {"cipher", OPT_CIPHER, 's', "Cipher"},
+ {"digest", OPT_DIGEST, 's', "Digest"},
+ {"mac", OPT_MAC, 's', "MAC"},
+ {OPT_MORE_STR, 1, '-', "See 'Supported Controls' in the EVP_KDF_ docs\n"},
+ {"keylen", OPT_KEYLEN, 's', "The size of the output derived key"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
+ {"binary", OPT_BIN, '-',
+ "Output in binary format (default is hexadecimal)"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"kdf_name", 0, 0, "Name of the KDF algorithm"},
+ {NULL}
+};
+
+static char *alloc_kdf_algorithm_name(STACK_OF(OPENSSL_STRING) **optp,
+ const char *name, const char *arg)
+{
+ size_t len = strlen(name) + strlen(arg) + 2;
+ char *res;
+
+ if (*optp == NULL)
+ *optp = sk_OPENSSL_STRING_new_null();
+ if (*optp == NULL)
+ return NULL;
+
+ res = app_malloc(len, "algorithm name");
+ BIO_snprintf(res, len, "%s:%s", name, arg);
+ if (sk_OPENSSL_STRING_push(*optp, res))
+ return res;
+ OPENSSL_free(res);
+ return NULL;
+}
+
+int kdf_main(int argc, char **argv)
+{
+ int ret = 1, out_bin = 0;
+ OPTION_CHOICE o;
+ STACK_OF(OPENSSL_STRING) *opts = NULL;
+ char *prog, *hexout = NULL;
+ const char *outfile = NULL;
+ unsigned char *dkm_bytes = NULL;
+ size_t dkm_len = 0;
+ BIO *out = NULL;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *ctx = NULL;
+ char *digest = NULL, *cipher = NULL, *mac = NULL;
+
+ prog = opt_init(argc, argv, kdf_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ default:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto err;
+ case OPT_HELP:
+ opt_help(kdf_options);
+ ret = 0;
+ goto err;
+ case OPT_BIN:
+ out_bin = 1;
+ break;
+ case OPT_KEYLEN:
+ dkm_len = (size_t)atoi(opt_arg());
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_KDFOPT:
+ if (opts == NULL)
+ opts = sk_OPENSSL_STRING_new_null();
+ if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_CIPHER:
+ OPENSSL_free(cipher);
+ cipher = alloc_kdf_algorithm_name(&opts, "cipher", opt_arg());
+ if (cipher == NULL)
+ goto opthelp;
+ break;
+ case OPT_DIGEST:
+ OPENSSL_free(digest);
+ digest = alloc_kdf_algorithm_name(&opts, "digest", opt_arg());
+ if (digest == NULL)
+ goto opthelp;
+ break;
+ case OPT_MAC:
+ OPENSSL_free(mac);
+ mac = alloc_kdf_algorithm_name(&opts, "mac", opt_arg());
+ if (mac == NULL)
+ goto opthelp;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto err;
+ break;
+ }
+ }
+
+ /* One argument, the KDF name. */
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc != 1)
+ goto opthelp;
+
+ if ((kdf = EVP_KDF_fetch(app_get0_libctx(), argv[0],
+ app_get0_propq())) == NULL) {
+ BIO_printf(bio_err, "Invalid KDF name %s\n", argv[0]);
+ goto opthelp;
+ }
+
+ ctx = EVP_KDF_CTX_new(kdf);
+ if (ctx == NULL)
+ goto err;
+
+ if (opts != NULL) {
+ int ok = 1;
+ OSSL_PARAM *params =
+ app_params_new_from_opts(opts, EVP_KDF_settable_ctx_params(kdf));
+
+ if (params == NULL)
+ goto err;
+
+ if (!EVP_KDF_CTX_set_params(ctx, params)) {
+ BIO_printf(bio_err, "KDF parameter error\n");
+ ERR_print_errors(bio_err);
+ ok = 0;
+ }
+ app_params_free(params);
+ if (!ok)
+ goto err;
+ }
+
+ out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
+ if (out == NULL)
+ goto err;
+
+ if (dkm_len <= 0) {
+ BIO_printf(bio_err, "Invalid derived key length.\n");
+ goto err;
+ }
+ dkm_bytes = app_malloc(dkm_len, "out buffer");
+ if (dkm_bytes == NULL)
+ goto err;
+
+ if (!EVP_KDF_derive(ctx, dkm_bytes, dkm_len, NULL)) {
+ BIO_printf(bio_err, "EVP_KDF_derive failed\n");
+ goto err;
+ }
+
+ if (out_bin) {
+ BIO_write(out, dkm_bytes, dkm_len);
+ } else {
+ hexout = OPENSSL_buf2hexstr(dkm_bytes, dkm_len);
+ if (hexout == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto err;
+ }
+ BIO_printf(out, "%s\n\n", hexout);
+ }
+
+ ret = 0;
+err:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ OPENSSL_clear_free(dkm_bytes, dkm_len);
+ sk_OPENSSL_STRING_free(opts);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(ctx);
+ BIO_free(out);
+ OPENSSL_free(hexout);
+ OPENSSL_free(cipher);
+ OPENSSL_free(digest);
+ OPENSSL_free(mac);
+ return ret;
+}
diff --git a/apps/lib/app_libctx.c b/apps/lib/app_libctx.c
new file mode 100644
index 000000000000..4b9ec40e8527
--- /dev/null
+++ b/apps/lib/app_libctx.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 "app_libctx.h"
+#include "apps.h"
+
+static OSSL_LIB_CTX *app_libctx = NULL;
+static const char *app_propq = NULL;
+
+int app_set_propq(const char *arg)
+{
+ app_propq = arg;
+ return 1;
+}
+
+const char *app_get0_propq(void)
+{
+ return app_propq;
+}
+
+OSSL_LIB_CTX *app_get0_libctx(void)
+{
+ return app_libctx;
+}
+
+OSSL_LIB_CTX *app_create_libctx(void)
+{
+ /*
+ * Load the NULL provider into the default library context and create a
+ * library context which will then be used for any OPT_PROV options.
+ */
+ if (app_libctx == NULL) {
+ if (!app_provider_load(NULL, "null")) {
+ opt_printf_stderr( "Failed to create null provider\n");
+ return NULL;
+ }
+ app_libctx = OSSL_LIB_CTX_new();
+ }
+ if (app_libctx == NULL)
+ opt_printf_stderr("Failed to create library context\n");
+ return app_libctx;
+}
+
diff --git a/apps/lib/app_params.c b/apps/lib/app_params.c
new file mode 100644
index 000000000000..95e1298ee926
--- /dev/null
+++ b/apps/lib/app_params.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 "app_params.h"
+
+static int describe_param_type(char *buf, size_t bufsz, const OSSL_PARAM *param)
+{
+ const char *type_mod = "";
+ const char *type = NULL;
+ int show_type_number = 0;
+ int printed_len;
+
+ switch (param->data_type) {
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ type_mod = "unsigned ";
+ /* FALLTHRU */
+ case OSSL_PARAM_INTEGER:
+ type = "integer";
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ type_mod = "pointer to a ";
+ /* FALLTHRU */
+ case OSSL_PARAM_UTF8_STRING:
+ type = "UTF8 encoded string";
+ break;
+ case OSSL_PARAM_OCTET_PTR:
+ type_mod = "pointer to an ";
+ /* FALLTHRU */
+ case OSSL_PARAM_OCTET_STRING:
+ type = "octet string";
+ break;
+ default:
+ type = "unknown type";
+ show_type_number = 1;
+ break;
+ }
+
+ printed_len = BIO_snprintf(buf, bufsz, "%s: ", param->key);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ printed_len = BIO_snprintf(buf, bufsz, "%s%s", type_mod, type);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ if (show_type_number) {
+ printed_len = BIO_snprintf(buf, bufsz, " [%d]", param->data_type);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ }
+ if (param->data_size == 0)
+ printed_len = BIO_snprintf(buf, bufsz, " (arbitrary size)");
+ else
+ printed_len = BIO_snprintf(buf, bufsz, " (max %zu bytes large)",
+ param->data_size);
+ if (printed_len > 0) {
+ buf += printed_len;
+ bufsz -= printed_len;
+ }
+ *buf = '\0';
+ return 1;
+}
+
+int print_param_types(const char *thing, const OSSL_PARAM *pdefs, int indent)
+{
+ if (pdefs == NULL) {
+ return 1;
+ } else if (pdefs->key == NULL) {
+ /*
+ * An empty list? This shouldn't happen, but let's just make sure to
+ * say something if there's a badly written provider...
+ */
+ BIO_printf(bio_out, "%*sEmpty list of %s (!!!)\n", indent, "", thing);
+ } else {
+ BIO_printf(bio_out, "%*s%s:\n", indent, "", thing);
+ for (; pdefs->key != NULL; pdefs++) {
+ char buf[200]; /* This should be ample space */
+
+ describe_param_type(buf, sizeof(buf), pdefs);
+ BIO_printf(bio_out, "%*s %s\n", indent, "", buf);
+ }
+ }
+ return 1;
+}
+
+void print_param_value(const OSSL_PARAM *p, int indent)
+{
+ int64_t i;
+ uint64_t u;
+
+ printf("%*s%s: ", indent, "", p->key);
+ switch (p->data_type) {
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ if (OSSL_PARAM_get_uint64(p, &u))
+ BIO_printf(bio_out, "%llu\n", (unsigned long long int)u);
+ else
+ BIO_printf(bio_out, "error getting value\n");
+ break;
+ case OSSL_PARAM_INTEGER:
+ if (OSSL_PARAM_get_int64(p, &i))
+ BIO_printf(bio_out, "%lld\n", (long long int)i);
+ else
+ BIO_printf(bio_out, "error getting value\n");
+ break;
+ case OSSL_PARAM_UTF8_PTR:
+ BIO_printf(bio_out, "'%s'\n", *(char **)(p->data));
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ BIO_printf(bio_out, "'%s'\n", (char *)p->data);
+ break;
+ case OSSL_PARAM_OCTET_PTR:
+ case OSSL_PARAM_OCTET_STRING:
+ BIO_printf(bio_out, "<%zu bytes>\n", p->data_size);
+ break;
+ default:
+ BIO_printf(bio_out, "unknown type (%u) of %zu bytes\n",
+ p->data_type, p->data_size);
+ break;
+ }
+}
+
diff --git a/apps/lib/app_provider.c b/apps/lib/app_provider.c
new file mode 100644
index 000000000000..63f78ae07d80
--- /dev/null
+++ b/apps/lib/app_provider.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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>
+#include <openssl/err.h>
+#include <openssl/provider.h>
+#include <openssl/safestack.h>
+
+/* Non-zero if any of the provider options have been seen */
+static int provider_option_given = 0;
+
+DEFINE_STACK_OF(OSSL_PROVIDER)
+
+/*
+ * See comments in opt_verify for explanation of this.
+ */
+enum prov_range { OPT_PROV_ENUM };
+
+static STACK_OF(OSSL_PROVIDER) *app_providers = NULL;
+
+static void provider_free(OSSL_PROVIDER *prov)
+{
+ OSSL_PROVIDER_unload(prov);
+}
+
+int app_provider_load(OSSL_LIB_CTX *libctx, const char *provider_name)
+{
+ OSSL_PROVIDER *prov;
+
+ prov = OSSL_PROVIDER_load(libctx, provider_name);
+ if (prov == NULL) {
+ opt_printf_stderr("%s: unable to load provider %s\n"
+ "Hint: use -provider-path option or OPENSSL_MODULES environment variable.\n",
+ opt_getprog(), provider_name);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ if (app_providers == NULL)
+ app_providers = sk_OSSL_PROVIDER_new_null();
+ if (app_providers == NULL
+ || !sk_OSSL_PROVIDER_push(app_providers, prov)) {
+ app_providers_cleanup();
+ return 0;
+ }
+ return 1;
+}
+
+void app_providers_cleanup(void)
+{
+ sk_OSSL_PROVIDER_pop_free(app_providers, provider_free);
+ app_providers = NULL;
+}
+
+static int opt_provider_path(const char *path)
+{
+ if (path != NULL && *path == '\0')
+ path = NULL;
+ return OSSL_PROVIDER_set_default_search_path(app_get0_libctx(), path);
+}
+
+int opt_provider(int opt)
+{
+ const int given = provider_option_given;
+
+ provider_option_given = 1;
+ switch ((enum prov_range)opt) {
+ case OPT_PROV__FIRST:
+ case OPT_PROV__LAST:
+ return 1;
+ case OPT_PROV_PROVIDER:
+ return app_provider_load(app_get0_libctx(), opt_arg());
+ case OPT_PROV_PROVIDER_PATH:
+ return opt_provider_path(opt_arg());
+ case OPT_PROV_PROPQUERY:
+ return app_set_propq(opt_arg());
+ }
+ /* Should never get here but if we do, undo what we did earlier */
+ provider_option_given = given;
+ return 0;
+}
+
+int opt_provider_option_given(void)
+{
+ return provider_option_given;
+}
diff --git a/apps/app_rand.c b/apps/lib/app_rand.c
index 2b0bbde03423..713792ead40a 100644
--- a/apps/app_rand.c
+++ b/apps/lib/app_rand.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -14,6 +14,7 @@
#include <openssl/conf.h>
static char *save_rand_file;
+static STACK_OF(OPENSSL_STRING) *randfiles;
void app_RAND_load_conf(CONF *c, const char *section)
{
@@ -27,8 +28,14 @@ void app_RAND_load_conf(CONF *c, const char *section)
BIO_printf(bio_err, "Can't load %s into RNG\n", randfile);
ERR_print_errors(bio_err);
}
- if (save_rand_file == NULL)
+ if (save_rand_file == NULL) {
save_rand_file = OPENSSL_strdup(randfile);
+ /* If some internal memory errors have occurred */
+ if (save_rand_file == NULL) {
+ BIO_printf(bio_err, "Can't duplicate %s\n", randfile);
+ ERR_print_errors(bio_err);
+ }
+ }
}
static int loadfiles(char *name)
@@ -57,16 +64,34 @@ static int loadfiles(char *name)
return ret;
}
-void app_RAND_write(void)
+int app_RAND_load(void)
{
+ char *p;
+ int i, ret = 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(randfiles); i++) {
+ p = sk_OPENSSL_STRING_value(randfiles, i);
+ if (!loadfiles(p))
+ ret = 0;
+ }
+ sk_OPENSSL_STRING_free(randfiles);
+ return ret;
+}
+
+int app_RAND_write(void)
+{
+ int ret = 1;
+
if (save_rand_file == NULL)
- return;
+ return 1;
if (RAND_write_file(save_rand_file) == -1) {
BIO_printf(bio_err, "Cannot write random bytes:\n");
ERR_print_errors(bio_err);
+ ret = 0;
}
OPENSSL_free(save_rand_file);
save_rand_file = NULL;
+ return ret;
}
@@ -82,11 +107,17 @@ int opt_rand(int opt)
case OPT_R__LAST:
break;
case OPT_R_RAND:
- return loadfiles(opt_arg());
+ if (randfiles == NULL
+ && (randfiles = sk_OPENSSL_STRING_new_null()) == NULL)
+ return 0;
+ if (!sk_OPENSSL_STRING_push(randfiles, opt_arg()))
+ return 0;
break;
case OPT_R_WRITERAND:
OPENSSL_free(save_rand_file);
save_rand_file = OPENSSL_strdup(opt_arg());
+ if (save_rand_file == NULL)
+ return 0;
break;
}
return 1;
diff --git a/apps/lib/app_x509.c b/apps/lib/app_x509.c
new file mode 100644
index 000000000000..f2c22948f201
--- /dev/null
+++ b/apps/lib/app_x509.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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"
+
+/*
+ * X509_ctrl_str() is sorely lacking in libcrypto, but is still needed to
+ * allow the application to process verification options in a manner similar
+ * to signature or other options that pass through EVP_PKEY_CTX_ctrl_str(),
+ * for uniformity.
+ *
+ * As soon as more stuff is added, the code will need serious rework. For
+ * the moment, it only handles the FIPS 196 / SM2 distinguishing ID.
+ */
+#ifdef EVP_PKEY_CTRL_SET1_ID
+static ASN1_OCTET_STRING *mk_octet_string(void *value, size_t value_n)
+{
+ ASN1_OCTET_STRING *v = ASN1_OCTET_STRING_new();
+
+ if (v == NULL) {
+ BIO_printf(bio_err, "error: allocation failed\n");
+ } else if (!ASN1_OCTET_STRING_set(v, value, (int)value_n)) {
+ ASN1_OCTET_STRING_free(v);
+ v = NULL;
+ }
+ return v;
+}
+#endif
+
+static int x509_ctrl(void *object, int cmd, void *value, size_t value_n)
+{
+ switch (cmd) {
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ case EVP_PKEY_CTRL_SET1_ID:
+ {
+ ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
+
+ if (v == NULL) {
+ BIO_printf(bio_err,
+ "error: setting distinguishing ID in certificate failed\n");
+ return 0;
+ }
+
+ X509_set0_distinguishing_id(object, v);
+ return 1;
+ }
+#endif
+ default:
+ break;
+ }
+ return -2; /* typical EVP_PKEY return for "unsupported" */
+}
+
+static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n)
+{
+ switch (cmd) {
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ case EVP_PKEY_CTRL_SET1_ID:
+ {
+ ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
+
+ if (v == NULL) {
+ BIO_printf(bio_err,
+ "error: setting distinguishing ID in certificate signing request failed\n");
+ return 0;
+ }
+
+ X509_REQ_set0_distinguishing_id(object, v);
+ return 1;
+ }
+#endif
+ default:
+ break;
+ }
+ return -2; /* typical EVP_PKEY return for "unsupported" */
+}
+
+static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd,
+ void *value, size_t value_n),
+ void *object, const char *value)
+{
+ int rv = 0;
+ char *stmp, *vtmp = NULL;
+ size_t vtmp_len = 0;
+ int cmd = 0; /* Will get command values that make sense somehow */
+
+ stmp = OPENSSL_strdup(value);
+ if (stmp == NULL)
+ return -1;
+ vtmp = strchr(stmp, ':');
+ if (vtmp != NULL) {
+ *vtmp = 0;
+ vtmp++;
+ vtmp_len = strlen(vtmp);
+ }
+
+ if (strcmp(stmp, "distid") == 0) {
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
+#endif
+ } else if (strcmp(stmp, "hexdistid") == 0) {
+ if (vtmp != NULL) {
+ void *hexid;
+ long hexid_len = 0;
+
+ hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len);
+ OPENSSL_free(stmp);
+ stmp = vtmp = hexid;
+ vtmp_len = (size_t)hexid_len;
+ }
+#ifdef EVP_PKEY_CTRL_SET1_ID
+ cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
+#endif
+ }
+
+ rv = ctrl(object, cmd, vtmp, vtmp_len);
+
+ OPENSSL_free(stmp);
+ return rv;
+}
+
+int x509_ctrl_string(X509 *x, const char *value)
+{
+ return do_x509_ctrl_string(x509_ctrl, x, value);
+}
+
+int x509_req_ctrl_string(X509_REQ *x, const char *value)
+{
+ return do_x509_ctrl_string(x509_req_ctrl, x, value);
+}
diff --git a/apps/apps.c b/apps/lib/apps.c
index f2447fb0bef8..0d7a20b52afc 100644
--- a/apps/apps.c
+++ b/apps/lib/apps.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -15,6 +15,12 @@
# define _POSIX_C_SOURCE 2
#endif
+#ifndef OPENSSL_NO_ENGINE
+/* We need to use some deprecated APIs */
+# define OPENSSL_SUPPRESS_DEPRECATED
+# include <openssl/engine.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -28,18 +34,19 @@
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include <openssl/http.h>
#include <openssl/pem.h>
+#include <openssl/store.h>
#include <openssl/pkcs12.h>
#include <openssl/ui.h>
#include <openssl/safestack.h>
-#ifndef OPENSSL_NO_ENGINE
-# include <openssl/engine.h>
-#endif
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
#include <openssl/bn.h>
#include <openssl/ssl.h>
+#include <openssl/store.h>
+#include <openssl/core_names.h>
+#include "s_apps.h"
#include "apps.h"
#ifdef _WIN32
@@ -51,23 +58,35 @@ static int WIN32_rename(const char *from, const char *to);
# include <conio.h>
#endif
-#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
+#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) || defined(__BORLANDC__)
# define _kbhit kbhit
#endif
+static BIO *bio_open_default_(const char *filename, char mode, int format,
+ int quiet);
+
+#define PASS_SOURCE_SIZE_MAX 4
+
+DEFINE_STACK_OF(CONF)
+
typedef struct {
const char *name;
unsigned long flag;
unsigned long mask;
} 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);
+static
+int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
+ int suppress_decode_errors);
int app_init(long mesgwin);
@@ -86,7 +105,7 @@ int chopup_args(ARGS *arg, char *buf)
/* Skip whitespace. */
while (*p && isspace(_UC(*p)))
p++;
- if (!*p)
+ if (*p == '\0')
break;
/* The start of something good :-) */
@@ -126,18 +145,29 @@ int app_init(long mesgwin)
}
#endif
-int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile,
- const char *CApath, int noCAfile, int noCApath)
+int ctx_set_verify_locations(SSL_CTX *ctx,
+ const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore)
{
- if (CAfile == NULL && CApath == NULL) {
+ if (CAfile == NULL && CApath == NULL && CAstore == 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;
+ if (!noCAstore && SSL_CTX_set_default_verify_store(ctx) <= 0)
+ return 0;
return 1;
}
- return SSL_CTX_load_verify_locations(ctx, CAfile, CApath);
+
+ if (CAfile != NULL && !SSL_CTX_load_verify_file(ctx, CAfile))
+ return 0;
+ if (CApath != NULL && !SSL_CTX_load_verify_dir(ctx, CApath))
+ return 0;
+ if (CAstore != NULL && !SSL_CTX_load_verify_store(ctx, CAstore))
+ return 0;
+ return 1;
}
#ifndef OPENSSL_NO_CT
@@ -170,201 +200,42 @@ unsigned long get_nameopt(void)
return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
}
-int dump_cert_text(BIO *out, X509 *x)
-{
- 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");
-
- return 0;
-}
-
-static int ui_open(UI *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)
+void dump_cert_text(BIO *out, X509 *x)
{
- 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)) {
- case UIT_PROMPT:
- case UIT_VERIFY:
- {
- const char *password =
- ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
- if (password && password[0] != '\0') {
- UI_set_result(ui, uis, password);
- return 1;
- }
- }
- break;
- case UIT_NONE:
- case UIT_BOOLEAN:
- case UIT_INFO:
- case UIT_ERROR:
- break;
- }
- }
-
- reader = UI_method_get_reader(ui_fallback_method);
- if (reader)
- return reader(ui, uis);
- return 1;
+ print_name(out, "subject=", X509_get_subject_name(x));
+ print_name(out, "issuer=", X509_get_issuer_name(x));
}
-static int ui_write(UI *ui, UI_STRING *uis)
+int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata)
{
- 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)) {
- case UIT_PROMPT:
- case UIT_VERIFY:
- {
- const char *password =
- ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
- if (password && password[0] != '\0')
- return 1;
- }
- break;
- case UIT_NONE:
- case UIT_BOOLEAN:
- case UIT_INFO:
- case UIT_ERROR:
- break;
- }
- }
-
- writer = UI_method_get_writer(ui_fallback_method);
- if (writer)
- return writer(ui, uis);
- return 1;
+ return password_callback(buf, bufsiz, verify, (PW_CB_DATA *)userdata);
}
-static int ui_close(UI *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);
- UI_method_set_writer(ui_method, ui_write);
- UI_method_set_closer(ui_method, ui_close);
- return 0;
-}
-
-void destroy_ui_method(void)
-{
- if (ui_method) {
- UI_destroy_method(ui_method);
- ui_method = NULL;
- }
-}
-
-const UI_METHOD *get_ui_method(void)
-{
- return ui_method;
-}
+static char *app_get_pass(const char *arg, int keepbio);
-int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp)
+char *get_passwd(const char *pass, const char *desc)
{
- int res = 0;
- UI *ui = NULL;
- PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
-
- ui = UI_new_method(ui_method);
- if (ui) {
- int ok = 0;
- char *buff = NULL;
- int ui_flags = 0;
- const char *prompt_info = NULL;
- char *prompt;
- int pw_min_len = PW_MIN_LENGTH;
-
- if (cb_data != NULL && cb_data->prompt_info != NULL)
- prompt_info = cb_data->prompt_info;
- if (cb_data != NULL && cb_data->password != NULL
- && *(const char*)cb_data->password != '\0')
- pw_min_len = 1;
- else if (!verify)
- pw_min_len = 0;
- prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
- if (!prompt) {
- BIO_printf(bio_err, "Out of memory\n");
- UI_free(ui);
- return 0;
- }
-
- ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
- UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
+ char *result = NULL;
- /* 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_len, bufsiz - 1);
-
- if (ok >= 0 && verify) {
- buff = app_malloc(bufsiz, "password buffer");
- ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
- pw_min_len, bufsiz - 1, buf);
- }
- if (ok >= 0)
- do {
- ok = UI_process(ui);
- } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
-
- OPENSSL_clear_free(buff, (unsigned int)bufsiz);
-
- if (ok >= 0)
- res = strlen(buf);
- if (ok == -1) {
- BIO_printf(bio_err, "User interface error\n");
- ERR_print_errors(bio_err);
- OPENSSL_cleanse(buf, (unsigned int)bufsiz);
- res = 0;
- }
- if (ok == -2) {
- BIO_printf(bio_err, "aborted!\n");
- OPENSSL_cleanse(buf, (unsigned int)bufsiz);
- res = 0;
- }
- UI_free(ui);
- OPENSSL_free(prompt);
+ if (desc == NULL)
+ desc = "<unknown>";
+ if (!app_passwd(pass, NULL, &result, NULL))
+ BIO_printf(bio_err, "Error getting password for %s\n", desc);
+ if (pass != NULL && result == NULL) {
+ BIO_printf(bio_err,
+ "Trying plain input string (better precede with 'pass:')\n");
+ result = OPENSSL_strdup(pass);
+ if (result == NULL)
+ BIO_printf(bio_err, "Out of memory getting password for %s\n", desc);
}
- return res;
+ return result;
}
-static char *app_get_pass(const char *arg, int keepbio);
-
int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
{
- int same;
- if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2))
- same = 0;
- else
- same = 1;
+ int same = arg1 != NULL && arg2 != NULL && strcmp(arg1, arg2) == 0;
+
if (arg1 != NULL) {
*pass1 = app_get_pass(arg1, same);
if (*pass1 == NULL)
@@ -384,16 +255,17 @@ int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
static char *app_get_pass(const char *arg, int keepbio)
{
- char *tmp, tpass[APP_PASS_LEN];
static BIO *pwdbio = NULL;
+ char *tmp, tpass[APP_PASS_LEN];
int i;
+ /* PASS_SOURCE_SIZE_MAX = max number of chars before ':' in below strings */
if (strncmp(arg, "pass:", 5) == 0)
return OPENSSL_strdup(arg + 5);
if (strncmp(arg, "env:", 4) == 0) {
tmp = getenv(arg + 4);
if (tmp == NULL) {
- BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4);
+ BIO_printf(bio_err, "No environment variable %s\n", arg + 4);
return NULL;
}
return OPENSSL_strdup(tmp);
@@ -419,7 +291,7 @@ static char *app_get_pass(const char *arg, int keepbio)
i = atoi(arg + 3);
if (i >= 0)
pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
- if ((i < 0) || !pwdbio) {
+ if ((i < 0) || pwdbio == NULL) {
BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
return NULL;
}
@@ -427,16 +299,32 @@ static char *app_get_pass(const char *arg, int keepbio)
* Can't do BIO_gets on an fd BIO so add a buffering BIO
*/
btmp = BIO_new(BIO_f_buffer());
+ if (btmp == NULL) {
+ BIO_free_all(pwdbio);
+ pwdbio = NULL;
+ BIO_printf(bio_err, "Out of memory\n");
+ return NULL;
+ }
pwdbio = BIO_push(btmp, pwdbio);
#endif
} else if (strcmp(arg, "stdin") == 0) {
+ unbuffer(stdin);
pwdbio = dup_bio_in(FORMAT_TEXT);
- if (!pwdbio) {
+ if (pwdbio == NULL) {
BIO_printf(bio_err, "Can't open BIO for stdin\n");
return NULL;
}
} else {
- BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg);
+ /* argument syntax error; do not reveal too much about arg */
+ tmp = strchr(arg, ':');
+ if (tmp == NULL || tmp - arg > PASS_SOURCE_SIZE_MAX)
+ BIO_printf(bio_err,
+ "Invalid password argument, missing ':' within the first %d chars\n",
+ PASS_SOURCE_SIZE_MAX + 1);
+ else
+ BIO_printf(bio_err,
+ "Invalid password argument, starting with \"%.*s\"\n",
+ (int)(tmp - arg + 1), arg);
return NULL;
}
}
@@ -461,7 +349,7 @@ CONF *app_load_config_bio(BIO *in, const char *filename)
CONF *conf;
int i;
- conf = NCONF_new(NULL);
+ conf = NCONF_new_ex(app_get0_libctx(), NULL);
i = NCONF_load_bio(conf, in, &errorline);
if (i > 0)
return conf;
@@ -481,31 +369,31 @@ CONF *app_load_config_bio(BIO *in, const char *filename)
return NULL;
}
-CONF *app_load_config(const char *filename)
+CONF *app_load_config_verbose(const char *filename, int verbose)
{
- 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;
+ if (verbose) {
+ if (*filename == '\0')
+ BIO_printf(bio_err, "No configuration used\n");
+ else
+ BIO_printf(bio_err, "Using configuration from %s\n", filename);
+ }
+ return app_load_config_internal(filename, 0);
}
-CONF *app_load_config_quiet(const char *filename)
+CONF *app_load_config_internal(const char *filename, int quiet)
{
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);
+ if (filename == NULL || *filename != '\0') {
+ if ((in = bio_open_default_(filename, 'r', FORMAT_TEXT, quiet)) == NULL)
+ return NULL;
+ conf = app_load_config_bio(in, filename);
+ BIO_free(in);
+ } else {
+ /* Return empty config if filename is empty string. */
+ conf = NCONF_new_ex(app_get0_libctx(), NULL);
+ }
return conf;
}
@@ -554,439 +442,663 @@ int add_oid_section(CONF *conf)
return 1;
}
-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)
+CONF *app_load_config_modules(const char *configfile)
{
- const char *pass;
- char tpass[PEM_BUFSIZE];
- int len, ret = 0;
- PKCS12 *p12;
- p12 = d2i_PKCS12_bio(in, NULL);
- if (p12 == NULL) {
- 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)) {
- pass = "";
- } 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(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(bio_err,
- "Mac verify error (wrong password?) in PKCS12 file for %s\n",
- desc);
- goto die;
+ CONF *conf = NULL;
+
+ if (configfile != NULL) {
+ if ((conf = app_load_config_verbose(configfile, 1)) == NULL)
+ return NULL;
+ if (configfile != default_config_file && !app_load_modules(conf)) {
+ NCONF_free(conf);
+ conf = NULL;
}
- pass = tpass;
}
- ret = PKCS12_parse(p12, pass, pkey, cert, ca);
- die:
- PKCS12_free(p12);
- return ret;
+ return conf;
}
-#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
-static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl)
+#define IS_HTTP(uri) ((uri) != NULL \
+ && strncmp(uri, OSSL_HTTP_PREFIX, strlen(OSSL_HTTP_PREFIX)) == 0)
+#define IS_HTTPS(uri) ((uri) != NULL \
+ && strncmp(uri, OSSL_HTTPS_PREFIX, strlen(OSSL_HTTPS_PREFIX)) == 0)
+
+X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc)
{
- char *host = NULL, *port = NULL, *path = NULL;
- BIO *bio = NULL;
- OCSP_REQ_CTX *rctx = NULL;
- int use_ssl, rv = 0;
- if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
- goto err;
- if (use_ssl) {
- 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 == NULL)
- goto err;
- if (!OCSP_REQ_CTX_http(rctx, "GET", path))
- goto err;
- if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host))
- goto err;
- if (pcert) {
- do {
- rv = X509_http_nbio(rctx, pcert);
- } while (rv == -1);
- } else {
- do {
- rv = X509_CRL_http_nbio(rctx, pcrl);
- } while (rv == -1);
- }
+ X509 *cert = NULL;
- err:
- OPENSSL_free(host);
- OPENSSL_free(path);
- OPENSSL_free(port);
- BIO_free_all(bio);
- OCSP_REQ_CTX_free(rctx);
- if (rv != 1) {
- BIO_printf(bio_err, "Error loading %s from %s\n",
- pcert ? "certificate" : "CRL", url);
+ if (desc == NULL)
+ desc = "certificate";
+ if (IS_HTTPS(uri))
+ BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc);
+ else if (IS_HTTP(uri))
+ cert = X509_load_http(uri, NULL, NULL, 0 /* timeout */);
+ else
+ (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
+ NULL, NULL, NULL, &cert, NULL, NULL, NULL);
+ if (cert == NULL) {
+ BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
- return rv;
+ return cert;
}
-#endif
-X509 *load_cert(const char *file, int format, const char *cert_descrip)
+X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
+ const char *desc)
{
- X509 *x = NULL;
- BIO *cert;
-
- if (format == FORMAT_HTTP) {
-#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
- load_cert_crl_http(file, &x, NULL);
-#endif
- return x;
- }
-
- if (file == NULL) {
- unbuffer(stdin);
- cert = dup_bio_in(format);
- } else {
- cert = bio_open_default(file, 'r', format);
- }
- if (cert == NULL)
- goto end;
+ X509_CRL *crl = NULL;
- if (format == FORMAT_ASN1) {
- x = d2i_X509_bio(cert, NULL);
- } 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(cert, cert_descrip, NULL, NULL, NULL, &x, NULL))
- goto end;
- } else {
- BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip);
- goto end;
- }
- end:
- if (x == NULL) {
- BIO_printf(bio_err, "unable to load certificate\n");
+ if (desc == NULL)
+ desc = "CRL";
+ if (IS_HTTPS(uri))
+ BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc);
+ else if (IS_HTTP(uri))
+ crl = X509_CRL_load_http(uri, NULL, NULL, 0 /* timeout */);
+ else
+ (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
+ NULL, NULL, NULL, NULL, NULL, &crl, NULL);
+ if (crl == NULL) {
+ BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
- BIO_free(cert);
- return x;
+ return crl;
}
-X509_CRL *load_crl(const char *infile, int format)
+X509_REQ *load_csr(const char *file, int format, const char *desc)
{
- X509_CRL *x = NULL;
- BIO *in = NULL;
-
- if (format == FORMAT_HTTP) {
-#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
- load_cert_crl_http(infile, NULL, &x);
-#endif
- return x;
- }
+ X509_REQ *req = NULL;
+ BIO *in;
- in = bio_open_default(infile, 'r', format);
+ if (format == FORMAT_UNDEF)
+ format = FORMAT_PEM;
+ if (desc == NULL)
+ desc = "CSR";
+ in = bio_open_default(file, 'r', format);
if (in == NULL)
goto end;
- if (format == FORMAT_ASN1) {
- x = d2i_X509_CRL_bio(in, NULL);
- } else if (format == FORMAT_PEM) {
- x = 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 (x == NULL) {
- BIO_printf(bio_err, "unable to load CRL\n");
- ERR_print_errors(bio_err);
- goto end;
- }
+
+ if (format == FORMAT_ASN1)
+ req = d2i_X509_REQ_bio(in, NULL);
+ else if (format == FORMAT_PEM)
+ req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
+ else
+ print_format_error(format, OPT_FMT_PEMDER);
end:
+ if (req == NULL) {
+ BIO_printf(bio_err, "Unable to load %s\n", desc);
+ ERR_print_errors(bio_err);
+ }
BIO_free(in);
- return x;
+ return req;
+}
+
+void cleanse(char *str)
+{
+ if (str != NULL)
+ OPENSSL_cleanse(str, strlen(str));
}
-EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
- const char *pass, ENGINE *e, const char *key_descrip)
+void clear_free(char *str)
+{
+ if (str != NULL)
+ OPENSSL_clear_free(str, strlen(str));
+}
+
+EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
+ const char *pass, ENGINE *e, const char *desc)
{
- BIO *key = NULL;
EVP_PKEY *pkey = NULL;
- PW_CB_DATA cb_data;
+ char *allocated_uri = NULL;
- cb_data.password = pass;
- cb_data.prompt_info = file;
+ if (desc == NULL)
+ desc = "private key";
- if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
- BIO_printf(bio_err, "no keyfile specified\n");
- goto end;
- }
if (format == FORMAT_ENGINE) {
- 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 == 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
- }
- goto end;
- }
- if (file == NULL && maybe_stdin) {
- 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);
- } 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) {
- pkey = b2i_PrivateKey_bio(key);
- } else if (format == FORMAT_PVK) {
- pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
- &cb_data);
-#endif
- } else {
- BIO_printf(bio_err, "bad input format specified for key file\n");
- goto end;
- }
- end:
- BIO_free(key);
- if (pkey == NULL) {
- BIO_printf(bio_err, "unable to load %s\n", key_descrip);
- ERR_print_errors(bio_err);
+ uri = allocated_uri = make_engine_uri(e, uri, desc);
}
+ (void)load_key_certs_crls(uri, format, may_stdin, pass, desc,
+ &pkey, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ OPENSSL_free(allocated_uri);
return pkey;
}
-EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin,
- const char *pass, ENGINE *e, const char *key_descrip)
+EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *desc)
{
- BIO *key = NULL;
EVP_PKEY *pkey = NULL;
- PW_CB_DATA cb_data;
+ char *allocated_uri = NULL;
- cb_data.password = pass;
- cb_data.prompt_info = file;
+ if (desc == NULL)
+ desc = "public key";
- if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
- BIO_printf(bio_err, "no keyfile specified\n");
- goto end;
- }
if (format == FORMAT_ENGINE) {
- if (e == NULL) {
- BIO_printf(bio_err, "no engine specified\n");
- } else {
-#ifndef OPENSSL_NO_ENGINE
- pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data);
- 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
- }
- goto end;
- }
- if (file == NULL && maybe_stdin) {
- 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
- RSA *rsa;
- rsa = d2i_RSAPublicKey_bio(key, NULL);
- if (rsa) {
- pkey = EVP_PKEY_new();
- 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 != NULL) {
- pkey = EVP_PKEY_new();
- 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_PEM) {
- pkey = PEM_read_bio_PUBKEY(key, NULL,
- (pem_password_cb *)password_callback,
- &cb_data);
-#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
- } else if (format == FORMAT_MSBLOB) {
- pkey = b2i_PublicKey_bio(key);
-#endif
+ uri = allocated_uri = make_engine_uri(e, uri, desc);
}
- end:
- BIO_free(key);
- if (pkey == NULL)
- BIO_printf(bio_err, "unable to load %s\n", key_descrip);
+ (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
+ NULL, &pkey, NULL, NULL, NULL, NULL, NULL);
+
+ OPENSSL_free(allocated_uri);
return pkey;
}
-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)
+EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc,
+ int suppress_decode_errors)
{
- int i;
- BIO *bio;
- STACK_OF(X509_INFO) *xis = NULL;
- X509_INFO *xi;
- PW_CB_DATA cb_data;
- int rv = 0;
+ EVP_PKEY *params = NULL;
- cb_data.password = pass;
- cb_data.prompt_info = file;
+ if (desc == NULL)
+ desc = "key parameters";
- if (format != FORMAT_PEM) {
- BIO_printf(bio_err, "bad input format specified for %s\n", desc);
- return 0;
+ (void)load_key_certs_crls_suppress(uri, format, maybe_stdin, NULL, desc,
+ NULL, NULL, &params, NULL, NULL, NULL,
+ NULL, suppress_decode_errors);
+ if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
+ if (!suppress_decode_errors) {
+ BIO_printf(bio_err,
+ "Unable to load %s from %s (unexpected parameters type)\n",
+ desc, uri);
+ ERR_print_errors(bio_err);
+ }
+ EVP_PKEY_free(params);
+ params = NULL;
}
+ return params;
+}
- bio = bio_open_default(file, 'r', FORMAT_PEM);
- if (bio == NULL)
- return 0;
+EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
+ const char *keytype, const char *desc)
+{
+ return load_keyparams_suppress(uri, format, maybe_stdin, keytype, desc, 0);
+}
- xis = PEM_X509_INFO_read_bio(bio, NULL,
- (pem_password_cb *)password_callback,
- &cb_data);
+void app_bail_out(char *fmt, ...)
+{
+ va_list args;
- BIO_free(bio);
+ va_start(args, fmt);
+ BIO_vprintf(bio_err, fmt, args);
+ va_end(args);
+ ERR_print_errors(bio_err);
+ exit(EXIT_FAILURE);
+}
- if (pcerts != NULL && *pcerts == NULL) {
- *pcerts = sk_X509_new_null();
- if (*pcerts == NULL)
- goto end;
- }
+void *app_malloc(size_t sz, const char *what)
+{
+ void *vp = OPENSSL_malloc(sz);
- if (pcrls != NULL && *pcrls == NULL) {
- *pcrls = sk_X509_CRL_new_null();
- if (*pcrls == NULL)
- goto end;
- }
+ if (vp == NULL)
+ app_bail_out("%s: Could not allocate %zu bytes for %s\n",
+ opt_getprog(), sz, what);
+ return vp;
+}
- for (i = 0; i < sk_X509_INFO_num(xis); i++) {
- xi = sk_X509_INFO_value(xis, i);
- if (xi->x509 != NULL && pcerts != NULL) {
- if (!sk_X509_push(*pcerts, xi->x509))
- goto end;
- xi->x509 = NULL;
- }
- if (xi->crl != NULL && pcrls != NULL) {
- if (!sk_X509_CRL_push(*pcrls, xi->crl))
- goto end;
- xi->crl = NULL;
- }
+char *next_item(char *opt) /* in list separated by comma and/or space */
+{
+ /* advance to separator (comma or whitespace), if any */
+ while (*opt != ',' && !isspace(*opt) && *opt != '\0')
+ opt++;
+ if (*opt != '\0') {
+ /* terminate current item */
+ *opt++ = '\0';
+ /* skip over any whitespace after separator */
+ while (isspace(*opt))
+ opt++;
}
+ return *opt == '\0' ? NULL : opt; /* NULL indicates end of input */
+}
- if (pcerts != NULL && sk_X509_num(*pcerts) > 0)
- rv = 1;
+static void warn_cert_msg(const char *uri, X509 *cert, const char *msg)
+{
+ char *subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
- if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0)
- rv = 1;
+ BIO_printf(bio_err, "Warning: certificate from '%s' with subject '%s' %s\n",
+ uri, subj, msg);
+ OPENSSL_free(subj);
+}
- end:
+static void warn_cert(const char *uri, X509 *cert, int warn_EE,
+ X509_VERIFY_PARAM *vpm)
+{
+ uint32_t ex_flags = X509_get_extension_flags(cert);
+ int res = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
+ X509_get0_notAfter(cert));
+
+ if (res != 0)
+ warn_cert_msg(uri, cert, res > 0 ? "has expired" : "not yet valid");
+ if (warn_EE && (ex_flags & EXFLAG_V1) == 0 && (ex_flags & EXFLAG_CA) == 0)
+ warn_cert_msg(uri, cert, "is not a CA cert");
+}
+
+static void warn_certs(const char *uri, STACK_OF(X509) *certs, int warn_EE,
+ X509_VERIFY_PARAM *vpm)
+{
+ int i;
- sk_X509_INFO_pop_free(xis, X509_INFO_free);
+ for (i = 0; i < sk_X509_num(certs); i++)
+ warn_cert(uri, sk_X509_value(certs, i), warn_EE, vpm);
+}
- if (rv == 0) {
+int load_cert_certs(const char *uri,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ int exclude_http, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm)
+{
+ int ret = 0;
+ char *pass_string;
+
+ if (exclude_http && (OPENSSL_strncasecmp(uri, "http://", 7) == 0
+ || OPENSSL_strncasecmp(uri, "https://", 8) == 0)) {
+ BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc);
+ return ret;
+ }
+ pass_string = get_passwd(pass, desc);
+ ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc,
+ NULL, NULL, NULL,
+ pcert, pcerts, NULL, NULL);
+ clear_free(pass_string);
+
+ if (ret) {
+ if (pcert != NULL)
+ warn_cert(uri, *pcert, 0, vpm);
+ if (pcerts != NULL)
+ warn_certs(uri, *pcerts, 1, vpm);
+ } else {
if (pcerts != NULL) {
sk_X509_pop_free(*pcerts, X509_free);
*pcerts = NULL;
}
- if (pcrls != NULL) {
- sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
- *pcrls = NULL;
+ }
+ return ret;
+}
+
+STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
+ const char *desc, X509_VERIFY_PARAM *vpm)
+{
+ STACK_OF(X509) *certs = NULL;
+ STACK_OF(X509) *result = sk_X509_new_null();
+
+ if (files == NULL)
+ goto err;
+ if (result == NULL)
+ goto oom;
+
+ while (files != NULL) {
+ char *next = next_item(files);
+
+ if (!load_cert_certs(files, NULL, &certs, 0, pass, desc, vpm))
+ goto err;
+ if (!X509_add_certs(result, certs,
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
+ goto oom;
+ sk_X509_pop_free(certs, X509_free);
+ certs = NULL;
+ files = next;
+ }
+ return result;
+
+ oom:
+ BIO_printf(bio_err, "out of memory\n");
+ err:
+ sk_X509_pop_free(certs, X509_free);
+ sk_X509_pop_free(result, X509_free);
+ return NULL;
+}
+
+static X509_STORE *sk_X509_to_store(X509_STORE *store /* may be NULL */,
+ const STACK_OF(X509) *certs /* may NULL */)
+{
+ int i;
+
+ if (store == NULL)
+ store = X509_STORE_new();
+ if (store == NULL)
+ return NULL;
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ if (!X509_STORE_add_cert(store, sk_X509_value(certs, i))) {
+ X509_STORE_free(store);
+ return NULL;
}
- BIO_printf(bio_err, "unable to load %s\n",
- pcerts ? "certificates" : "CRLs");
- ERR_print_errors(bio_err);
}
- return rv;
+ return store;
}
-void* app_malloc(int sz, const char *what)
+/*
+ * Create cert store structure with certificates read from given file(s).
+ * Returns pointer to created X509_STORE on success, NULL on error.
+ */
+X509_STORE *load_certstore(char *input, const char *pass, const char *desc,
+ X509_VERIFY_PARAM *vpm)
{
- void *vp = OPENSSL_malloc(sz);
+ X509_STORE *store = NULL;
+ STACK_OF(X509) *certs = NULL;
- 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);
+ while (input != NULL) {
+ char *next = next_item(input);
+ int ok;
+
+ if (!load_cert_certs(input, NULL, &certs, 1, pass, desc, vpm)) {
+ X509_STORE_free(store);
+ return NULL;
+ }
+ ok = (store = sk_X509_to_store(store, certs)) != NULL;
+ sk_X509_pop_free(certs, X509_free);
+ certs = NULL;
+ if (!ok)
+ return NULL;
+ input = next;
}
- return vp;
+ return store;
}
/*
* Initialize or extend, if *certs != NULL, a certificate stack.
+ * The caller is responsible for freeing *certs if its value is left not NULL.
*/
-int load_certs(const char *file, STACK_OF(X509) **certs, int format,
+int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
const char *pass, const char *desc)
{
- return load_certs_crls(file, format, pass, desc, certs, NULL);
+ int was_NULL = *certs == NULL;
+ int ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin,
+ pass, desc, NULL, NULL,
+ NULL, NULL, certs, NULL, NULL);
+
+ if (!ret && was_NULL) {
+ sk_X509_pop_free(*certs, X509_free);
+ *certs = NULL;
+ }
+ return ret;
}
/*
* Initialize or extend, if *crls != NULL, a certificate stack.
+ * The caller is responsible for freeing *crls if its value is left not NULL.
*/
-int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
+int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
const char *pass, const char *desc)
{
- return load_certs_crls(file, format, pass, desc, NULL, crls);
+ int was_NULL = *crls == NULL;
+ int ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, crls);
+
+ if (!ret && was_NULL) {
+ sk_X509_CRL_pop_free(*crls, X509_CRL_free);
+ *crls = NULL;
+ }
+ return ret;
+}
+
+static const char *format2string(int format)
+{
+ switch(format) {
+ case FORMAT_PEM:
+ return "PEM";
+ case FORMAT_ASN1:
+ return "DER";
+ }
+ return NULL;
+}
+
+/* Set type expectation, but clear it if objects of different types expected. */
+#define SET_EXPECT(expect, val) ((expect) = (expect) < 0 ? (val) : ((expect) == (val) ? (val) : 0))
+/*
+ * Load those types of credentials for which the result pointer is not NULL.
+ * Reads from stdio if uri is NULL and maybe_stdin is nonzero.
+ * For non-NULL ppkey, pcert, and pcrl the first suitable value found is loaded.
+ * If pcerts is non-NULL and *pcerts == NULL then a new cert list is allocated.
+ * If pcerts is non-NULL then all available certificates are appended to *pcerts
+ * except any certificate assigned to *pcert.
+ * If pcrls is non-NULL and *pcrls == NULL then a new list of CRLs is allocated.
+ * If pcrls is non-NULL then all available CRLs are appended to *pcerts
+ * except any CRL assigned to *pcrl.
+ * In any case (also on error) the caller is responsible for freeing all members
+ * of *pcerts and *pcrls (as far as they are not NULL).
+ */
+static
+int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
+ int suppress_decode_errors)
+{
+ PW_CB_DATA uidata;
+ OSSL_STORE_CTX *ctx = NULL;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ const char *propq = app_get0_propq();
+ int ncerts = 0;
+ int ncrls = 0;
+ const char *failed =
+ ppkey != NULL ? "key" : ppubkey != NULL ? "public key" :
+ pparams != NULL ? "params" : pcert != NULL ? "cert" :
+ pcrl != NULL ? "CRL" : pcerts != NULL ? "certs" :
+ pcrls != NULL ? "CRLs" : NULL;
+ int cnt_expectations = 0;
+ int expect = -1;
+ const char *input_type;
+ OSSL_PARAM itp[2];
+ const OSSL_PARAM *params = NULL;
+
+ if (ppkey != NULL) {
+ *ppkey = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_PKEY);
+ }
+ if (ppubkey != NULL) {
+ *ppubkey = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_PUBKEY);
+ }
+ if (pparams != NULL) {
+ *pparams = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_PARAMS);
+ }
+ if (pcert != NULL) {
+ *pcert = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CERT);
+ }
+ if (pcerts != NULL) {
+ if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) {
+ BIO_printf(bio_err, "Out of memory loading");
+ goto end;
+ }
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CERT);
+ }
+ if (pcrl != NULL) {
+ *pcrl = NULL;
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CRL);
+ }
+ if (pcrls != NULL) {
+ if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) {
+ BIO_printf(bio_err, "Out of memory loading");
+ goto end;
+ }
+ cnt_expectations++;
+ SET_EXPECT(expect, OSSL_STORE_INFO_CRL);
+ }
+ if (cnt_expectations == 0) {
+ BIO_printf(bio_err, "Internal error: nothing to load from %s\n",
+ uri != NULL ? uri : "<stdin>");
+ return 0;
+ }
+
+ uidata.password = pass;
+ uidata.prompt_info = uri;
+
+ if ((input_type = format2string(format)) != NULL) {
+ itp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE,
+ (char *)input_type, 0);
+ itp[1] = OSSL_PARAM_construct_end();
+ params = itp;
+ }
+
+ if (uri == NULL) {
+ BIO *bio;
+
+ if (!maybe_stdin) {
+ BIO_printf(bio_err, "No filename or uri specified for loading");
+ goto end;
+ }
+ uri = "<stdin>";
+ unbuffer(stdin);
+ bio = BIO_new_fp(stdin, 0);
+ if (bio != NULL) {
+ ctx = OSSL_STORE_attach(bio, "file", libctx, propq,
+ get_ui_method(), &uidata, params,
+ NULL, NULL);
+ BIO_free(bio);
+ }
+ } else {
+ ctx = OSSL_STORE_open_ex(uri, libctx, propq, get_ui_method(), &uidata,
+ params, NULL, NULL);
+ }
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "Could not open file or uri for loading");
+ goto end;
+ }
+ if (expect > 0 && !OSSL_STORE_expect(ctx, expect))
+ goto end;
+
+ failed = NULL;
+ while (cnt_expectations > 0 && !OSSL_STORE_eof(ctx)) {
+ OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
+ int type, ok = 1;
+
+ /*
+ * This can happen (for example) if we attempt to load a file with
+ * multiple different types of things in it - but the thing we just
+ * tried to load wasn't one of the ones we wanted, e.g. if we're trying
+ * to load a certificate but the file has both the private key and the
+ * certificate in it. We just retry until eof.
+ */
+ if (info == NULL) {
+ continue;
+ }
+
+ type = OSSL_STORE_INFO_get_type(info);
+ switch (type) {
+ case OSSL_STORE_INFO_PKEY:
+ if (ppkey != NULL && *ppkey == NULL) {
+ ok = (*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL;
+ cnt_expectations -= ok;
+ }
+ /*
+ * An EVP_PKEY with private parts also holds the public parts,
+ * so if the caller asked for a public key, and we got a private
+ * key, we can still pass it back.
+ */
+ if (ok && ppubkey != NULL && *ppubkey == NULL) {
+ ok = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL);
+ cnt_expectations -= ok;
+ }
+ break;
+ case OSSL_STORE_INFO_PUBKEY:
+ if (ppubkey != NULL && *ppubkey == NULL) {
+ ok = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL);
+ cnt_expectations -= ok;
+ }
+ break;
+ case OSSL_STORE_INFO_PARAMS:
+ if (pparams != NULL && *pparams == NULL) {
+ ok = ((*pparams = OSSL_STORE_INFO_get1_PARAMS(info)) != NULL);
+ cnt_expectations -= ok;
+ }
+ break;
+ case OSSL_STORE_INFO_CERT:
+ if (pcert != NULL && *pcert == NULL) {
+ ok = (*pcert = OSSL_STORE_INFO_get1_CERT(info)) != NULL;
+ cnt_expectations -= ok;
+ }
+ else if (pcerts != NULL)
+ ok = X509_add_cert(*pcerts,
+ OSSL_STORE_INFO_get1_CERT(info),
+ X509_ADD_FLAG_DEFAULT);
+ ncerts += ok;
+ break;
+ case OSSL_STORE_INFO_CRL:
+ if (pcrl != NULL && *pcrl == NULL) {
+ ok = (*pcrl = OSSL_STORE_INFO_get1_CRL(info)) != NULL;
+ cnt_expectations -= ok;
+ }
+ else if (pcrls != NULL)
+ ok = sk_X509_CRL_push(*pcrls, OSSL_STORE_INFO_get1_CRL(info));
+ ncrls += ok;
+ break;
+ default:
+ /* skip any other type */
+ break;
+ }
+ OSSL_STORE_INFO_free(info);
+ if (!ok) {
+ failed = info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
+ BIO_printf(bio_err, "Error reading");
+ break;
+ }
+ }
+
+ end:
+ OSSL_STORE_close(ctx);
+ if (failed == NULL) {
+ int any = 0;
+
+ if ((ppkey != NULL && *ppkey == NULL)
+ || (ppubkey != NULL && *ppubkey == NULL)) {
+ failed = "key";
+ } else if (pparams != NULL && *pparams == NULL) {
+ failed = "params";
+ } else if ((pcert != NULL || pcerts != NULL) && ncerts == 0) {
+ if (pcert == NULL)
+ any = 1;
+ failed = "cert";
+ } else if ((pcrl != NULL || pcrls != NULL) && ncrls == 0) {
+ if (pcrl == NULL)
+ any = 1;
+ failed = "CRL";
+ }
+ if (!suppress_decode_errors) {
+ if (failed != NULL)
+ BIO_printf(bio_err, "Could not read");
+ if (any)
+ BIO_printf(bio_err, " any");
+ }
+ }
+ if (!suppress_decode_errors && failed != NULL) {
+ if (desc != NULL && strstr(desc, failed) != NULL) {
+ BIO_printf(bio_err, " %s", desc);
+ } else {
+ BIO_printf(bio_err, " %s", failed);
+ if (desc != NULL)
+ BIO_printf(bio_err, " of %s", desc);
+ }
+ if (uri != NULL)
+ BIO_printf(bio_err, " from %s", uri);
+ BIO_printf(bio_err, "\n");
+ ERR_print_errors(bio_err);
+ }
+ if (suppress_decode_errors || failed == NULL)
+ /* clear any spurious errors */
+ ERR_clear_error();
+ return failed == NULL;
+}
+
+int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
+ const char *pass, const char *desc,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
+ X509 **pcert, STACK_OF(X509) **pcerts,
+ X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
+{
+ return load_key_certs_crls_suppress(uri, format, maybe_stdin, pass, desc,
+ ppkey, ppubkey, pparams, pcert, pcerts,
+ pcrl, pcrls, 0);
}
#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
@@ -1069,13 +1181,24 @@ int set_name_ex(unsigned long *flags, const char *arg)
return 1;
}
+int set_dateopt(unsigned long *dateopt, const char *arg)
+{
+ if (OPENSSL_strcasecmp(arg, "rfc_822") == 0)
+ *dateopt = ASN1_DTFLGS_RFC822;
+ else if (OPENSSL_strcasecmp(arg, "iso_8601") == 0)
+ *dateopt = ASN1_DTFLGS_ISO8601;
+ else
+ return 0;
+ return 1;
+}
+
int set_ext_copy(int *copy_type, const char *arg)
{
- if (strcasecmp(arg, "none") == 0)
+ if (OPENSSL_strcasecmp(arg, "none") == 0)
*copy_type = EXT_COPY_NONE;
- else if (strcasecmp(arg, "copy") == 0)
+ else if (OPENSSL_strcasecmp(arg, "copy") == 0)
*copy_type = EXT_COPY_ADD;
- else if (strcasecmp(arg, "copyall") == 0)
+ else if (OPENSSL_strcasecmp(arg, "copyall") == 0)
*copy_type = EXT_COPY_ALL;
else
return 0;
@@ -1084,41 +1207,38 @@ int set_ext_copy(int *copy_type, const char *arg)
int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
{
- STACK_OF(X509_EXTENSION) *exts = NULL;
- X509_EXTENSION *ext, *tmpext;
- ASN1_OBJECT *obj;
- int i, idx, ret = 0;
- if (!x || !req || (copy_type == EXT_COPY_NONE))
+ STACK_OF(X509_EXTENSION) *exts;
+ int i, ret = 0;
+
+ if (x == NULL || req == NULL)
+ return 0;
+ if (copy_type == EXT_COPY_NONE)
return 1;
exts = X509_REQ_get_extensions(req);
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
- ext = sk_X509_EXTENSION_value(exts, i);
- obj = X509_EXTENSION_get_object(ext);
- idx = X509_get_ext_by_OBJ(x, obj, -1);
- /* Does extension exist? */
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
+ int idx = X509_get_ext_by_OBJ(x, obj, -1);
+
+ /* Does extension exist in target? */
if (idx != -1) {
/* If normal copy don't override existing extension */
if (copy_type == EXT_COPY_ADD)
continue;
/* Delete all extensions of same type */
do {
- tmpext = X509_get_ext(x, idx);
- X509_delete_ext(x, idx);
- X509_EXTENSION_free(tmpext);
+ X509_EXTENSION_free(X509_delete_ext(x, idx));
idx = X509_get_ext_by_OBJ(x, obj, -1);
} while (idx != -1);
}
if (!X509_add_ext(x, ext, -1))
goto end;
}
-
ret = 1;
end:
-
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
-
return ret;
}
@@ -1158,7 +1278,7 @@ static int set_table_opts(unsigned long *flags, const char *arg,
}
for (ptbl = in_tbl; ptbl->name; ptbl++) {
- if (strcasecmp(arg, ptbl->name) == 0) {
+ if (OPENSSL_strcasecmp(arg, ptbl->name) == 0) {
*flags &= ~ptbl->mask;
if (c)
*flags |= ptbl->flag;
@@ -1170,14 +1290,16 @@ static int set_table_opts(unsigned long *flags, const char *arg,
return 0;
}
-void print_name(BIO *out, const char *title, X509_NAME *nm,
- unsigned long lflags)
+void print_name(BIO *out, const char *title, const X509_NAME *nm)
{
char *buf;
char mline = 0;
int indent = 0;
+ unsigned long lflags = get_nameopt();
- if (title)
+ if (out == NULL)
+ return;
+ if (title != NULL)
BIO_puts(out, title);
if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mline = 1;
@@ -1233,10 +1355,14 @@ void print_array(BIO *out, const char* title, int len, const unsigned char* d)
BIO_printf(out, "\n};\n");
}
-X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath)
+X509_STORE *setup_verify(const char *CAfile, int noCAfile,
+ const char *CApath, int noCApath,
+ const char *CAstore, int noCAstore)
{
X509_STORE *store = X509_STORE_new();
X509_LOOKUP *lookup;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ const char *propq = app_get0_propq();
if (store == NULL)
goto end;
@@ -1245,13 +1371,15 @@ X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, i
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)) {
+ if (CAfile != NULL) {
+ if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM,
+ libctx, propq) <= 0) {
BIO_printf(bio_err, "Error loading file %s\n", CAfile);
goto end;
}
} else {
- X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+ X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT,
+ libctx, propq);
}
}
@@ -1259,8 +1387,8 @@ X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, i
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)) {
+ if (CApath != NULL) {
+ if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) {
BIO_printf(bio_err, "Error loading directory %s\n", CApath);
goto end;
}
@@ -1269,72 +1397,25 @@ X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, i
}
}
+ if (CAstore != NULL || !noCAstore) {
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_store());
+ if (lookup == NULL)
+ goto end;
+ if (!X509_LOOKUP_add_store_ex(lookup, CAstore, libctx, propq)) {
+ if (CAstore != NULL)
+ BIO_printf(bio_err, "Error loading store URI %s\n", CAstore);
+ goto end;
+ }
+ }
+
ERR_clear_error();
return store;
end:
+ ERR_print_errors(bio_err);
X509_STORE_free(store);
return NULL;
}
-#ifndef OPENSSL_NO_ENGINE
-/* Try to load an engine in a shareable library */
-static ENGINE *try_load_engine(const char *engine)
-{
- ENGINE *e = ENGINE_by_id("dynamic");
- if (e) {
- if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
- || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
- ENGINE_free(e);
- e = NULL;
- }
- }
- return e;
-}
-#endif
-
-ENGINE *setup_engine(const char *engine, int debug)
-{
- ENGINE *e = NULL;
-
-#ifndef OPENSSL_NO_ENGINE
- if (engine != NULL) {
- if (strcmp(engine, "auto") == 0) {
- 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(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, 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(bio_err, "can't use that engine\n");
- ERR_print_errors(bio_err);
- ENGINE_free(e);
- return NULL;
- }
-
- BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e));
- }
-#endif
- return e;
-}
-
-void release_engine(ENGINE *e)
-{
-#ifndef OPENSSL_NO_ENGINE
- if (e != NULL)
- /* Free our "structural" reference. */
- ENGINE_free(e);
-#endif
-}
-
static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
{
const char *n;
@@ -1408,19 +1489,18 @@ BIGNUM *load_serial(const char *serialfile, int *exists, int create,
}
} else {
if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
- BIO_printf(bio_err, "unable to load number from %s\n",
+ BIO_printf(bio_err, "Unable to load number from %s\n",
serialfile);
goto err;
}
ret = ASN1_INTEGER_to_BN(ai, NULL);
if (ret == NULL) {
- BIO_printf(bio_err,
- "error converting number from bin to BIGNUM\n");
+ BIO_printf(bio_err, "Error converting number from bin to BIGNUM\n");
goto err;
}
}
- if (ret && retai) {
+ if (ret != NULL && retai != NULL) {
*retai = ai;
ai = NULL;
}
@@ -1446,7 +1526,7 @@ int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial
else
j = strlen(serialfile) + strlen(suffix) + 1;
if (j >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
+ BIO_printf(bio_err, "File name too long\n");
goto err;
}
@@ -1461,7 +1541,6 @@ int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial
}
out = BIO_new_file(buf[0], "w");
if (out == NULL) {
- ERR_print_errors(bio_err);
goto err;
}
@@ -1477,6 +1556,8 @@ int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial
ai = NULL;
}
err:
+ if (!ret)
+ ERR_print_errors(bio_err);
BIO_free_all(out);
ASN1_INTEGER_free(ai);
return ret;
@@ -1493,7 +1574,7 @@ int rotate_serial(const char *serialfile, const char *new_suffix,
if (i > j)
j = i;
if (j + 1 >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
+ BIO_printf(bio_err, "File name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
@@ -1509,19 +1590,20 @@ int rotate_serial(const char *serialfile, const char *new_suffix,
#endif
) {
BIO_printf(bio_err,
- "unable to rename %s to %s\n", serialfile, buf[1]);
+ "Unable to rename %s to %s\n", serialfile, buf[1]);
perror("reason");
goto err;
}
if (rename(buf[0], serialfile) < 0) {
BIO_printf(bio_err,
- "unable to rename %s to %s\n", buf[0], serialfile);
+ "Unable to rename %s to %s\n", buf[0], serialfile);
perror("reason");
rename(buf[1], serialfile);
goto err;
}
return 1;
err:
+ ERR_print_errors(bio_err);
return 0;
}
@@ -1562,17 +1644,14 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
#endif
in = BIO_new_file(dbfile, "r");
- if (in == NULL) {
- ERR_print_errors(bio_err);
+ if (in == NULL)
goto err;
- }
#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);
+ ERR_raise_data(ERR_LIB_SYS, errno,
+ "calling fstat(%s)", dbfile);
goto err;
}
#endif
@@ -1609,6 +1688,7 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
#endif
err:
+ ERR_print_errors(bio_err);
NCONF_free(dbattr_conf);
TXT_DB_free(tmpdb);
BIO_free_all(in);
@@ -1624,20 +1704,23 @@ int index_index(CA_DB *db)
LHASH_HASH_FN(index_serial),
LHASH_COMP_FN(index_serial))) {
BIO_printf(bio_err,
- "error creating serial number index:(%ld,%ld,%ld)\n",
+ "Error creating serial number index:(%ld,%ld,%ld)\n",
db->db->error, db->db->arg1, db->db->arg2);
- return 0;
+ goto err;
}
if (db->attributes.unique_subject
&& !TXT_DB_create_index(db->db, DB_name, index_name_qual,
LHASH_HASH_FN(index_name),
LHASH_COMP_FN(index_name))) {
- BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
+ BIO_printf(bio_err, "Error creating name index:(%ld,%ld,%ld)\n",
db->db->error, db->db->arg1, db->db->arg2);
- return 0;
+ goto err;
}
return 1;
+ err:
+ ERR_print_errors(bio_err);
+ return 0;
}
int save_index(const char *dbfile, const char *suffix, CA_DB *db)
@@ -1648,7 +1731,7 @@ int save_index(const char *dbfile, const char *suffix, CA_DB *db)
j = strlen(dbfile) + strlen(suffix);
if (j + 6 >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
+ BIO_printf(bio_err, "File name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
@@ -1663,7 +1746,7 @@ int save_index(const char *dbfile, const char *suffix, CA_DB *db)
out = BIO_new_file(buf[0], "w");
if (out == NULL) {
perror(dbfile);
- BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
+ BIO_printf(bio_err, "Unable to open '%s'\n", dbfile);
goto err;
}
j = TXT_DB_write(out, db->db);
@@ -1674,7 +1757,7 @@ int save_index(const char *dbfile, const char *suffix, CA_DB *db)
out = BIO_new_file(buf[1], "w");
if (out == NULL) {
perror(buf[2]);
- BIO_printf(bio_err, "unable to open '%s'\n", buf[2]);
+ BIO_printf(bio_err, "Unable to open '%s'\n", buf[2]);
goto err;
}
BIO_printf(out, "unique_subject = %s\n",
@@ -1683,6 +1766,7 @@ int save_index(const char *dbfile, const char *suffix, CA_DB *db)
return 1;
err:
+ ERR_print_errors(bio_err);
return 0;
}
@@ -1697,7 +1781,7 @@ int rotate_index(const char *dbfile, const char *new_suffix,
if (i > j)
j = i;
if (j + 6 >= BSIZE) {
- BIO_printf(bio_err, "file name too long\n");
+ BIO_printf(bio_err, "File name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
@@ -1718,12 +1802,12 @@ int rotate_index(const char *dbfile, const char *new_suffix,
&& errno != ENOTDIR
#endif
) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]);
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", dbfile, buf[1]);
perror("reason");
goto err;
}
if (rename(buf[0], dbfile) < 0) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile);
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[0], dbfile);
perror("reason");
rename(buf[1], dbfile);
goto err;
@@ -1733,14 +1817,14 @@ int rotate_index(const char *dbfile, const char *new_suffix,
&& errno != ENOTDIR
#endif
) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]);
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[4], buf[3]);
perror("reason");
rename(dbfile, buf[0]);
rename(buf[1], dbfile);
goto err;
}
if (rename(buf[2], buf[4]) < 0) {
- BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]);
+ BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[2], buf[4]);
perror("reason");
rename(buf[3], buf[4]);
rename(dbfile, buf[0]);
@@ -1749,6 +1833,7 @@ int rotate_index(const char *dbfile, const char *new_suffix,
}
return 1;
err:
+ ERR_print_errors(bio_err);
return 0;
}
@@ -1784,9 +1869,11 @@ int parse_yesno(const char *str, int def)
/*
* name is expected to be in the format /type0=value0/type1=value1/type2=...
- * where characters may be escaped by \
+ * where + can be used instead of / to form multi-valued RDNs if canmulti
+ * and characters may be escaped by \
*/
-X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
+X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
+ const char *desc)
{
int nextismulti = 0;
char *work;
@@ -1794,21 +1881,26 @@ X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
if (*cp++ != '/') {
BIO_printf(bio_err,
- "name is expected to be in the format "
+ "%s: %s 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);
+ opt_getprog(), desc, --cp);
return NULL;
}
n = X509_NAME_new();
- if (n == NULL)
+ if (n == NULL) {
+ BIO_printf(bio_err, "%s: Out of memory\n", opt_getprog());
return NULL;
+ }
work = OPENSSL_strdup(cp);
- if (work == NULL)
+ if (work == NULL) {
+ BIO_printf(bio_err, "%s: Error copying %s name input\n",
+ opt_getprog(), desc);
goto err;
+ }
- while (*cp) {
+ while (*cp != '\0') {
char *bp = work;
char *typestr = bp;
unsigned char *valstr;
@@ -1817,54 +1909,64 @@ X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
nextismulti = 0;
/* Collect the type */
- while (*cp && *cp != '=')
+ while (*cp != '\0' && *cp != '=')
*bp++ = *cp++;
+ *bp++ = '\0';
if (*cp == '\0') {
BIO_printf(bio_err,
- "%s: Hit end of string before finding the equals.\n",
- opt_getprog());
+ "%s: Missing '=' after RDN type string '%s' in %s name string\n",
+ opt_getprog(), typestr, desc);
goto err;
}
- *bp++ = '\0';
++cp;
/* Collect the value. */
valstr = (unsigned char *)bp;
- for (; *cp && *cp != '/'; *bp++ = *cp++) {
+ for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) {
+ /* unescaped '+' symbol string signals further member of multiRDN */
if (canmulti && *cp == '+') {
nextismulti = 1;
break;
}
if (*cp == '\\' && *++cp == '\0') {
BIO_printf(bio_err,
- "%s: escape character at end of string\n",
- opt_getprog());
+ "%s: Escape character at end of %s name string\n",
+ opt_getprog(), desc);
goto err;
}
}
*bp++ = '\0';
/* If not at EOS (must be + or /), move forward. */
- if (*cp)
+ if (*cp != '\0')
++cp;
/* Parse */
nid = OBJ_txt2nid(typestr);
if (nid == NID_undef) {
- BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n",
- opt_getprog(), typestr);
+ BIO_printf(bio_err,
+ "%s: Skipping unknown %s name attribute \"%s\"\n",
+ opt_getprog(), desc, typestr);
+ if (ismulti)
+ BIO_printf(bio_err,
+ "Hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n");
continue;
}
if (*valstr == '\0') {
BIO_printf(bio_err,
- "%s: No value provided for Subject Attribute %s, skipped\n",
- opt_getprog(), typestr);
+ "%s: No value provided for %s name attribute \"%s\", skipped\n",
+ opt_getprog(), desc, typestr);
continue;
}
if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
valstr, strlen((char *)valstr),
- -1, ismulti ? -1 : 0))
+ -1, ismulti ? -1 : 0)) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err,
+ "%s: Error adding %s name attribute \"/%s=%s\"\n",
+ opt_getprog(), desc, typestr ,valstr);
goto err;
+ }
}
OPENSSL_free(work);
@@ -1919,17 +2021,21 @@ int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
{
- int rv;
+ int rv = 0;
char *stmp, *vtmp = NULL;
+
stmp = OPENSSL_strdup(value);
- if (!stmp)
+ if (stmp == NULL)
return -1;
vtmp = strchr(stmp, ':');
- if (vtmp) {
- *vtmp = 0;
- vtmp++;
- }
+ if (vtmp == NULL)
+ goto err;
+
+ *vtmp = 0;
+ vtmp++;
rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
+
+ err:
OPENSSL_free(stmp);
return rv;
}
@@ -2047,6 +2153,209 @@ void print_cert_checks(BIO *bio, X509 *x,
}
}
+static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts)
+{
+ int i;
+
+ if (opts == NULL)
+ return 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (pkey_ctrl_string(pkctx, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int do_x509_init(X509 *x, STACK_OF(OPENSSL_STRING) *opts)
+{
+ int i;
+
+ if (opts == NULL)
+ return 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (x509_ctrl_string(x, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts)
+{
+ int i;
+
+ if (opts == NULL)
+ return 1;
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (x509_req_ctrl_string(x, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
+ const char *md, STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ EVP_PKEY_CTX *pkctx = NULL;
+ char def_md[80];
+
+ if (ctx == NULL)
+ return 0;
+ /*
+ * EVP_PKEY_get_default_digest_name() returns 2 if the digest is mandatory
+ * for this algorithm.
+ */
+ if (EVP_PKEY_get_default_digest_name(pkey, def_md, sizeof(def_md)) == 2
+ && strcmp(def_md, "UNDEF") == 0) {
+ /* The signing algorithm requires there to be no digest */
+ md = NULL;
+ }
+
+ return EVP_DigestSignInit_ex(ctx, &pkctx, md, app_get0_libctx(),
+ app_get0_propq(), pkey, NULL)
+ && do_pkey_ctx_init(pkctx, sigopts);
+}
+
+static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
+ const char *name, const char *value, int add_default)
+{
+ const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
+ X509_EXTENSION *new_ext = X509V3_EXT_nconf(NULL, ext_ctx, name, value);
+ int idx, rv = 0;
+
+ if (new_ext == NULL)
+ return rv;
+
+ idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1);
+ if (idx >= 0) {
+ X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx);
+ ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(found_ext);
+ int disabled = ASN1_STRING_length(data) <= 2; /* config said "none" */
+
+ if (disabled) {
+ X509_delete_ext(cert, idx);
+ X509_EXTENSION_free(found_ext);
+ } /* else keep existing key identifier, which might be outdated */
+ rv = 1;
+ } else {
+ rv = !add_default || X509_add_ext(cert, new_ext, -1);
+ }
+ X509_EXTENSION_free(new_ext);
+ return rv;
+}
+
+/* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
+int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
+{
+ const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+ int self_sign;
+ int rv = 0;
+
+ if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) {
+ /* Prevent X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 */
+ if (!X509_set_version(cert, X509_VERSION_3))
+ goto end;
+
+ /*
+ * Add default SKID before such that default AKID can make use of it
+ * in case the certificate is self-signed
+ */
+ /* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */
+ if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1))
+ goto end;
+ /* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */
+ ERR_set_mark();
+ self_sign = X509_check_private_key(cert, pkey);
+ ERR_pop_to_mark();
+ if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier",
+ "keyid, issuer", !self_sign))
+ goto end;
+ }
+
+ if (mctx != NULL && do_sign_init(mctx, pkey, md, sigopts) > 0)
+ rv = (X509_sign_ctx(cert, mctx) > 0);
+ end:
+ EVP_MD_CTX_free(mctx);
+ return rv;
+}
+
+/* Sign the certificate request info */
+int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ int rv = 0;
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+
+ if (do_sign_init(mctx, pkey, md, sigopts) > 0)
+ rv = (X509_REQ_sign_ctx(x, mctx) > 0);
+ EVP_MD_CTX_free(mctx);
+ return rv;
+}
+
+/* Sign the CRL info */
+int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ int rv = 0;
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+
+ if (do_sign_init(mctx, pkey, md, sigopts) > 0)
+ rv = (X509_CRL_sign_ctx(x, mctx) > 0);
+ EVP_MD_CTX_free(mctx);
+ return rv;
+}
+
+/*
+ * do_X509_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
+int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts)
+{
+ int rv = 0;
+
+ if (do_x509_init(x, vfyopts) > 0)
+ rv = X509_verify(x, pkey);
+ else
+ rv = -1;
+ return rv;
+}
+
+/*
+ * do_X509_REQ_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
+int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *vfyopts)
+{
+ int rv = 0;
+
+ if (do_x509_req_init(x, vfyopts) > 0)
+ rv = X509_REQ_verify_ex(x, pkey,
+ app_get0_libctx(), app_get0_propq());
+ else
+ rv = -1;
+ return rv;
+}
+
/* Get first http URL from a DIST_POINT structure */
static const char *get_dp_url(DIST_POINT *dp)
@@ -2063,7 +2372,8 @@ static const char *get_dp_url(DIST_POINT *dp)
uri = GENERAL_NAME_get0_value(gen, &gtype);
if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) {
const char *uptr = (const char *)ASN1_STRING_get0_data(uri);
- if (strncmp(uptr, "http://", 7) == 0)
+
+ if (IS_HTTP(uptr)) /* can/should not use HTTPS here */
return uptr;
}
}
@@ -2082,19 +2392,19 @@ static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
urlptr = get_dp_url(dp);
- if (urlptr)
- return load_crl(urlptr, FORMAT_HTTP);
+ if (urlptr != NULL)
+ return load_crl(urlptr, FORMAT_UNDEF, 0, "CRL via CDP");
}
return NULL;
}
/*
- * Example of downloading CRLs from CRLDP: not usable for real world as it
- * always downloads, doesn't support non-blocking I/O and doesn't cache
- * anything.
+ * Example of downloading CRLs from CRLDP:
+ * not usable for real world as it always downloads and doesn't cache anything.
*/
-static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm)
+static STACK_OF(X509_CRL) *crls_http_cb(const X509_STORE_CTX *ctx,
+ const X509_NAME *nm)
{
X509 *x;
STACK_OF(X509_CRL) *crls = NULL;
@@ -2127,6 +2437,184 @@ void store_setup_crl_download(X509_STORE *st)
X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
}
+#ifndef OPENSSL_NO_SOCK
+static const char *tls_error_hint(void)
+{
+ unsigned long err = ERR_peek_error();
+
+ if (ERR_GET_LIB(err) != ERR_LIB_SSL)
+ err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) != ERR_LIB_SSL)
+ return NULL;
+
+ switch (ERR_GET_REASON(err)) {
+ case SSL_R_WRONG_VERSION_NUMBER:
+ return "The server does not support (a suitable version of) TLS";
+ case SSL_R_UNKNOWN_PROTOCOL:
+ return "The server does not support HTTPS";
+ case SSL_R_CERTIFICATE_VERIFY_FAILED:
+ return "Cannot authenticate server via its TLS certificate, likely due to mismatch with our trusted TLS certs or missing revocation status";
+ case SSL_AD_REASON_OFFSET + TLS1_AD_UNKNOWN_CA:
+ return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status";
+ case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE:
+ return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it";
+ default: /* no error or no hint available for error */
+ return NULL;
+ }
+}
+
+/* HTTP callback function that supports TLS connection also via HTTPS proxy */
+BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail)
+{
+ APP_HTTP_TLS_INFO *info = (APP_HTTP_TLS_INFO *)arg;
+ SSL_CTX *ssl_ctx = info->ssl_ctx;
+
+ if (ssl_ctx == NULL) /* not using TLS */
+ return bio;
+ if (connect) {
+ SSL *ssl;
+ BIO *sbio = NULL;
+
+ /* adapt after fixing callback design flaw, see #17088 */
+ if ((info->use_proxy
+ && !OSSL_HTTP_proxy_connect(bio, info->server, info->port,
+ NULL, NULL, /* no proxy credentials */
+ info->timeout, bio_err, opt_getprog()))
+ || (sbio = BIO_new(BIO_f_ssl())) == NULL) {
+ return NULL;
+ }
+ if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) {
+ BIO_free(sbio);
+ return NULL;
+ }
+
+ /* adapt after fixing callback design flaw, see #17088 */
+ SSL_set_tlsext_host_name(ssl, info->server); /* not critical to do */
+
+ SSL_set_connect_state(ssl);
+ BIO_set_ssl(sbio, ssl, BIO_CLOSE);
+
+ bio = BIO_push(sbio, bio);
+ }
+ if (!connect) {
+ const char *hint;
+ BIO *cbio;
+
+ if (!detail) { /* disconnecting after error */
+ hint = tls_error_hint();
+ if (hint != NULL)
+ ERR_add_error_data(2, " : ", hint);
+ }
+ if (ssl_ctx != NULL) {
+ (void)ERR_set_mark();
+ BIO_ssl_shutdown(bio);
+ cbio = BIO_pop(bio); /* connect+HTTP BIO */
+ BIO_free(bio); /* SSL BIO */
+ (void)ERR_pop_to_mark(); /* hide SSL_R_READ_BIO_NOT_SET etc. */
+ bio = cbio;
+ }
+ }
+ return bio;
+}
+
+void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info)
+{
+ if (info != NULL) {
+ SSL_CTX_free(info->ssl_ctx);
+ OPENSSL_free(info);
+ }
+}
+
+ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
+ const char *no_proxy, SSL_CTX *ssl_ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ long timeout, const char *expected_content_type,
+ const ASN1_ITEM *it)
+{
+ APP_HTTP_TLS_INFO info;
+ char *server;
+ char *port;
+ int use_ssl;
+ BIO *mem;
+ ASN1_VALUE *resp = NULL;
+
+ if (url == NULL || it == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if (!OSSL_HTTP_parse_url(url, &use_ssl, NULL /* userinfo */, &server, &port,
+ NULL /* port_num, */, NULL, NULL, NULL))
+ return NULL;
+ if (use_ssl && ssl_ctx == NULL) {
+ ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER,
+ "missing SSL_CTX");
+ goto end;
+ }
+ if (!use_ssl && ssl_ctx != NULL) {
+ ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT,
+ "SSL_CTX given but use_ssl == 0");
+ goto end;
+ }
+
+ info.server = server;
+ info.port = port;
+ info.use_proxy = /* workaround for callback design flaw, see #17088 */
+ OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl) != NULL;
+ info.timeout = timeout;
+ info.ssl_ctx = ssl_ctx;
+ mem = OSSL_HTTP_get(url, proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
+ app_http_tls_cb, &info, 0 /* buf_size */, headers,
+ expected_content_type, 1 /* expect_asn1 */,
+ OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout);
+ resp = ASN1_item_d2i_bio(it, mem, NULL);
+ BIO_free(mem);
+
+ end:
+ OPENSSL_free(server);
+ OPENSSL_free(port);
+ return resp;
+
+}
+
+ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
+ const char *path, const char *proxy,
+ const char *no_proxy, SSL_CTX *ssl_ctx,
+ const STACK_OF(CONF_VALUE) *headers,
+ const char *content_type,
+ ASN1_VALUE *req, const ASN1_ITEM *req_it,
+ const char *expected_content_type,
+ long timeout, const ASN1_ITEM *rsp_it)
+{
+ int use_ssl = ssl_ctx != NULL;
+ APP_HTTP_TLS_INFO info;
+ BIO *rsp, *req_mem = ASN1_item_i2d_mem_bio(req_it, req);
+ ASN1_VALUE *res;
+
+ if (req_mem == NULL)
+ return NULL;
+
+ info.server = host;
+ info.port = port;
+ info.use_proxy = /* workaround for callback design flaw, see #17088 */
+ OSSL_HTTP_adapt_proxy(proxy, no_proxy, host, use_ssl) != NULL;
+ info.timeout = timeout;
+ info.ssl_ctx = ssl_ctx;
+ rsp = OSSL_HTTP_transfer(NULL, host, port, path, use_ssl,
+ proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
+ app_http_tls_cb, &info,
+ 0 /* buf_size */, headers, content_type, req_mem,
+ expected_content_type, 1 /* expect_asn1 */,
+ OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout,
+ 0 /* keep_alive */);
+ BIO_free(req_mem);
+ res = ASN1_item_d2i_bio(rsp_it, rsp, NULL);
+ BIO_free(rsp);
+ return res;
+}
+
+#endif
+
/*
* Platform-specific sections
*/
@@ -2277,40 +2765,6 @@ double app_tminterval(int stop, int usertime)
return ret;
}
-#elif defined(OPENSSL_SYSTEM_VMS)
-# include <time.h>
-# include <times.h>
-
-double app_tminterval(int stop, int usertime)
-{
- static clock_t tmstart;
- double ret = 0;
- clock_t now;
-# ifdef __TMS
- struct tms rus;
-
- now = times(&rus);
- if (usertime)
- now = rus.tms_utime;
-# else
- if (usertime)
- now = clock(); /* sum of user and kernel times */
- else {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK +
- (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK)
- );
- }
-# endif
- if (stop == TM_START)
- tmstart = now;
- else
- ret = (now - tmstart) / (double)(CLK_TCK);
-
- return ret;
-}
-
#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
# include <sys/times.h>
@@ -2369,56 +2823,10 @@ int app_access(const char* name, int flag)
#endif
}
-/* app_isdir section */
-#ifdef _WIN32
int app_isdir(const char *name)
{
- DWORD attr;
-# if defined(UNICODE) || defined(_UNICODE)
- size_t i, len_0 = strlen(name) + 1;
- WCHAR tempname[MAX_PATH];
-
- if (len_0 > MAX_PATH)
- return -1;
-
-# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
- if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH))
-# endif
- for (i = 0; i < len_0; i++)
- tempname[i] = (WCHAR)name[i];
-
- attr = GetFileAttributes(tempname);
-# else
- attr = GetFileAttributes(name);
-# endif
- if (attr == INVALID_FILE_ATTRIBUTES)
- return -1;
- return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ return opt_isdir(name);
}
-#else
-# include <sys/stat.h>
-# ifndef S_ISDIR
-# if defined(_S_IFMT) && defined(_S_IFDIR)
-# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR)
-# else
-# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
-# endif
-# endif
-
-int app_isdir(const char *name)
-{
-# if defined(S_ISDIR)
- struct stat st;
-
- if (stat(name, &st) == 0)
- return S_ISDIR(st.st_mode);
- else
- return -1;
-# else
- return -1;
-# endif
-}
-#endif
/* raw_read|write section */
#if defined(__VMS)
@@ -2468,6 +2876,11 @@ int raw_read_stdin(void *buf, int siz)
return recv(fileno_stdin(), buf, siz, 0);
}
#else
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_read)>
+# endif
+# endif
int raw_read_stdin(void *buf, int siz)
{
return read(fileno_stdin(), buf, siz);
@@ -2483,7 +2896,22 @@ int raw_write_stdout(const void *buf, int siz)
else
return -1;
}
+#elif defined(OPENSSL_SYS_TANDEM) && defined(OPENSSL_THREADS) && defined(_SPT_MODEL_)
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_write)>
+# endif
+# endif
+int raw_write_stdout(const void *buf,int siz)
+{
+ return write(fileno(stdout),(void*)buf,siz);
+}
#else
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_write)>
+# endif
+# endif
int raw_write_stdout(const void *buf, int siz)
{
return write(fileno_stdout(), buf, siz);
@@ -2491,41 +2919,36 @@ int raw_write_stdout(const void *buf, int siz)
#endif
/*
- * Centralized handling if input and output files with format specification
+ * Centralized handling of 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
+ * does impact behavior on some platforms, 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));
+ BIO_NOCLOSE | (FMT_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));
+ BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
void *prefix = NULL;
+ if (b == NULL)
+ return NULL;
+
#ifdef OPENSSL_SYS_VMS
- if (istext(format))
+ if (FMT_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);
+ if (FMT_istext(format)
+ && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
+ b = BIO_push(BIO_new(BIO_f_prefix()), b);
+ BIO_set_prefix(b, prefix);
}
return b;
@@ -2534,20 +2957,14 @@ BIO *dup_bio_out(int format)
BIO *dup_bio_err(int format)
{
BIO *b = BIO_new_fp(stderr,
- BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
+ BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
#ifdef OPENSSL_SYS_VMS
- if (istext(format))
+ if (b != NULL && FMT_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)
{
/*
@@ -2573,11 +2990,11 @@ static const char *modestr(char mode, int format)
switch (mode) {
case 'a':
- return istext(format) ? "a" : "ab";
+ return FMT_istext(format) ? "a" : "ab";
case 'r':
- return istext(format) ? "r" : "rb";
+ return FMT_istext(format) ? "r" : "rb";
case 'w':
- return istext(format) ? "w" : "wb";
+ return FMT_istext(format) ? "w" : "wb";
}
/* The assert above should make sure we never reach this point */
return NULL;
@@ -2603,28 +3020,32 @@ BIO *bio_open_owner(const char *filename, int format, int private)
{
FILE *fp = NULL;
BIO *b = NULL;
- int fd = -1, bflags, mode, textmode;
+ int textmode, bflags;
+#ifndef OPENSSL_NO_POSIX_IO
+ int fd = -1, mode;
+#endif
if (!private || filename == NULL || strcmp(filename, "-") == 0)
return bio_open_default(filename, 'w', format);
+ textmode = FMT_istext(format);
+#ifndef OPENSSL_NO_POSIX_IO
mode = O_WRONLY;
-#ifdef O_CREAT
+# ifdef O_CREAT
mode |= O_CREAT;
-#endif
-#ifdef O_TRUNC
+# endif
+# ifdef O_TRUNC
mode |= O_TRUNC;
-#endif
- textmode = istext(format);
+# endif
if (!textmode) {
-#ifdef O_BINARY
+# ifdef O_BINARY
mode |= O_BINARY;
-#elif defined(_O_BINARY)
+# elif defined(_O_BINARY)
mode |= _O_BINARY;
-#endif
+# endif
}
-#ifdef OPENSSL_SYS_VMS
+# 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
@@ -2633,18 +3054,22 @@ BIO *bio_open_owner(const char *filename, int format, int private)
if (!textmode)
fd = open(filename, mode, 0600, "ctx=bin");
else
-#endif
+# endif
fd = open(filename, mode, 0600);
if (fd < 0)
goto err;
fp = fdopen(fd, modestr('w', format));
+#else /* OPENSSL_NO_POSIX_IO */
+ /* Have stdio but not Posix IO, do the best we can */
+ fp = fopen(filename, modestr('w', format));
+#endif /* OPENSSL_NO_POSIX_IO */
if (fp == NULL)
goto err;
bflags = BIO_CLOSE;
if (textmode)
bflags |= BIO_FP_TEXT;
b = BIO_new_fp(fp, bflags);
- if (b)
+ if (b != NULL)
return b;
err:
@@ -2652,10 +3077,12 @@ BIO *bio_open_owner(const char *filename, int format, int private)
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)
+ if (fp != NULL)
fclose(fp);
+#ifndef OPENSSL_NO_POSIX_IO
else if (fd >= 0)
close(fd);
+#endif
return NULL;
}
@@ -2684,7 +3111,7 @@ static BIO *bio_open_default_(const char *filename, char mode, int format,
if (ret != NULL)
return ret;
BIO_printf(bio_err,
- "Can't open %s for %s, %s\n",
+ "Can't open \"%s\" for %s, %s\n",
filename, modeverb(mode), strerror(errno));
}
ERR_print_errors(bio_err);
@@ -2787,6 +3214,57 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
return 1;
}
+int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate)
+{
+ int ret = 0;
+ ASN1_TIME *tm = ASN1_TIME_new();
+
+ if (tm == NULL)
+ goto end;
+
+ if (lastupdate == NULL) {
+ if (X509_gmtime_adj(tm, 0) == NULL)
+ goto end;
+ } else {
+ if (!ASN1_TIME_set_string_X509(tm, lastupdate))
+ goto end;
+ }
+
+ if (!X509_CRL_set1_lastUpdate(crl, tm))
+ goto end;
+
+ ret = 1;
+end:
+ ASN1_TIME_free(tm);
+ return ret;
+}
+
+int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate,
+ long days, long hours, long secs)
+{
+ int ret = 0;
+ ASN1_TIME *tm = ASN1_TIME_new();
+
+ if (tm == NULL)
+ goto end;
+
+ if (nextupdate == NULL) {
+ if (X509_time_adj_ex(tm, days, hours * 60 * 60 + secs, NULL) == NULL)
+ goto end;
+ } else {
+ if (!ASN1_TIME_set_string_X509(tm, nextupdate))
+ goto end;
+ }
+
+ if (!X509_CRL_set1_nextUpdate(crl, tm))
+ goto end;
+
+ ret = 1;
+end:
+ ASN1_TIME_free(tm);
+ return ret;
+}
+
void make_uppercase(char *string)
{
int i;
@@ -2794,3 +3272,118 @@ void make_uppercase(char *string)
for (i = 0; string[i] != '\0'; i++)
string[i] = toupper((unsigned char)string[i]);
}
+
+/* This function is defined here due to visibility of bio_err */
+int opt_printf_stderr(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = BIO_vprintf(bio_err, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts,
+ const OSSL_PARAM *paramdefs)
+{
+ OSSL_PARAM *params = NULL;
+ size_t sz = (size_t)sk_OPENSSL_STRING_num(opts);
+ size_t params_n;
+ char *opt = "", *stmp, *vtmp = NULL;
+ int found = 1;
+
+ if (opts == NULL)
+ return NULL;
+
+ params = OPENSSL_zalloc(sizeof(OSSL_PARAM) * (sz + 1));
+ if (params == NULL)
+ return NULL;
+
+ for (params_n = 0; params_n < sz; params_n++) {
+ opt = sk_OPENSSL_STRING_value(opts, (int)params_n);
+ if ((stmp = OPENSSL_strdup(opt)) == NULL
+ || (vtmp = strchr(stmp, ':')) == NULL)
+ goto err;
+ /* Replace ':' with 0 to terminate the string pointed to by stmp */
+ *vtmp = 0;
+ /* Skip over the separator so that vmtp points to the value */
+ vtmp++;
+ if (!OSSL_PARAM_allocate_from_text(&params[params_n], paramdefs,
+ stmp, vtmp, strlen(vtmp), &found))
+ goto err;
+ OPENSSL_free(stmp);
+ }
+ params[params_n] = OSSL_PARAM_construct_end();
+ return params;
+err:
+ OPENSSL_free(stmp);
+ BIO_printf(bio_err, "Parameter %s '%s'\n", found ? "error" : "unknown",
+ opt);
+ ERR_print_errors(bio_err);
+ app_params_free(params);
+ return NULL;
+}
+
+void app_params_free(OSSL_PARAM *params)
+{
+ int i;
+
+ if (params != NULL) {
+ for (i = 0; params[i].key != NULL; ++i)
+ OPENSSL_free(params[i].data);
+ OPENSSL_free(params);
+ }
+}
+
+EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose)
+{
+ EVP_PKEY *res = NULL;
+
+ if (verbose && alg != NULL) {
+ BIO_printf(bio_err, "Generating %s key", alg);
+ if (bits > 0)
+ BIO_printf(bio_err, " with %d bits\n", bits);
+ else
+ BIO_printf(bio_err, "\n");
+ }
+ if (!RAND_status())
+ BIO_printf(bio_err, "Warning: generating random key material may take a long time\n"
+ "if the system has a poor entropy source\n");
+ if (EVP_PKEY_keygen(ctx, &res) <= 0)
+ app_bail_out("%s: Error generating %s key\n", opt_getprog(),
+ alg != NULL ? alg : "asymmetric");
+ return res;
+}
+
+EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg)
+{
+ EVP_PKEY *res = NULL;
+
+ if (!RAND_status())
+ BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n"
+ "if the system has a poor entropy source\n");
+ if (EVP_PKEY_paramgen(ctx, &res) <= 0)
+ app_bail_out("%s: Generating %s key parameters failed\n",
+ opt_getprog(), alg != NULL ? alg : "asymmetric");
+ return res;
+}
+
+/*
+ * Return non-zero if the legacy path is still an option.
+ * This decision is based on the global command line operations and the
+ * behaviour thus far.
+ */
+int opt_legacy_okay(void)
+{
+ int provider_options = opt_provider_option_given();
+ int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL;
+ /*
+ * Having a provider option specified or a custom library context or
+ * property query, is a sure sign we're not using legacy.
+ */
+ if (provider_options || libctx)
+ return 0;
+ return 1;
+}
diff --git a/apps/lib/apps_ui.c b/apps/lib/apps_ui.c
new file mode 100644
index 000000000000..00e0ba5d9996
--- /dev/null
+++ b/apps/lib/apps_ui.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 <openssl/err.h>
+#include <openssl/ui.h>
+#include "apps_ui.h"
+
+static UI_METHOD *ui_method = NULL;
+static const UI_METHOD *ui_base_method = NULL;
+
+static int ui_open(UI *ui)
+{
+ int (*opener)(UI *ui) = UI_method_get_opener(ui_base_method);
+
+ if (opener != NULL)
+ 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)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ {
+ const char *password =
+ ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
+
+ if (password != NULL) {
+ UI_set_result(ui, uis, password);
+ return 1;
+ }
+ }
+ break;
+ case UIT_NONE:
+ case UIT_BOOLEAN:
+ case UIT_INFO:
+ case UIT_ERROR:
+ break;
+ }
+ }
+
+ reader = UI_method_get_reader(ui_base_method);
+ if (reader != NULL)
+ return reader(ui, uis);
+ /* Default to the empty password if we've got nothing better */
+ UI_set_result(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)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ {
+ const char *password =
+ ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
+
+ if (password != NULL)
+ return 1;
+ }
+ break;
+ case UIT_NONE:
+ case UIT_BOOLEAN:
+ case UIT_INFO:
+ case UIT_ERROR:
+ break;
+ }
+ }
+
+ writer = UI_method_get_writer(ui_base_method);
+ if (writer != NULL)
+ return writer(ui, uis);
+ return 1;
+}
+
+static int ui_close(UI *ui)
+{
+ int (*closer)(UI *ui) = UI_method_get_closer(ui_base_method);
+
+ if (closer != NULL)
+ return closer(ui);
+ return 1;
+}
+
+/* object_name defaults to prompt_info from ui user data if present */
+static char *ui_prompt_construct(UI *ui, const char *phrase_desc,
+ const char *object_name)
+{
+ PW_CB_DATA *cb_data = (PW_CB_DATA *)UI_get0_user_data(ui);
+
+ if (phrase_desc == NULL)
+ phrase_desc = "pass phrase";
+ if (object_name == NULL && cb_data != NULL)
+ object_name = cb_data->prompt_info;
+ return UI_construct_prompt(NULL, phrase_desc, object_name);
+}
+
+int set_base_ui_method(const UI_METHOD *ui_meth)
+{
+ if (ui_meth == NULL)
+ ui_meth = UI_null();
+ ui_base_method = ui_meth;
+ return 1;
+}
+
+int setup_ui_method(void)
+{
+ ui_base_method = UI_null();
+#ifndef OPENSSL_NO_UI_CONSOLE
+ ui_base_method = UI_OpenSSL();
+#endif
+ ui_method = UI_create_method("OpenSSL application user interface");
+ return ui_method != NULL
+ && 0 == UI_method_set_opener(ui_method, ui_open)
+ && 0 == UI_method_set_reader(ui_method, ui_read)
+ && 0 == UI_method_set_writer(ui_method, ui_write)
+ && 0 == UI_method_set_closer(ui_method, ui_close)
+ && 0 == UI_method_set_prompt_constructor(ui_method,
+ ui_prompt_construct);
+}
+
+void destroy_ui_method(void)
+{
+ if (ui_method != NULL) {
+ UI_destroy_method(ui_method);
+ ui_method = NULL;
+ }
+}
+
+const UI_METHOD *get_ui_method(void)
+{
+ return ui_method;
+}
+
+static void *ui_malloc(int sz, const char *what)
+{
+ void *vp = OPENSSL_malloc(sz);
+
+ if (vp == NULL) {
+ BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what);
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ return vp;
+}
+
+int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data)
+{
+ int res = 0;
+ UI *ui;
+ int ok = 0;
+ char *buff = NULL;
+ int ui_flags = 0;
+ const char *prompt_info = NULL;
+ char *prompt;
+
+ if ((ui = UI_new_method(ui_method)) == NULL)
+ return 0;
+
+ 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 == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ UI_free(ui);
+ return 0;
+ }
+
+ ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
+ UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
+
+ /* 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 = ui_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));
+
+ OPENSSL_clear_free(buff, (unsigned int)bufsiz);
+
+ if (ok >= 0)
+ res = strlen(buf);
+ if (ok == -1) {
+ BIO_printf(bio_err, "User interface error\n");
+ ERR_print_errors(bio_err);
+ OPENSSL_cleanse(buf, (unsigned int)bufsiz);
+ res = 0;
+ }
+ if (ok == -2) {
+ BIO_printf(bio_err, "aborted!\n");
+ OPENSSL_cleanse(buf, (unsigned int)bufsiz);
+ res = 0;
+ }
+ UI_free(ui);
+ OPENSSL_free(prompt);
+ return res;
+}
diff --git a/apps/lib/build.info b/apps/lib/build.info
new file mode 100644
index 000000000000..923ef5d92b83
--- /dev/null
+++ b/apps/lib/build.info
@@ -0,0 +1,23 @@
+# Auxiliary program source
+IF[{- $config{target} =~ /^(?:VC-|mingw|BC-)/ -}]
+ # It's called 'init', but doesn't have much 'init' in it...
+ $AUXLIBAPPSSRC=win32_init.c
+ENDIF
+IF[{- $config{target} =~ /^vms-/ -}]
+ $AUXLIBAPPSSRC=vms_term_sock.c vms_decc_argv.c
+ENDIF
+
+# Source for libapps
+$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
+ columns.c app_params.c names.c app_provider.c app_x509.c http_server.c \
+ engine.c engine_loader.c app_libctx.c
+
+IF[{- !$disabled{apps} -}]
+ LIBS{noinst}=../libapps.a
+ SOURCE[../libapps.a]=$LIBAPPSSRC $AUXLIBAPPSSRC
+ INCLUDE[../libapps.a]=../.. ../../include ../include
+ENDIF
+
+IF[{- !$disabled{srp} -}]
+ SOURCE[../libapps.a]=tlssrp_depr.c
+ENDIF
diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c
new file mode 100644
index 000000000000..b37f3dd3d89c
--- /dev/null
+++ b/apps/lib/cmp_mock_srv.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Siemens AG 2018-2020
+ *
+ * Licensed under the Apache License 2.0 (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 atf
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include "cmp_mock_srv.h"
+
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+#include <openssl/cmperr.h>
+
+/* the context for the CMP mock server */
+typedef struct
+{
+ X509 *certOut; /* certificate to be returned in cp/ip/kup msg */
+ STACK_OF(X509) *chainOut; /* chain of certOut to add to extraCerts field */
+ STACK_OF(X509) *caPubsOut; /* certs to return in caPubs field of ip msg */
+ OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
+ int sendError; /* send error response also on valid requests */
+ OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */
+ int certReqId; /* id of last ir/cr/kur, used for polling */
+ int pollCount; /* number of polls before actual cert response */
+ int curr_pollCount; /* number of polls so far for current request */
+ int checkAfterTime; /* time the client should wait between polling */
+} mock_srv_ctx;
+
+
+static void mock_srv_ctx_free(mock_srv_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ OSSL_CMP_PKISI_free(ctx->statusOut);
+ X509_free(ctx->certOut);
+ sk_X509_pop_free(ctx->chainOut, X509_free);
+ sk_X509_pop_free(ctx->caPubsOut, X509_free);
+ OSSL_CMP_MSG_free(ctx->certReq);
+ OPENSSL_free(ctx);
+}
+
+static mock_srv_ctx *mock_srv_ctx_new(void)
+{
+ mock_srv_ctx *ctx = OPENSSL_zalloc(sizeof(mock_srv_ctx));
+
+ if (ctx == NULL)
+ goto err;
+
+ if ((ctx->statusOut = OSSL_CMP_PKISI_new()) == NULL)
+ goto err;
+
+ ctx->certReqId = -1;
+
+ /* all other elements are initialized to 0 or NULL, respectively */
+ return ctx;
+ err:
+ mock_srv_ctx_free(ctx);
+ return NULL;
+}
+
+int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (cert == NULL || X509_up_ref(cert)) {
+ X509_free(ctx->certOut);
+ ctx->certOut = cert;
+ return 1;
+ }
+ return 0;
+}
+
+int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *chain)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ STACK_OF(X509) *chain_copy = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL)
+ return 0;
+ sk_X509_pop_free(ctx->chainOut, X509_free);
+ ctx->chainOut = chain_copy;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ STACK_OF(X509) *caPubs)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ STACK_OF(X509) *caPubs_copy = NULL;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL)
+ return 0;
+ sk_X509_pop_free(ctx->caPubsOut, X509_free);
+ ctx->caPubsOut = caPubs_copy;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
+ int fail_info, const char *text)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ OSSL_CMP_PKISI *si;
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, text)) == NULL)
+ return 0;
+ OSSL_CMP_PKISI_free(ctx->statusOut);
+ ctx->statusOut = si;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->sendError = val != 0;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (count < 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+ ctx->pollCount = count;
+ return 1;
+}
+
+int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ ctx->checkAfterTime = sec;
+ return 1;
+}
+
+static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *cert_req,
+ int certReqId,
+ const OSSL_CRMF_MSG *crm,
+ const X509_REQ *p10cr,
+ X509 **certOut,
+ STACK_OF(X509) **chainOut,
+ STACK_OF(X509) **caPubs)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ OSSL_CMP_PKISI *si = NULL;
+
+ if (ctx == NULL || cert_req == NULL
+ || certOut == NULL || chainOut == NULL || caPubs == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ if (ctx->sendError) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return NULL;
+ }
+
+ *certOut = NULL;
+ *chainOut = NULL;
+ *caPubs = NULL;
+ ctx->certReqId = certReqId;
+
+ if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) {
+ /* start polling */
+ if (ctx->certReq != NULL) {
+ /* already in polling mode */
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return NULL;
+ }
+ if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL)
+ return NULL;
+ return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL);
+ }
+ if (ctx->curr_pollCount >= ctx->pollCount)
+ /* give final response after polling */
+ ctx->curr_pollCount = 0;
+
+ if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_KUR
+ && crm != NULL && ctx->certOut != NULL) {
+ const OSSL_CRMF_CERTID *cid = OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm);
+ const X509_NAME *issuer = X509_get_issuer_name(ctx->certOut);
+ const ASN1_INTEGER *serial = X509_get0_serialNumber(ctx->certOut);
+
+ if (cid == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID);
+ return NULL;
+ }
+ if (issuer != NULL
+ && X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID);
+ return NULL;
+ }
+ if (serial != NULL
+ && ASN1_INTEGER_cmp(serial,
+ OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID);
+ return NULL;
+ }
+ }
+
+ if (ctx->certOut != NULL
+ && (*certOut = X509_dup(ctx->certOut)) == NULL)
+ goto err;
+ if (ctx->chainOut != NULL
+ && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL)
+ goto err;
+ if (ctx->caPubsOut != NULL
+ && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL)
+ goto err;
+ if (ctx->statusOut != NULL
+ && (si = OSSL_CMP_PKISI_dup(ctx->statusOut)) == NULL)
+ goto err;
+ return si;
+
+ err:
+ X509_free(*certOut);
+ *certOut = NULL;
+ sk_X509_pop_free(*chainOut, X509_free);
+ *chainOut = NULL;
+ sk_X509_pop_free(*caPubs, X509_free);
+ *caPubs = NULL;
+ return NULL;
+}
+
+static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *rr,
+ const X509_NAME *issuer,
+ const ASN1_INTEGER *serial)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL || rr == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ if (ctx->sendError || ctx->certOut == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return NULL;
+ }
+
+ /* Allow any RR derived from CSR, which may include subject and serial */
+ if (issuer == NULL || serial == NULL)
+ return OSSL_CMP_PKISI_dup(ctx->statusOut);
+
+ /* accept revocation only for the certificate we sent in ir/cr/kur */
+ if (X509_NAME_cmp(issuer, X509_get_issuer_name(ctx->certOut)) != 0
+ || ASN1_INTEGER_cmp(serial,
+ X509_get0_serialNumber(ctx->certOut)) != 0) {
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED,
+ "wrong certificate to revoke");
+ return NULL;
+ }
+ return OSSL_CMP_PKISI_dup(ctx->statusOut);
+}
+
+static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *genm,
+ const STACK_OF(OSSL_CMP_ITAV) *in,
+ STACK_OF(OSSL_CMP_ITAV) **out)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL || genm == NULL || in == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (sk_OSSL_CMP_ITAV_num(in) > 1 || ctx->sendError) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return 0;
+ }
+
+ *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup,
+ OSSL_CMP_ITAV_free);
+ return *out != NULL;
+}
+
+static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error,
+ const OSSL_CMP_PKISI *statusInfo,
+ const ASN1_INTEGER *errorCode,
+ const OSSL_CMP_PKIFREETEXT *errorDetails)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+ char *sibuf;
+ int i;
+
+ if (ctx == NULL || error == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return;
+ }
+
+ BIO_printf(bio_err, "mock server received error:\n");
+
+ if (statusInfo == NULL) {
+ BIO_printf(bio_err, "pkiStatusInfo absent\n");
+ } else {
+ sibuf = OSSL_CMP_snprint_PKIStatusInfo(statusInfo, buf, sizeof(buf));
+ BIO_printf(bio_err, "pkiStatusInfo: %s\n",
+ sibuf != NULL ? sibuf: "<invalid>");
+ }
+
+ if (errorCode == NULL)
+ BIO_printf(bio_err, "errorCode absent\n");
+ else
+ BIO_printf(bio_err, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode));
+
+ if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) {
+ BIO_printf(bio_err, "errorDetails absent\n");
+ } else {
+ BIO_printf(bio_err, "errorDetails: ");
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) {
+ if (i > 0)
+ BIO_printf(bio_err, ", ");
+ BIO_printf(bio_err, "\"");
+ ASN1_STRING_print(bio_err,
+ sk_ASN1_UTF8STRING_value(errorDetails, i));
+ BIO_printf(bio_err, "\"");
+ }
+ BIO_printf(bio_err, "\n");
+ }
+}
+
+static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *certConf, int certReqId,
+ const ASN1_OCTET_STRING *certHash,
+ const OSSL_CMP_PKISI *si)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+ ASN1_OCTET_STRING *digest;
+
+ if (ctx == NULL || certConf == NULL || certHash == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ctx->sendError || ctx->certOut == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return 0;
+ }
+
+ if (certReqId != ctx->certReqId) {
+ /* in case of error, invalid reqId -1 */
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
+
+ if ((digest = X509_digest_sig(ctx->certOut, NULL, NULL)) == NULL)
+ return 0;
+ if (ASN1_OCTET_STRING_cmp(certHash, digest) != 0) {
+ ASN1_OCTET_STRING_free(digest);
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERTHASH_UNMATCHED);
+ return 0;
+ }
+ ASN1_OCTET_STRING_free(digest);
+ return 1;
+}
+
+static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *pollReq, int certReqId,
+ OSSL_CMP_MSG **certReq, int64_t *check_after)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL || pollReq == NULL
+ || certReq == NULL || check_after == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ctx->sendError) {
+ *certReq = NULL;
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ return 0;
+ }
+ if (ctx->certReq == NULL) {
+ /* not currently in polling mode */
+ *certReq = NULL;
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return 0;
+ }
+
+ if (++ctx->curr_pollCount >= ctx->pollCount) {
+ /* end polling */
+ *certReq = ctx->certReq;
+ ctx->certReq = NULL;
+ *check_after = 0;
+ } else {
+ *certReq = NULL;
+ *check_after = ctx->checkAfterTime;
+ }
+ return 1;
+}
+
+OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq)
+{
+ OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(libctx, propq);
+ mock_srv_ctx *ctx = mock_srv_ctx_new();
+
+ if (srv_ctx != NULL && ctx != NULL
+ && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request,
+ process_rr, process_genm, process_error,
+ process_certConf, process_pollReq))
+ return srv_ctx;
+
+ mock_srv_ctx_free(ctx);
+ OSSL_CMP_SRV_CTX_free(srv_ctx);
+ return NULL;
+}
+
+void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx)
+{
+ if (srv_ctx != NULL)
+ mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx));
+ OSSL_CMP_SRV_CTX_free(srv_ctx);
+}
diff --git a/apps/lib/columns.c b/apps/lib/columns.c
new file mode 100644
index 000000000000..aa58fe1781f5
--- /dev/null
+++ b/apps/lib/columns.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 "function.h"
+
+void calculate_columns(FUNCTION *functions, DISPLAY_COLUMNS *dc)
+{
+ FUNCTION *f;
+ int len, maxlen = 0;
+
+ 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;
+
+ dc->width = maxlen + 2;
+ dc->columns = (80 - 1) / dc->width;
+}
+
diff --git a/apps/lib/engine.c b/apps/lib/engine.c
new file mode 100644
index 000000000000..209c4b6b03c2
--- /dev/null
+++ b/apps/lib/engine.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/*
+ * Here is a set of wrappers for the ENGINE API, which are no-ops when the
+ * ENGINE API is disabled / removed.
+ * We need to suppress deprecation warnings to make this work.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <string.h> /* strcmp */
+
+#include <openssl/types.h> /* Ensure we have the ENGINE type, regardless */
+#include <openssl/err.h>
+#ifndef OPENSSL_NO_ENGINE
+# include <openssl/engine.h>
+#endif
+#include "apps.h"
+
+#ifndef OPENSSL_NO_ENGINE
+/* Try to load an engine in a shareable library */
+static ENGINE *try_load_engine(const char *engine)
+{
+ ENGINE *e = NULL;
+
+ if ((e = ENGINE_by_id("dynamic")) != NULL) {
+ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
+ || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
+ ENGINE_free(e);
+ e = NULL;
+ }
+ }
+ return e;
+}
+#endif
+
+ENGINE *setup_engine_methods(const char *id, unsigned int methods, int debug)
+{
+ ENGINE *e = NULL;
+
+#ifndef OPENSSL_NO_ENGINE
+ if (id != NULL) {
+ if (strcmp(id, "auto") == 0) {
+ BIO_printf(bio_err, "Enabling auto ENGINE support\n");
+ ENGINE_register_all_complete();
+ return NULL;
+ }
+ if ((e = ENGINE_by_id(id)) == NULL
+ && (e = try_load_engine(id)) == NULL) {
+ BIO_printf(bio_err, "Invalid engine \"%s\"\n", id);
+ ERR_print_errors(bio_err);
+ return NULL;
+ }
+ if (debug)
+ (void)ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0);
+ if (!ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0,
+ (void *)get_ui_method(), 0, 1)
+ || !ENGINE_set_default(e, methods)) {
+ BIO_printf(bio_err, "Cannot use engine \"%s\"\n", ENGINE_get_id(e));
+ ERR_print_errors(bio_err);
+ ENGINE_free(e);
+ return NULL;
+ }
+
+ BIO_printf(bio_err, "Engine \"%s\" set.\n", ENGINE_get_id(e));
+ }
+#endif
+ return e;
+}
+
+void release_engine(ENGINE *e)
+{
+#ifndef OPENSSL_NO_ENGINE
+ /* Free our "structural" reference. */
+ ENGINE_free(e);
+#endif
+}
+
+int init_engine(ENGINE *e)
+{
+ int rv = 1;
+
+#ifndef OPENSSL_NO_ENGINE
+ rv = ENGINE_init(e);
+#endif
+ return rv;
+}
+
+int finish_engine(ENGINE *e)
+{
+ int rv = 1;
+
+#ifndef OPENSSL_NO_ENGINE
+ rv = ENGINE_finish(e);
+#endif
+ return rv;
+}
+
+char *make_engine_uri(ENGINE *e, const char *key_id, const char *desc)
+{
+ char *new_uri = NULL;
+
+#ifndef OPENSSL_NO_ENGINE
+ if (e == NULL) {
+ BIO_printf(bio_err, "No engine specified for loading %s\n", desc);
+ } else if (key_id == NULL) {
+ BIO_printf(bio_err, "No engine key id specified for loading %s\n", desc);
+ } else {
+ const char *engineid = ENGINE_get_id(e);
+ size_t uri_sz =
+ sizeof(ENGINE_SCHEME_COLON) - 1
+ + strlen(engineid)
+ + 1 /* : */
+ + strlen(key_id)
+ + 1 /* \0 */
+ ;
+
+ new_uri = OPENSSL_malloc(uri_sz);
+ if (new_uri != NULL) {
+ OPENSSL_strlcpy(new_uri, ENGINE_SCHEME_COLON, uri_sz);
+ OPENSSL_strlcat(new_uri, engineid, uri_sz);
+ OPENSSL_strlcat(new_uri, ":", uri_sz);
+ OPENSSL_strlcat(new_uri, key_id, uri_sz);
+ }
+ }
+#else
+ BIO_printf(bio_err, "Engines not supported for loading %s\n", desc);
+#endif
+ return new_uri;
+}
+
+int get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ ENGINE *tmpeng = NULL;
+ int pkey_id = NID_undef;
+
+ ERR_set_mark();
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);
+
+#if !defined(OPENSSL_NO_ENGINE)
+ ENGINE_finish(tmpeng);
+
+ if (ameth == NULL && e != NULL)
+ ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1);
+ else
+#endif
+ /* We're only interested if it comes from an ENGINE */
+ if (tmpeng == NULL)
+ ameth = NULL;
+
+ ERR_pop_to_mark();
+ if (ameth == NULL)
+ return NID_undef;
+
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+
+ return pkey_id;
+}
+
+const EVP_MD *get_digest_from_engine(const char *name)
+{
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *eng;
+
+ eng = ENGINE_get_digest_engine(OBJ_sn2nid(name));
+ if (eng != NULL) {
+ ENGINE_finish(eng);
+ return EVP_get_digestbyname(name);
+ }
+#endif
+ return NULL;
+}
+
+const EVP_CIPHER *get_cipher_from_engine(const char *name)
+{
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *eng;
+
+ eng = ENGINE_get_cipher_engine(OBJ_sn2nid(name));
+ if (eng != NULL) {
+ ENGINE_finish(eng);
+ return EVP_get_cipherbyname(name);
+ }
+#endif
+ return NULL;
+}
diff --git a/apps/lib/engine_loader.c b/apps/lib/engine_loader.c
new file mode 100644
index 000000000000..42775a89f361
--- /dev/null
+++ b/apps/lib/engine_loader.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/*
+ * Here is an STORE loader for ENGINE backed keys. It relies on deprecated
+ * functions, and therefore need to have deprecation warnings suppressed.
+ * This file is not compiled at all in a '--api=3 no-deprecated' configuration.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include "apps.h"
+
+#ifndef OPENSSL_NO_ENGINE
+
+# include <stdarg.h>
+# include <string.h>
+# include <openssl/engine.h>
+# include <openssl/store.h>
+
+/*
+ * Support for legacy private engine keys via the 'org.openssl.engine:' scheme
+ *
+ * org.openssl.engine:{engineid}:{keyid}
+ *
+ * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key()
+ * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly
+ * this sort of purpose.
+ */
+
+/* Local definition of OSSL_STORE_LOADER_CTX */
+struct ossl_store_loader_ctx_st {
+ ENGINE *e; /* Structural reference */
+ char *keyid;
+ int expected;
+ int loaded; /* 0 = key not loaded yet, 1 = key loaded */
+};
+
+static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid)
+{
+ OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL) {
+ ctx->e = e;
+ ctx->keyid = keyid;
+ }
+ return ctx;
+}
+
+static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
+{
+ if (ctx != NULL) {
+ ENGINE_free(ctx->e);
+ OPENSSL_free(ctx->keyid);
+ OPENSSL_free(ctx);
+ }
+}
+
+static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,
+ const char *uri,
+ const UI_METHOD *ui_method,
+ void *ui_data)
+{
+ const char *p = uri, *q;
+ ENGINE *e = NULL;
+ char *keyid = NULL;
+ OSSL_STORE_LOADER_CTX *ctx = NULL;
+
+ if (OPENSSL_strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1)
+ != 0)
+ return NULL;
+ p += sizeof(ENGINE_SCHEME_COLON) - 1;
+
+ /* Look for engine ID */
+ q = strchr(p, ':');
+ if (q != NULL /* There is both an engine ID and a key ID */
+ && p[0] != ':' /* The engine ID is at least one character */
+ && q[1] != '\0') { /* The key ID is at least one character */
+ char engineid[256];
+ size_t engineid_l = q - p;
+
+ strncpy(engineid, p, engineid_l);
+ engineid[engineid_l] = '\0';
+ e = ENGINE_by_id(engineid);
+
+ keyid = OPENSSL_strdup(q + 1);
+ }
+
+ if (e != NULL && keyid != NULL)
+ ctx = OSSL_STORE_LOADER_CTX_new(e, keyid);
+
+ if (ctx == NULL) {
+ OPENSSL_free(keyid);
+ ENGINE_free(e);
+ }
+
+ return ctx;
+}
+
+static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
+{
+ if (expected == 0
+ || expected == OSSL_STORE_INFO_PUBKEY
+ || expected == OSSL_STORE_INFO_PKEY) {
+ ctx->expected = expected;
+ return 1;
+ }
+ return 0;
+}
+
+static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ EVP_PKEY *pkey = NULL, *pubkey = NULL;
+ OSSL_STORE_INFO *info = NULL;
+
+ if (ctx->loaded == 0) {
+ if (ENGINE_init(ctx->e)) {
+ if (ctx->expected == 0
+ || ctx->expected == OSSL_STORE_INFO_PKEY)
+ pkey =
+ ENGINE_load_private_key(ctx->e, ctx->keyid,
+ (UI_METHOD *)ui_method, ui_data);
+ if ((pkey == NULL && ctx->expected == 0)
+ || ctx->expected == OSSL_STORE_INFO_PUBKEY)
+ pubkey =
+ ENGINE_load_public_key(ctx->e, ctx->keyid,
+ (UI_METHOD *)ui_method, ui_data);
+ ENGINE_finish(ctx->e);
+ }
+ }
+
+ ctx->loaded = 1;
+
+ if (pubkey != NULL)
+ info = OSSL_STORE_INFO_new_PUBKEY(pubkey);
+ else if (pkey != NULL)
+ info = OSSL_STORE_INFO_new_PKEY(pkey);
+ if (info == NULL) {
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(pubkey);
+ }
+ return info;
+}
+
+static int engine_eof(OSSL_STORE_LOADER_CTX *ctx)
+{
+ return ctx->loaded != 0;
+}
+
+static int engine_error(OSSL_STORE_LOADER_CTX *ctx)
+{
+ return 0;
+}
+
+static int engine_close(OSSL_STORE_LOADER_CTX *ctx)
+{
+ OSSL_STORE_LOADER_CTX_free(ctx);
+ return 1;
+}
+
+int setup_engine_loader(void)
+{
+ OSSL_STORE_LOADER *loader = NULL;
+
+ if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL
+ || !OSSL_STORE_LOADER_set_open(loader, engine_open)
+ || !OSSL_STORE_LOADER_set_expect(loader, engine_expect)
+ || !OSSL_STORE_LOADER_set_load(loader, engine_load)
+ || !OSSL_STORE_LOADER_set_eof(loader, engine_eof)
+ || !OSSL_STORE_LOADER_set_error(loader, engine_error)
+ || !OSSL_STORE_LOADER_set_close(loader, engine_close)
+ || !OSSL_STORE_register_loader(loader)) {
+ OSSL_STORE_LOADER_free(loader);
+ loader = NULL;
+ }
+
+ return loader != NULL;
+}
+
+void destroy_engine_loader(void)
+{
+ OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME);
+ OSSL_STORE_LOADER_free(loader);
+}
+
+#else /* !OPENSSL_NO_ENGINE */
+
+int setup_engine_loader(void)
+{
+ return 0;
+}
+
+void destroy_engine_loader(void)
+{
+}
+
+#endif
diff --git a/apps/lib/fmt.c b/apps/lib/fmt.c
new file mode 100644
index 000000000000..af0e63b85b14
--- /dev/null
+++ b/apps/lib/fmt.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 "fmt.h"
+
+int FMT_istext(int format)
+{
+ return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT;
+}
diff --git a/apps/lib/http_server.c b/apps/lib/http_server.c
new file mode 100644
index 000000000000..a7fe5e1a58b0
--- /dev/null
+++ b/apps/lib/http_server.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/* Very basic HTTP server */
+
+#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
+/*
+ * On VMS, you need to define this to get the declaration of fileno(). The
+ * value 2 is to make sure no function defined in POSIX-2 is left undefined.
+ */
+# define _POSIX_C_SOURCE 2
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include "http_server.h"
+#include "internal/sockets.h"
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include "s_apps.h"
+
+#if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_fork)>
+# endif
+#endif
+
+static int verbosity = LOG_INFO;
+
+#define HTTP_PREFIX "HTTP/"
+#define HTTP_VERSION_PATT "1." /* allow 1.x */
+#define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT
+#define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */
+
+#ifdef HTTP_DAEMON
+
+int multi = 0; /* run multiple responder processes */
+int acfd = (int) INVALID_SOCKET;
+
+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;
+}
+#endif
+
+void log_message(const char *prog, int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (verbosity < level)
+ return;
+
+ va_start(ap, fmt);
+#ifdef HTTP_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);
+ } else
+#endif
+ {
+ BIO_printf(bio_err, "%s: ", prog);
+ BIO_vprintf(bio_err, fmt, ap);
+ BIO_printf(bio_err, "\n");
+ (void)BIO_flush(bio_err);
+ }
+ va_end(ap);
+}
+
+#ifdef HTTP_DAEMON
+void socket_timeout(int signum)
+{
+ if (acfd != (int)INVALID_SOCKET)
+ (void)shutdown(acfd, SHUT_RD);
+}
+
+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);
+ OPENSSL_free(kidpids);
+ ossl_sleep(1000);
+ exit(ret);
+}
+
+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.
+ */
+void spawn_loop(const char *prog)
+{
+ 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
+ "");
+ ossl_sleep(1000);
+ }
+ 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 */
+ ossl_sleep(30000);
+ break;
+ case 0: /* child */
+ OPENSSL_free(kidpids);
+ 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;
+ }
+ }
+
+ /* The loop above can only break on termsig */
+ syslog(LOG_INFO, "terminating on signal: %d", termsig);
+ killall(0, kidpids);
+}
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+BIO *http_server_init_bio(const char *prog, const char *port)
+{
+ BIO *acbio = NULL, *bufbio;
+ int asock;
+
+ bufbio = BIO_new(BIO_f_buffer());
+ if (bufbio == NULL)
+ goto err;
+ 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(prog, LOG_ERR, "Error setting up accept BIO");
+ goto err;
+ }
+
+ BIO_set_accept_bios(acbio, bufbio);
+ bufbio = NULL;
+ if (BIO_do_accept(acbio) <= 0) {
+ log_message(prog, LOG_ERR, "Error starting accept");
+ goto err;
+ }
+
+ /* Report back what address and port are used */
+ BIO_get_fd(acbio, &asock);
+ if (!report_server_accept(bio_out, asock, 1, 1)) {
+ log_message(prog, LOG_ERR, "Error printing ACCEPT string");
+ goto err;
+ }
+
+ return acbio;
+
+ err:
+ BIO_free_all(acbio);
+ BIO_free(bufbio);
+ return NULL;
+}
+
+/*
+ * Decode %xx URL-decoding in-place. Ignores malformed 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);
+}
+
+/* if *pcbio != NULL, continue given connected session, else accept new */
+/* if found_keep_alive != NULL, return this way connection persistence state */
+int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
+ char **ppath, BIO **pcbio, BIO *acbio,
+ int *found_keep_alive,
+ const char *prog, const char *port,
+ int accept_get, int timeout)
+{
+ BIO *cbio = *pcbio, *getbio = NULL, *b64 = NULL;
+ int len;
+ char reqbuf[2048], inbuf[2048];
+ char *meth, *url, *end;
+ ASN1_VALUE *req;
+ int ret = 0;
+
+ *preq = NULL;
+ if (ppath != NULL)
+ *ppath = NULL;
+
+ if (cbio == NULL) {
+ log_message(prog, LOG_DEBUG,
+ "Awaiting new connection on port %s...", port);
+ if (BIO_do_accept(acbio) <= 0)
+ /* Connection loss before accept() is routine, ignore silently */
+ return ret;
+
+ *pcbio = cbio = BIO_pop(acbio);
+ } else {
+ log_message(prog, LOG_DEBUG, "Awaiting next request...");
+ }
+ if (cbio == NULL) {
+ /* Cannot call http_server_send_status(cbio, ...) */
+ ret = -1;
+ goto out;
+ }
+
+# ifdef HTTP_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)
+ return ret;
+ ret = 1;
+ if (len < 0) {
+ log_message(prog, LOG_WARNING, "Request line read error");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ if ((end = strchr(reqbuf, '\r')) != NULL
+ || (end = strchr(reqbuf, '\n')) != NULL)
+ *end = '\0';
+ log_message(prog, LOG_INFO, "Received request, 1st line: %s", reqbuf);
+
+ meth = reqbuf;
+ url = meth + 3;
+ if ((accept_get && strncmp(meth, "GET ", 4) == 0)
+ || (url++, strncmp(meth, "POST ", 5) == 0)) {
+ static const char http_version_str[] = " "HTTP_PREFIX_VERSION;
+ static const size_t http_version_str_len = sizeof(http_version_str) - 1;
+
+ /* Expecting (GET|POST) {sp} /URL {sp} HTTP/1.x */
+ *(url++) = '\0';
+ while (*url == ' ')
+ url++;
+ if (*url != '/') {
+ log_message(prog, LOG_WARNING,
+ "Invalid %s -- URL does not begin with '/': %s",
+ meth, url);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ url++;
+
+ /* Splice off the HTTP version identifier. */
+ for (end = url; *end != '\0'; end++)
+ if (*end == ' ')
+ break;
+ if (strncmp(end, http_version_str, http_version_str_len) != 0) {
+ log_message(prog, LOG_WARNING,
+ "Invalid %s -- bad HTTP/version string: %s",
+ meth, end + 1);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ *end = '\0';
+ /* above HTTP 1.0, connection persistence is the default */
+ if (found_keep_alive != NULL)
+ *found_keep_alive = end[http_version_str_len] > '0';
+
+ /*-
+ * Skip "GET / HTTP..." requests often used by load-balancers.
+ * 'url' was incremented above to point to the first byte *after*
+ * the leading slash, so in case 'GET / ' it is now an empty string.
+ */
+ if (strlen(meth) == 3 && url[0] == '\0') {
+ (void)http_server_send_status(cbio, 200, "OK");
+ goto out;
+ }
+
+ len = urldecode(url);
+ if (len < 0) {
+ log_message(prog, LOG_WARNING,
+ "Invalid %s request -- bad URL encoding: %s",
+ meth, url);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ if (strlen(meth) == 3) { /* GET */
+ if ((getbio = BIO_new_mem_buf(url, len)) == NULL
+ || (b64 = BIO_new(BIO_f_base64())) == NULL) {
+ log_message(prog, LOG_ERR,
+ "Could not allocate base64 bio with size = %d",
+ len);
+ goto fatal;
+ }
+ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+ getbio = BIO_push(b64, getbio);
+ }
+ } else {
+ log_message(prog, LOG_WARNING,
+ "HTTP request does not begin with %sPOST: %s",
+ accept_get ? "GET or " : "", reqbuf);
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+
+ /* chop any further/duplicate leading or trailing '/' */
+ while (*url == '/')
+ url++;
+ while (end >= url + 2 && end[-2] == '/' && end[-1] == '/')
+ end--;
+ *end = '\0';
+
+ /* Read and skip past the headers. */
+ for (;;) {
+ char *key, *value, *line_end = NULL;
+
+ len = BIO_gets(cbio, inbuf, sizeof(inbuf));
+ if (len <= 0) {
+ log_message(prog, LOG_WARNING, "Error reading HTTP header");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+
+ if (inbuf[0] == '\r' || inbuf[0] == '\n')
+ break;
+
+ key = inbuf;
+ value = strchr(key, ':');
+ if (value == NULL) {
+ log_message(prog, LOG_WARNING,
+ "Error parsing HTTP header: missing ':'");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ *(value++) = '\0';
+ while (*value == ' ')
+ value++;
+ line_end = strchr(value, '\r');
+ if (line_end == NULL) {
+ line_end = strchr(value, '\n');
+ if (line_end == NULL) {
+ log_message(prog, LOG_WARNING,
+ "Error parsing HTTP header: missing end of line");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ goto out;
+ }
+ }
+ *line_end = '\0';
+ /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
+ if (found_keep_alive != NULL
+ && OPENSSL_strcasecmp(key, "Connection") == 0) {
+ if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
+ *found_keep_alive = 1;
+ else if (OPENSSL_strcasecmp(value, "close") == 0)
+ *found_keep_alive = 0;
+ }
+ }
+
+# ifdef HTTP_DAEMON
+ /* Clear alarm before we close the client socket */
+ alarm(0);
+ timeout = 0;
+# endif
+
+ /* Try to read and parse request */
+ req = ASN1_item_d2i_bio(it, getbio != NULL ? getbio : cbio, NULL);
+ if (req == NULL) {
+ log_message(prog, LOG_WARNING,
+ "Error parsing DER-encoded request content");
+ (void)http_server_send_status(cbio, 400, "Bad Request");
+ } else if (ppath != NULL && (*ppath = OPENSSL_strdup(url)) == NULL) {
+ log_message(prog, LOG_ERR,
+ "Out of memory allocating %zu bytes", strlen(url) + 1);
+ ASN1_item_free(req, it);
+ goto fatal;
+ }
+
+ *preq = req;
+
+ out:
+ BIO_free_all(getbio);
+# ifdef HTTP_DAEMON
+ if (timeout > 0)
+ alarm(0);
+ acfd = (int)INVALID_SOCKET;
+# endif
+ return ret;
+
+ fatal:
+ (void)http_server_send_status(cbio, 500, "Internal Server Error");
+ if (ppath != NULL) {
+ OPENSSL_free(*ppath);
+ *ppath = NULL;
+ }
+ BIO_free_all(cbio);
+ *pcbio = NULL;
+ ret = -1;
+ goto out;
+}
+
+/* assumes that cbio does not do an encoding that changes the output length */
+int http_server_send_asn1_resp(BIO *cbio, int keep_alive,
+ const char *content_type,
+ const ASN1_ITEM *it, const ASN1_VALUE *resp)
+{
+ int ret = BIO_printf(cbio, HTTP_1_0" 200 OK\r\n%s"
+ "Content-type: %s\r\n"
+ "Content-Length: %d\r\n\r\n",
+ keep_alive ? "Connection: keep-alive\r\n" : "",
+ content_type,
+ ASN1_item_i2d(resp, NULL, it)) > 0
+ && ASN1_item_i2d_bio(it, cbio, resp) > 0;
+
+ (void)BIO_flush(cbio);
+ return ret;
+}
+
+int http_server_send_status(BIO *cbio, int status, const char *reason)
+{
+ int ret = BIO_printf(cbio, HTTP_1_0" %d %s\r\n\r\n",
+ /* This implicitly cancels keep-alive */
+ status, reason) > 0;
+
+ (void)BIO_flush(cbio);
+ return ret;
+}
+#endif
diff --git a/apps/lib/names.c b/apps/lib/names.c
new file mode 100644
index 000000000000..4788ae84b915
--- /dev/null
+++ b/apps/lib/names.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 <openssl/bio.h>
+#include <openssl/safestack.h>
+#include "names.h"
+#include "openssl/crypto.h"
+
+int name_cmp(const char * const *a, const char * const *b)
+{
+ return OPENSSL_strcasecmp(*a, *b);
+}
+
+void collect_names(const char *name, void *vdata)
+{
+ STACK_OF(OPENSSL_CSTRING) *names = vdata;
+
+ sk_OPENSSL_CSTRING_push(names, name);
+}
+
+void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names)
+{
+ int i = sk_OPENSSL_CSTRING_num(names);
+ int j;
+
+ sk_OPENSSL_CSTRING_sort(names);
+ if (i > 1)
+ BIO_printf(out, "{ ");
+ for (j = 0; j < i; j++) {
+ const char *name = sk_OPENSSL_CSTRING_value(names, j);
+
+ if (j > 0)
+ BIO_printf(out, ", ");
+ BIO_printf(out, "%s", name);
+ }
+ if (i > 1)
+ BIO_printf(out, " }");
+}
diff --git a/apps/opt.c b/apps/lib/opt.c
index 666856535d5e..157367982d2f 100644
--- a/apps/opt.c
+++ b/apps/lib/opt.c
@@ -1,27 +1,38 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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"
+
+/*
+ * This file is also used by the test suite. Do not #include "apps.h".
+ */
+#include "opt.h"
+#include "fmt.h"
+#include "app_libctx.h"
+#include "internal/nelem.h"
+#include "internal/numbers.h"
#include <string.h>
#if !defined(OPENSSL_SYS_MSDOS)
-# include OPENSSL_UNISTD
+# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
+#include <openssl/err.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[] = "---";
+const char OPT_HELP_STR[] = "-H";
+const char OPT_MORE_STR[] = "-M";
+const char OPT_SECTION_STR[] = "-S";
+const char OPT_PARAM_STR[] = "-P";
/* Our state */
static char **argv;
@@ -38,18 +49,27 @@ 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)
+
+const char *opt_path_end(const char *filename)
{
- size_t i, n;
const char *p;
- char *q;
/* find the last '/', '\' or ':' */
- for (p = argv0 + strlen(argv0); --p > argv0;)
+ for (p = filename + strlen(filename); --p > filename; )
if (*p == '/' || *p == '\\' || *p == ':') {
p++;
break;
}
+ return p;
+}
+
+char *opt_progname(const char *argv0)
+{
+ size_t i, n;
+ const char *p;
+ char *q;
+
+ p = opt_path_end(argv0);
/* Strip off trailing nonsense. */
n = strlen(p);
@@ -68,19 +88,28 @@ char *opt_progname(const char *argv0)
#elif defined(OPENSSL_SYS_VMS)
-char *opt_progname(const char *argv0)
+const char *opt_path_end(const char *filename)
{
- const char *p, *q;
+ const char *p;
/* Find last special character sys:[foo.bar]openssl */
- for (p = argv0 + strlen(argv0); --p > argv0;)
+ for (p = filename + strlen(filename); --p > filename;)
if (*p == ':' || *p == ']' || *p == '>') {
p++;
break;
}
+ return p;
+}
+char *opt_progname(const char *argv0)
+{
+ const char *p, *q;
+
+ /* Find last special character sys:[foo.bar]openssl */
+ p = opt_path_end(argv0);
q = strrchr(p, '.');
- strncpy(prog, p, sizeof(prog) - 1);
+ if (prog != p)
+ strncpy(prog, p, sizeof(prog) - 1);
prog[sizeof(prog) - 1] = '\0';
if (q != NULL && q - p < sizeof(prog))
prog[q - p] = '\0';
@@ -89,22 +118,40 @@ char *opt_progname(const char *argv0)
#else
-char *opt_progname(const char *argv0)
+const char *opt_path_end(const char *filename)
{
const char *p;
/* Could use strchr, but this is like the ones above. */
- for (p = argv0 + strlen(argv0); --p > argv0;)
+ for (p = filename + strlen(filename); --p > filename;)
if (*p == '/') {
p++;
break;
}
- strncpy(prog, p, sizeof(prog) - 1);
+ return p;
+}
+
+char *opt_progname(const char *argv0)
+{
+ const char *p;
+
+ p = opt_path_end(argv0);
+ if (prog != p)
+ strncpy(prog, p, sizeof(prog) - 1);
prog[sizeof(prog) - 1] = '\0';
return prog;
}
#endif
+char *opt_appname(const char *argv0)
+{
+ size_t len = strlen(prog);
+
+ if (argv0 != NULL)
+ BIO_snprintf(prog + len, sizeof(prog) - len - 1, " %s", argv0);
+ return prog;
+}
+
char *opt_getprog(void)
{
return prog;
@@ -116,32 +163,41 @@ char *opt_init(int ac, char **av, const OPTIONS *o)
/* Store state. */
argc = ac;
argv = av;
- opt_index = 1;
+ opt_begin();
opts = o;
- opt_progname(av[0]);
unknown = NULL;
- for (; o->name; ++o) {
+ /* Make sure prog name is set for usage output */
+ (void)opt_progname(argv[0]);
+
+ /* Check all options up until the PARAM marker (if present) */
+ for (; o->name != NULL && o->name != OPT_PARAM_STR; ++o) {
#ifndef NDEBUG
const OPTIONS *next;
int duplicated, i;
#endif
- if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR)
+ if (o->name == OPT_HELP_STR
+ || o->name == OPT_MORE_STR
+ || o->name == OPT_SECTION_STR)
continue;
#ifndef NDEBUG
i = o->valtype;
/* Make sure options are legit. */
- assert(o->name[0] != '-');
- assert(o->retval > 0);
+ OPENSSL_assert(o->name[0] != '-');
+ if (o->valtype == '.')
+ OPENSSL_assert(o->retval == OPT_PARAM);
+ else
+ OPENSSL_assert(o->retval == OPT_DUP || o->retval > OPT_PARAM);
switch (i) {
- case 0: case '-': case '/': case '<': case '>': case 'E': case 'F':
+ case 0: case '-': 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':
+ case 'u': case 'c': case ':': case 'N':
break;
default:
- assert(0);
+ OPENSSL_assert(0);
}
/* Make sure there are no duplicates. */
@@ -149,14 +205,19 @@ char *opt_init(int ac, char **av, const OPTIONS *o)
/*
* Some compilers inline strcmp and the assert string is too long.
*/
- duplicated = strcmp(o->name, next->name) == 0;
- assert(!duplicated);
+ duplicated = next->retval != OPT_DUP
+ && strcmp(o->name, next->name) == 0;
+ if (duplicated) {
+ opt_printf_stderr("%s: Internal error: duplicate option %s\n",
+ prog, o->name);
+ OPENSSL_assert(!duplicated);
+ }
}
#endif
if (o->name[0] == '\0') {
- assert(unknown == NULL);
+ OPENSSL_assert(unknown == NULL);
unknown = o;
- assert(unknown->valtype == 0 || unknown->valtype == '-');
+ OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-');
}
}
return prog;
@@ -176,19 +237,19 @@ static OPT_PAIR formats[] = {
};
/* Print an error message about a failed format parse. */
-int opt_format_error(const char *s, unsigned long flags)
+static 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);
+ opt_printf_stderr("%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);
+ opt_printf_stderr("%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);
+ opt_printf_stderr(" %s\n", ap->name);
}
return 0;
}
@@ -198,6 +259,7 @@ int opt_format(const char *s, unsigned long flags, int *result)
{
switch (*s) {
default:
+ opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s);
return 0;
case 'D':
case 'd':
@@ -264,6 +326,7 @@ int opt_format(const char *s, unsigned long flags, int *result)
return opt_format_error(s, flags);
*result = FORMAT_PKCS12;
} else {
+ opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s);
return 0;
}
break;
@@ -271,28 +334,132 @@ int opt_format(const char *s, unsigned long flags, int *result)
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)
+/* Return string representing the given format. */
+static const char *format2str(int format)
+{
+ switch (format) {
+ default:
+ return "(undefined)";
+ case FORMAT_PEM:
+ return "PEM";
+ case FORMAT_ASN1:
+ return "DER";
+ case FORMAT_TEXT:
+ return "TEXT";
+ case FORMAT_NSS:
+ return "NSS";
+ case FORMAT_SMIME:
+ return "SMIME";
+ case FORMAT_MSBLOB:
+ return "MSBLOB";
+ case FORMAT_ENGINE:
+ return "ENGINE";
+ case FORMAT_HTTP:
+ return "HTTP";
+ case FORMAT_PKCS12:
+ return "P12";
+ case FORMAT_PVK:
+ return "PVK";
+ }
+}
+
+/* Print an error message about unsuitable/unsupported format requested. */
+void print_format_error(int format, unsigned long flags)
{
- *cipherp = EVP_get_cipherbyname(name);
- if (*cipherp != NULL)
+ (void)opt_format_error(format2str(format), flags);
+}
+
+/*
+ * Parse a cipher name, put it in *cipherp after freeing what was there, if
+ * cipherp is not NULL. Return 0 on failure, else 1.
+ */
+int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp)
+{
+ EVP_CIPHER *c;
+
+ ERR_set_mark();
+ if ((c = EVP_CIPHER_fetch(app_get0_libctx(), name,
+ app_get0_propq())) != NULL
+ || (opt_legacy_okay()
+ && (c = (EVP_CIPHER *)EVP_get_cipherbyname(name)) != NULL)) {
+ ERR_pop_to_mark();
+ if (cipherp != NULL) {
+ EVP_CIPHER_free(*cipherp);
+ *cipherp = c;
+ } else {
+ EVP_CIPHER_free(c);
+ }
return 1;
- BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
+ }
+ ERR_clear_last_mark();
return 0;
}
+int opt_cipher_any(const char *name, EVP_CIPHER **cipherp)
+{
+ int ret;
+
+ if ((ret = opt_cipher_silent(name, cipherp)) == 0)
+ opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name);
+ return ret;
+}
+
+int opt_cipher(const char *name, EVP_CIPHER **cipherp)
+{
+ int mode, ret = 0;
+ unsigned long int flags;
+ EVP_CIPHER *c = NULL;
+
+ if (opt_cipher_any(name, &c)) {
+ mode = EVP_CIPHER_get_mode(c);
+ flags = EVP_CIPHER_get_flags(c);
+ if (mode == EVP_CIPH_XTS_MODE) {
+ opt_printf_stderr("%s XTS ciphers not supported\n", prog);
+ } else if ((flags & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
+ opt_printf_stderr("%s: AEAD ciphers not supported\n", prog);
+ } else {
+ ret = 1;
+ if (cipherp != NULL)
+ *cipherp = c;
+ }
+ }
+ return ret;
+}
+
/*
* 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)
+int opt_md_silent(const char *name, EVP_MD **mdp)
{
- *mdp = EVP_get_digestbyname(name);
- if (*mdp != NULL)
+ EVP_MD *md;
+
+ ERR_set_mark();
+ if ((md = EVP_MD_fetch(app_get0_libctx(), name, app_get0_propq())) != NULL
+ || (opt_legacy_okay()
+ && (md = (EVP_MD *)EVP_get_digestbyname(name)) != NULL)) {
+ ERR_pop_to_mark();
+ if (mdp != NULL) {
+ EVP_MD_free(*mdp);
+ *mdp = md;
+ } else {
+ EVP_MD_free(md);
+ }
return 1;
- BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
+ }
+ ERR_clear_last_mark();
return 0;
}
+int opt_md(const char *name, EVP_MD **mdp)
+{
+ int ret;
+
+ if ((ret = opt_md_silent(name, mdp)) == 0)
+ opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog,
+ name != NULL ? name : "\"\"");
+ return ret;
+}
+
/* Look through a list of name/value pairs. */
int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
{
@@ -303,9 +470,23 @@ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
*result = pp->retval;
return 1;
}
- BIO_printf(bio_err, "%s: Value must be one of:\n", prog);
+ opt_printf_stderr("%s: Value must be one of:\n", prog);
for (pp = pairs; pp->name; pp++)
- BIO_printf(bio_err, "\t%s\n", pp->name);
+ opt_printf_stderr("\t%s\n", pp->name);
+ return 0;
+}
+
+/* Look through a list of valid names */
+int opt_string(const char *name, const char **options)
+{
+ const char **p;
+
+ for (p = options; *p != NULL; p++)
+ if (strcmp(*p, name) == 0)
+ return 1;
+ opt_printf_stderr("%s: Value must be one of:\n", prog);
+ for (p = options; *p != NULL; p++)
+ opt_printf_stderr("\t%s\n", *p);
return 0;
}
@@ -318,13 +499,22 @@ int opt_int(const char *value, int *result)
return 0;
*result = (int)l;
if (*result != l) {
- BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n",
- prog, value);
+ opt_printf_stderr("%s: Value \"%s\" outside integer range\n",
+ prog, value);
return 0;
}
return 1;
}
+/* Parse and return an integer, assuming range has been checked before. */
+int opt_int_arg(void)
+{
+ int result = -1;
+
+ (void)opt_int(arg, &result);
+ return result;
+}
+
static void opt_number_error(const char *v)
{
size_t i = 0;
@@ -339,13 +529,12 @@ static void opt_number_error(const char *v)
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);
+ opt_printf_stderr("%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);
+ opt_printf_stderr("%s: Can't parse \"%s\" as a number\n", prog, v);
return;
}
@@ -372,10 +561,11 @@ int opt_long(const char *value, long *result)
}
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
- defined(INTMAX_MAX) && defined(UINTMAX_MAX)
+ defined(INTMAX_MAX) && defined(UINTMAX_MAX) && \
+ !defined(OPENSSL_NO_INTTYPES_H)
/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */
-int opt_imax(const char *value, intmax_t *result)
+int opt_intmax(const char *value, ossl_intmax_t *result)
{
int oerrno = errno;
intmax_t m;
@@ -385,19 +575,26 @@ int opt_imax(const char *value, intmax_t *result)
m = strtoimax(value, &endp, 0);
if (*endp
|| endp == value
- || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE)
+ || ((m == INTMAX_MAX || m == INTMAX_MIN)
+ && errno == ERANGE)
|| (m == 0 && errno != 0)) {
opt_number_error(value);
errno = oerrno;
return 0;
}
- *result = m;
+ /* Ensure that the value in |m| is never too big for |*result| */
+ if (sizeof(m) > sizeof(*result)
+ && (m < OSSL_INTMAX_MIN || m > OSSL_INTMAX_MAX)) {
+ opt_number_error(value);
+ return 0;
+ }
+ *result = (ossl_intmax_t)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 opt_uintmax(const char *value, ossl_uintmax_t *result)
{
int oerrno = errno;
uintmax_t m;
@@ -413,10 +610,37 @@ int opt_umax(const char *value, uintmax_t *result)
errno = oerrno;
return 0;
}
- *result = m;
+ /* Ensure that the value in |m| is never too big for |*result| */
+ if (sizeof(m) > sizeof(*result)
+ && m > OSSL_UINTMAX_MAX) {
+ opt_number_error(value);
+ return 0;
+ }
+ *result = (ossl_intmax_t)m;
errno = oerrno;
return 1;
}
+#else
+/* Fallback implementations based on long */
+int opt_intmax(const char *value, ossl_intmax_t *result)
+{
+ long m;
+ int ret;
+
+ if ((ret = opt_long(value, &m)))
+ *result = m;
+ return ret;
+}
+
+int opt_uintmax(const char *value, ossl_uintmax_t *result)
+{
+ unsigned long m;
+ int ret;
+
+ if ((ret = opt_ulong(value, &m)))
+ *result = m;
+ return ret;
+}
#endif
/*
@@ -458,9 +682,9 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
X509_PURPOSE *xptmp;
const X509_VERIFY_PARAM *vtmp;
- assert(vpm != NULL);
- assert(opt > OPT_V__FIRST);
- assert(opt < OPT_V__LAST);
+ OPENSSL_assert(vpm != NULL);
+ OPENSSL_assert(opt > OPT_V__FIRST);
+ OPENSSL_assert(opt < OPT_V__LAST);
switch ((enum range)opt) {
case OPT_V__FIRST:
@@ -469,7 +693,7 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
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());
+ opt_printf_stderr("%s: Invalid Policy %s\n", prog, opt_arg());
return 0;
}
X509_VERIFY_PARAM_add0_policy(vpm, otmp);
@@ -478,7 +702,7 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
/* 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());
+ opt_printf_stderr("%s: Invalid purpose %s\n", prog, opt_arg());
return 0;
}
@@ -489,17 +713,16 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
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());
+ opt_printf_stderr("%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());
+ opt_printf_stderr("%s: Invalid verify name %s\n",
+ prog, opt_arg());
return 0;
}
X509_VERIFY_PARAM_set1(vpm, vtmp);
@@ -515,11 +738,11 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
X509_VERIFY_PARAM_set_auth_level(vpm, i);
break;
case OPT_V_ATTIME:
- if (!opt_imax(opt_arg(), &t))
+ if (!opt_intmax(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());
+ opt_printf_stderr("%s: epoch time out of range %s\n",
+ prog, opt_arg());
return 0;
}
X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
@@ -606,6 +829,13 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
}
+void opt_begin(void)
+{
+ opt_index = 1;
+ arg = NULL;
+ flag = NULL;
+}
+
/*
* Parse the next flag (and value if specified), return 0 if done, -1 on
* error, otherwise the flag's retval.
@@ -645,14 +875,15 @@ int opt_next(void)
*arg++ = '\0';
for (o = opts; o->name; ++o) {
/* If not this option, move on to the next one. */
- if (strcmp(p, o->name) != 0)
+ if (!(strcmp(p, "h") == 0 && strcmp(o->name, "help") == 0)
+ && 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);
+ opt_printf_stderr("%s: Option -%s does not take a value\n",
+ prog, p);
return -1;
}
return o->retval;
@@ -661,8 +892,8 @@ int opt_next(void)
/* 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);
+ opt_printf_stderr("%s: Option -%s needs a value\n",
+ prog, o->name);
return -1;
}
arg = argv[opt_index++];
@@ -672,12 +903,16 @@ int opt_next(void)
switch (o->valtype) {
default:
case 's':
+ case ':':
/* Just a string. */
break;
+ case '.':
+ /* Parameters */
+ break;
case '/':
- if (app_isdir(arg) > 0)
+ if (opt_isdir(arg) > 0)
break;
- BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg);
+ opt_printf_stderr("%s: Not a directory: %s\n", prog, arg);
return -1;
case '<':
/* Input file. */
@@ -687,45 +922,35 @@ int opt_next(void)
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);
+ case 'N':
+ if (!opt_int(arg, &ival))
+ return -1;
+ if (o->valtype == 'p' && ival <= 0) {
+ opt_printf_stderr("%s: Non-positive number \"%s\" for option -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ if (o->valtype == 'N' && ival < 0) {
+ opt_printf_stderr("%s: Negative number \"%s\" for option -%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);
+ if (!opt_intmax(arg, &imval))
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);
+ if (!opt_uintmax(arg, &umval))
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);
+ if (!opt_long(arg, &lval))
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);
+ if (!opt_ulong(arg, &ulval))
return -1;
- }
break;
case 'c':
case 'E':
@@ -737,9 +962,8 @@ int opt_next(void)
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);
+ opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n",
+ prog, arg, o->name);
return -1;
}
@@ -750,7 +974,7 @@ int opt_next(void)
dunno = p;
return unknown->retval;
}
- BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p);
+ opt_printf_stderr("%s: Unknown option: -%s\n", prog, p);
return -1;
}
@@ -760,7 +984,7 @@ char *opt_arg(void)
return arg;
}
-/* Return the most recent flag. */
+/* Return the most recent flag (option name including the preceding '-'). */
char *opt_flag(void)
{
return flag;
@@ -796,6 +1020,8 @@ static const char *valtype2param(const OPTIONS *o)
case 0:
case '-':
return "";
+ case ':':
+ return "uri";
case 's':
return "val";
case '/':
@@ -820,47 +1046,33 @@ static const char *valtype2param(const OPTIONS *o)
return "format";
case 'M':
return "intmax";
+ case 'N':
+ return "nonneg";
case 'U':
return "uintmax";
}
return "parm";
}
-void opt_help(const OPTIONS *list)
+static void opt_print(const OPTIONS *o, int doingparams, int width)
{
- const OPTIONS *o;
- int i;
- int standard_prolog;
- int width = 5;
+ const char* help;
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;
+ opt_printf_stderr(help, prog);
+ return;
+ }
+ if (o->name == OPT_SECTION_STR) {
+ opt_printf_stderr("\n");
+ opt_printf_stderr(help, prog);
+ return;
+ }
+ if (o->name == OPT_PARAM_STR) {
+ opt_printf_stderr("\nParameters:\n");
+ return;
}
/* Pad out prefix */
@@ -870,14 +1082,15 @@ void opt_help(const OPTIONS *list)
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;
+ opt_printf_stderr("%s %s\n", start, help);
+ return;
}
/* Build up the "-flag [param]" part. */
p = start;
*p++ = ' ';
- *p++ = '-';
+ if (!doingparams)
+ *p++ = '-';
if (o->name[0])
p += strlen(strcpy(p, o->name));
else
@@ -889,10 +1102,97 @@ void opt_help(const OPTIONS *list)
*p = ' ';
if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
*p = '\0';
- BIO_printf(bio_err, "%s\n", start);
+ opt_printf_stderr("%s\n", start);
memset(start, ' ', sizeof(start));
}
start[width] = '\0';
- BIO_printf(bio_err, "%s %s\n", start, help);
+ opt_printf_stderr("%s %s\n", start, help);
+}
+
+void opt_help(const OPTIONS *list)
+{
+ const OPTIONS *o;
+ int i, sawparams = 0, width = 5;
+ int standard_prolog;
+ char start[80 + 1];
+
+ /* 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;
+ OPENSSL_assert(i < (int)sizeof(start));
+ }
+
+ if (standard_prolog) {
+ opt_printf_stderr("Usage: %s [options]\n", prog);
+ if (list[0].name != OPT_SECTION_STR)
+ opt_printf_stderr("Valid options are:\n", prog);
}
+
+ /* Now let's print. */
+ for (o = list; o->name; o++) {
+ if (o->name == OPT_PARAM_STR)
+ sawparams = 1;
+ opt_print(o, sawparams, width);
+ }
+}
+
+/* opt_isdir section */
+#ifdef _WIN32
+# include <windows.h>
+int opt_isdir(const char *name)
+{
+ DWORD attr;
+# if defined(UNICODE) || defined(_UNICODE)
+ size_t i, len_0 = strlen(name) + 1;
+ WCHAR tempname[MAX_PATH];
+
+ if (len_0 > MAX_PATH)
+ return -1;
+
+# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH))
+# endif
+ for (i = 0; i < len_0; i++)
+ tempname[i] = (WCHAR)name[i];
+
+ attr = GetFileAttributes(tempname);
+# else
+ attr = GetFileAttributes(name);
+# endif
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ return -1;
+ return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
}
+#else
+# include <sys/stat.h>
+# ifndef S_ISDIR
+# if defined(_S_IFMT) && defined(_S_IFDIR)
+# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR)
+# else
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+# endif
+# endif
+
+int opt_isdir(const char *name)
+{
+# if defined(S_ISDIR)
+ struct stat st;
+
+ if (stat(name, &st) == 0)
+ return S_ISDIR(st.st_mode);
+ else
+ return -1;
+# else
+ return -1;
+# endif
+}
+#endif
diff --git a/apps/s_cb.c b/apps/lib/s_cb.c
index 2f94c13393a5..f2ddd94c3de4 100644
--- a/apps/s_cb.c
+++ b/apps/lib/s_cb.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -12,6 +12,8 @@
#include <stdlib.h>
#include <string.h> /* for memcpy() and strcmp() */
#include "apps.h"
+#include <openssl/core_names.h>
+#include <openssl/params.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
@@ -150,6 +152,7 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
STACK_OF(X509) *chain, int build_chain)
{
int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0;
+
if (cert == NULL)
return 1;
if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
@@ -194,7 +197,7 @@ static STRINT_PAIR cert_type_list[] = {
{"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH},
{"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH},
{"GOST01 Sign", TLS_CT_GOST01_SIGN},
- {"GOST12 Sign", TLS_CT_GOST12_SIGN},
+ {"GOST12 Sign", TLS_CT_GOST12_IANA_SIGN},
{NULL}
};
@@ -203,6 +206,7 @@ static void ssl_print_client_cert_types(BIO *bio, SSL *s)
const unsigned char *p;
int i;
int cert_type_num = SSL_get0_certificate_types(s, &p);
+
if (!cert_type_num)
return;
BIO_puts(bio, "Client Certificate Types: ");
@@ -232,22 +236,22 @@ static const char *get_sigtype(int nid)
case EVP_PKEY_DSA:
return "DSA";
- case EVP_PKEY_EC:
+ case EVP_PKEY_EC:
return "ECDSA";
- case NID_ED25519:
+ case NID_ED25519:
return "Ed25519";
- case NID_ED448:
+ case NID_ED448:
return "Ed448";
- case NID_id_GostR3410_2001:
+ case NID_id_GostR3410_2001:
return "gost2001";
- case NID_id_GostR3410_2012_256:
+ case NID_id_GostR3410_2012_256:
return "gost2012_256";
- case NID_id_GostR3410_2012_512:
+ case NID_id_GostR3410_2012_512:
return "gost2012_512";
default:
@@ -258,6 +262,7 @@ static const char *get_sigtype(int nid)
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, 0, NULL, NULL, NULL, NULL, NULL);
@@ -300,6 +305,7 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared)
int ssl_print_sigalgs(BIO *out, SSL *s)
{
int nid;
+
if (!SSL_is_server(s))
ssl_print_client_cert_types(out, s);
do_print_sigalgs(out, s, 0);
@@ -316,6 +322,7 @@ int ssl_print_point_formats(BIO *out, SSL *s)
{
int i, nformats;
const char *pformats;
+
nformats = SSL_get0_ec_point_formats(s, &pformats);
if (nformats <= 0)
return 1;
@@ -349,7 +356,6 @@ int ssl_print_point_formats(BIO *out, SSL *s)
int ssl_print_groups(BIO *out, SSL *s, int noshared)
{
int i, ngroups, *groups, nid;
- const char *gname;
ngroups = SSL_get1_groups(s, NULL);
if (ngroups <= 0)
@@ -357,39 +363,25 @@ int ssl_print_groups(BIO *out, SSL *s, int noshared)
groups = app_malloc(ngroups * sizeof(int), "groups to print");
SSL_get1_groups(s, groups);
- BIO_puts(out, "Supported Elliptic Groups: ");
+ BIO_puts(out, "Supported groups: ");
for (i = 0; i < ngroups; i++) {
if (i)
BIO_puts(out, ":");
nid = groups[i];
- /* If unrecognised print out hex version */
- if (nid & TLSEXT_nid_unknown) {
- BIO_printf(out, "0x%04X", nid & 0xFFFF);
- } else {
- /* TODO(TLS1.3): Get group name here */
- /* Use NIST name for curve if it exists */
- gname = EC_curve_nid2nist(nid);
- if (gname == NULL)
- gname = OBJ_nid2sn(nid);
- BIO_printf(out, "%s", gname);
- }
+ BIO_printf(out, "%s", SSL_group_to_name(s, nid));
}
OPENSSL_free(groups);
if (noshared) {
BIO_puts(out, "\n");
return 1;
}
- BIO_puts(out, "\nShared Elliptic groups: ");
+ BIO_puts(out, "\nShared groups: ");
ngroups = SSL_get_shared_group(s, -1);
for (i = 0; i < ngroups; i++) {
if (i)
BIO_puts(out, ":");
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);
+ BIO_printf(out, "%s", SSL_group_to_name(s, nid));
}
if (ngroups == 0)
BIO_puts(out, "NONE");
@@ -405,39 +397,37 @@ int ssl_print_tmp_key(BIO *out, SSL *s)
if (!SSL_get_peer_tmp_key(s, &key))
return 1;
BIO_puts(out, "Server Temp Key: ");
- switch (EVP_PKEY_id(key)) {
+ switch (EVP_PKEY_get_id(key)) {
case EVP_PKEY_RSA:
- BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key));
+ BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_get_bits(key));
break;
case EVP_PKEY_DH:
- BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key));
+ BIO_printf(out, "DH, %d bits\n", EVP_PKEY_get_bits(key));
break;
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
{
- EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
- int nid;
- const char *cname;
- nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
- EC_KEY_free(ec);
- cname = EC_curve_nid2nist(nid);
- if (cname == NULL)
- cname = OBJ_nid2sn(nid);
- BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key));
+ char name[80];
+ size_t name_len;
+
+ if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME,
+ name, sizeof(name), &name_len))
+ strcpy(name, "?");
+ BIO_printf(out, "ECDH, %s, %d bits\n", name, EVP_PKEY_get_bits(key));
}
break;
#endif
default:
- BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)),
- EVP_PKEY_bits(key));
+ BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_get_id(key)),
+ EVP_PKEY_get_bits(key));
}
EVP_PKEY_free(key);
return 1;
}
-long 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, size_t len,
+ int argi, long argl, int ret, size_t *processed)
{
BIO *out;
@@ -446,14 +436,23 @@ long bio_dump_callback(BIO *bio, int cmd, const char *argp,
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;
+ if (ret > 0 && processed != NULL) {
+ BIO_printf(out, "read from %p [%p] (%zu bytes => %zu (0x%zX))\n",
+ (void *)bio, (void *)argp, len, *processed, *processed);
+ BIO_dump(out, argp, (int)*processed);
+ } else {
+ BIO_printf(out, "read from %p [%p] (%zu bytes => %d)\n",
+ (void *)bio, (void *)argp, len, 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);
+ if (ret > 0 && processed != NULL) {
+ BIO_printf(out, "write to %p [%p] (%zu bytes => %zu (0x%zX))\n",
+ (void *)bio, (void *)argp, len, *processed, *processed);
+ BIO_dump(out, argp, (int)*processed);
+ } else {
+ BIO_printf(out, "write to %p [%p] (%zu bytes => %d)\n",
+ (void *)bio, (void *)argp, len, ret);
+ }
}
return ret;
}
@@ -569,8 +568,8 @@ void msg_cb(int write_p, int version, int content_type, const void *buf,
{
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 = "";
+ char tmpbuf[128];
+ const char *str_version, *str_content_type = "", *str_details1 = "", *str_details2 = "";
const unsigned char* bp = buf;
if (version == SSL3_VERSION ||
@@ -579,11 +578,14 @@ void msg_cb(int write_p, int version, int content_type, const void *buf,
version == TLS1_2_VERSION ||
version == TLS1_3_VERSION ||
version == DTLS1_VERSION || version == DTLS1_BAD_VER) {
+ str_version = lookup(version, ssl_versions, "???");
switch (content_type) {
- case 20:
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ /* type 20 */
str_content_type = ", ChangeCipherSpec";
break;
- case 21:
+ case SSL3_RT_ALERT:
+ /* type 21 */
str_content_type = ", Alert";
str_details1 = ", ???";
if (len == 2) {
@@ -598,32 +600,32 @@ void msg_cb(int write_p, int version, int content_type, const void *buf,
str_details2 = lookup((int)bp[1], alert_types, " ???");
}
break;
- case 22:
+ case SSL3_RT_HANDSHAKE:
+ /* type 22 */
str_content_type = ", Handshake";
str_details1 = "???";
if (len > 0)
str_details1 = lookup((int)bp[0], handshakes, "???");
break;
- case 23:
+ case SSL3_RT_APPLICATION_DATA:
+ /* type 23 */
str_content_type = ", ApplicationData";
break;
-#ifndef OPENSSL_NO_HEARTBEATS
- case 24:
- str_details1 = ", Heartbeat";
-
- if (len > 0) {
- switch (bp[0]) {
- case 1:
- str_details1 = ", HeartbeatRequest";
- break;
- case 2:
- str_details1 = ", HeartbeatResponse";
- break;
- }
- }
+ case SSL3_RT_HEADER:
+ /* type 256 */
+ str_content_type = ", RecordHeader";
break;
-#endif
+ case SSL3_RT_INNER_CONTENT_TYPE:
+ /* type 257 */
+ str_content_type = ", InnerContent";
+ break;
+ default:
+ BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, ", Unknown (content_type=%d)", content_type);
+ str_content_type = tmpbuf;
}
+ } else {
+ BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, "Not TLS data or unknown version (version=%d, content_type=%d)", version, content_type);
+ str_version = tmpbuf;
}
BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version,
@@ -663,7 +665,6 @@ static STRINT_PAIR tlsext_types[] = {
{"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},
@@ -750,13 +751,14 @@ void tlsext_cb(SSL *s, int client_server, int type,
}
#ifndef OPENSSL_NO_SOCK
-int generate_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)
{
- unsigned char *buffer;
+ unsigned char *buffer = NULL;
size_t length = 0;
unsigned short port;
BIO_ADDR *lpeer = NULL, *peer = NULL;
+ int res = 0;
/* Initialize a random secret */
if (!cookie_initialized) {
@@ -783,6 +785,7 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
/* Create buffer with peer's address and port */
if (!BIO_ADDR_rawaddress(peer, NULL, &length)) {
BIO_printf(bio_err, "Failed getting peer address\n");
+ BIO_ADDR_free(lpeer);
return 0;
}
OPENSSL_assert(length != 0);
@@ -793,26 +796,31 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
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, cookie, cookie_len);
-
+ if (EVP_Q_mac(NULL, "HMAC", NULL, "SHA1", NULL,
+ cookie_secret, COOKIE_SECRET_LENGTH, buffer, length,
+ cookie, DTLS1_COOKIE_LENGTH, cookie_len) == NULL) {
+ BIO_printf(bio_err,
+ "Error calculating HMAC-SHA1 of buffer with secret\n");
+ goto end;
+ }
+ res = 1;
+end:
OPENSSL_free(buffer);
BIO_ADDR_free(lpeer);
- return 1;
+ return res;
}
-int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
- unsigned int cookie_len)
+int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ size_t cookie_len)
{
unsigned char result[EVP_MAX_MD_SIZE];
- unsigned int resultlength;
+ size_t resultlength;
/* Note: we check cookie_initialized because if it's not,
* it cannot be valid */
if (cookie_initialized
- && generate_cookie_callback(ssl, result, &resultlength)
+ && generate_stateless_cookie_callback(ssl, result, &resultlength)
&& cookie_len == resultlength
&& memcmp(result, cookie, resultlength) == 0)
return 1;
@@ -820,21 +828,21 @@ int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
return 0;
}
-int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
- size_t *cookie_len)
+int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len)
{
- unsigned int temp;
- int res = generate_cookie_callback(ssl, cookie, &temp);
+ size_t temp = 0;
+ int res = generate_stateless_cookie_callback(ssl, cookie, &temp);
if (res != 0)
- *cookie_len = temp;
+ *cookie_len = (unsigned int)temp;
return res;
}
-int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
- size_t cookie_len)
+int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned int cookie_len)
{
- return verify_cookie_callback(ssl, cookie, cookie_len);
+ return verify_stateless_cookie_callback(ssl, cookie, cookie_len);
}
#endif
@@ -898,6 +906,7 @@ static int set_cert_cb(SSL *ssl, void *arg)
SSL_EXCERT *exc = arg;
#ifdef CERT_CB_TEST_RETRY
static int retry_cnt;
+
if (retry_cnt < 5) {
retry_cnt++;
BIO_printf(bio_err,
@@ -996,6 +1005,7 @@ void ssl_excert_free(SSL_EXCERT *exc)
int load_excert(SSL_EXCERT **pexc)
{
SSL_EXCERT *exc = *pexc;
+
if (exc == NULL)
return 1;
/* If nothing in list, free and set to NULL */
@@ -1015,16 +1025,15 @@ int load_excert(SSL_EXCERT **pexc)
return 0;
if (exc->keyfile != NULL) {
exc->key = load_key(exc->keyfile, exc->keyform,
- 0, NULL, NULL, "Server Key");
+ 0, NULL, NULL, "server key");
} else {
exc->key = load_key(exc->certfile, exc->certform,
- 0, NULL, NULL, "Server Key");
+ 0, NULL, NULL, "server key");
}
if (exc->key == NULL)
return 0;
if (exc->chainfile != NULL) {
- if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL,
- "Server Chain"))
+ if (!load_certs(exc->chainfile, 0, &exc->chain, NULL, "server chain"))
return 0;
}
}
@@ -1080,11 +1089,11 @@ int args_excert(int opt, SSL_EXCERT **pexc)
exc->build_chain = 1;
break;
case OPT_X_CERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->certform))
return 0;
break;
case OPT_X_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->keyform))
return 0;
break;
}
@@ -1102,6 +1111,7 @@ static void print_raw_cipherlist(SSL *s)
const unsigned char *rlist;
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);
@@ -1210,7 +1220,7 @@ void print_ssl_summary(SSL *s)
c = SSL_get_current_cipher(s);
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);
+ peer = SSL_get0_peer_certificate(s);
if (peer != NULL) {
int nid;
@@ -1226,7 +1236,6 @@ void print_ssl_summary(SSL *s)
} else {
BIO_puts(bio_err, "No peer certificate\n");
}
- X509_free(peer);
#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio_err, s);
if (SSL_is_server(s))
@@ -1248,12 +1257,10 @@ int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str,
for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) {
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);
+ BIO_printf(bio_err, "Call to SSL_CONF_cmd(%s, %s) failed\n",
+ flag, arg == NULL ? "<NULL>" : arg);
ERR_print_errors(bio_err);
return 0;
}
@@ -1269,17 +1276,20 @@ int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str,
static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls)
{
X509_CRL *crl;
- int i;
+ int i, ret = 1;
+
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
crl = sk_X509_CRL_value(crls, i);
- X509_STORE_add_crl(st, crl);
+ if (!X509_STORE_add_crl(st, crl))
+ ret = 0;
}
- return 1;
+ return ret;
}
int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
{
X509_STORE *st;
+
st = SSL_CTX_get_cert_store(ctx);
add_crls_store(st, crls);
if (crl_download)
@@ -1289,27 +1299,38 @@ 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 *vfyCAstore,
const char *chCApath, const char *chCAfile,
+ const char *chCAstore,
STACK_OF(X509_CRL) *crls, int crl_download)
{
X509_STORE *vfy = NULL, *ch = NULL;
int rv = 0;
- if (vfyCApath != NULL || vfyCAfile != NULL) {
+
+ if (vfyCApath != NULL || vfyCAfile != NULL || vfyCAstore != NULL) {
vfy = X509_STORE_new();
if (vfy == NULL)
goto err;
- if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath))
+ if (vfyCAfile != NULL && !X509_STORE_load_file(vfy, vfyCAfile))
+ goto err;
+ if (vfyCApath != NULL && !X509_STORE_load_path(vfy, vfyCApath))
+ goto err;
+ if (vfyCAstore != NULL && !X509_STORE_load_store(vfy, vfyCAstore))
goto err;
add_crls_store(vfy, crls);
SSL_CTX_set1_verify_cert_store(ctx, vfy);
if (crl_download)
store_setup_crl_download(vfy);
}
- if (chCApath != NULL || chCAfile != NULL) {
+ if (chCApath != NULL || chCAfile != NULL || chCAstore != NULL) {
ch = X509_STORE_new();
if (ch == NULL)
goto err;
- if (!X509_STORE_load_locations(ch, chCAfile, chCApath))
+ if (chCAfile != NULL && !X509_STORE_load_file(ch, chCAfile))
+ goto err;
+ if (chCApath != NULL && !X509_STORE_load_path(ch, chCApath))
+ goto err;
+ if (chCAstore != NULL && !X509_STORE_load_store(ch, chCAstore))
goto err;
SSL_CTX_set1_chain_cert_store(ctx, ch);
}
@@ -1362,6 +1383,7 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
int rv, show_bits = 1, cert_md = 0;
const char *nm;
int show_nm;
+
rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
if (rv == 1 && sdb->verbose < 2)
return 1;
@@ -1411,26 +1433,25 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
}
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));
+
+ if (pkey == NULL) {
+ BIO_printf(sdb->out, "Public key missing");
+ } else {
+ 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_get_bits(pkey));
+ }
}
break;
}
diff --git a/apps/s_socket.c b/apps/lib/s_socket.c
index 96f16d2931cd..059afe47b904 100644
--- a/apps/s_socket.c
+++ b/apps/lib/s_socket.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -26,12 +26,27 @@
typedef unsigned int u_int;
#endif
+#ifdef _WIN32
+# include <process.h>
+
+/* MSVC renamed some POSIX functions to have an underscore prefix. */
+# ifdef _MSC_VER
+# define getpid _getpid
+# endif
+#endif
+
#ifndef OPENSSL_NO_SOCK
# include "apps.h"
# include "s_apps.h"
# include "internal/sockets.h"
+# if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_read)>
+# endif
+# endif
+
# include <openssl/bio.h>
# include <openssl/err.h>
@@ -160,7 +175,9 @@ int init_client(int *sock, const char *host, const char *port,
if (*sock == INVALID_SOCKET) {
if (bindaddr != NULL && !found) {
BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n",
+#ifdef AF_INET6
BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " :
+#endif
BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " :
BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "",
bindhost != NULL ? bindhost : "",
@@ -183,6 +200,42 @@ out:
return ret;
}
+int report_server_accept(BIO *out, int asock, int with_address, int with_pid)
+{
+ int success = 1;
+
+ if (BIO_printf(out, "ACCEPT") <= 0)
+ return 0;
+ if (with_address) {
+ union BIO_sock_info_u info;
+ char *hostname = NULL;
+ char *service = NULL;
+
+ 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) {
+ success = BIO_printf(out,
+ strchr(hostname, ':') == NULL
+ ? /* IPv4 */ " %s:%s"
+ : /* IPv6 */ " [%s]:%s",
+ hostname, service) > 0;
+ } else {
+ (void)BIO_printf(out, "unknown:error\n");
+ success = 0;
+ }
+ OPENSSL_free(hostname);
+ OPENSSL_free(service);
+ BIO_ADDR_free(info.addr);
+ }
+ if (with_pid)
+ success = success && BIO_printf(out, " PID=%d", getpid()) > 0;
+ success = success && BIO_printf(out, "\n") > 0;
+ (void)BIO_flush(out);
+
+ return success;
+}
+
/*
* do_server - helper routine to perform a server operation
* @accept_sock: pointer to storage of resulting socket.
@@ -239,6 +292,7 @@ int do_server(int *accept_sock, const char *host, const char *port,
sock_protocol = BIO_ADDRINFO_protocol(res);
sock_address = BIO_ADDRINFO_address(res);
next = BIO_ADDRINFO_next(res);
+#ifdef AF_INET6
if (sock_family == AF_INET6)
sock_options |= BIO_SOCK_V6_ONLY;
if (next != NULL
@@ -257,6 +311,7 @@ int do_server(int *accept_sock, const char *host, const char *port,
sock_options &= ~BIO_SOCK_V6_ONLY;
}
}
+#endif
asock = BIO_socket(sock_family, sock_type, sock_protocol, 0);
if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) {
@@ -296,36 +351,10 @@ int do_server(int *accept_sock, const char *host, const char *port,
BIO_ADDRINFO_free(res);
res = NULL;
- 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 ((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;
-
- (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;
- }
- } else {
- (void)BIO_printf(bio_s_out, "ACCEPT\n");
- (void)BIO_flush(bio_s_out);
+ if (!report_server_accept(bio_s_out, asock, sock_port == 0, 0)) {
+ BIO_closesocket(asock);
+ ERR_print_errors(bio_err);
+ goto end;
}
if (accept_sock != NULL)
@@ -402,4 +431,25 @@ int do_server(int *accept_sock, const char *host, const char *port,
return ret;
}
+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);
+}
+
#endif /* OPENSSL_NO_SOCK */
diff --git a/apps/lib/tlssrp_depr.c b/apps/lib/tlssrp_depr.c
new file mode 100644
index 000000000000..91c19b096e9a
--- /dev/null
+++ b/apps/lib/tlssrp_depr.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/*
+ * This file is to enable backwards compatibility for the SRP features of
+ * s_client, s_server and ciphers. All of those features are deprecated and will
+ * eventually disappear. In the meantime, to continue to support them, we
+ * need to access deprecated SRP APIs.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <openssl/bn.h>
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/srp.h>
+#include "apps_ui.h"
+#include "apps.h"
+#include "s_apps.h"
+
+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_check_prime(N, bn_ctx, NULL) == 1 &&
+ p != NULL && BN_rshift1(p, N) &&
+ /* p = (N-1)/2 */
+ BN_check_prime(p, 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;
+
+ BN_free(r);
+ BN_free(p);
+ BN_CTX_free(bn_ctx);
+ return ret;
+}
+
+/*-
+ * This callback is used here for two purposes:
+ * - extended debugging
+ * - making some primality tests for unknown groups
+ * The callback is only called for a non default group.
+ *
+ * An application does not need the call back at all if
+ * 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
+ * is not one of those defined in RFC 5054, it is more appropriate
+ * to add the group to a static list and then compare since
+ * primality tests are rather cpu consuming.
+ */
+
+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)) == 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");
+ BIO_printf(bio_err, "\tN=");
+ BN_print(bio_err, N);
+ BIO_printf(bio_err, "\n\tg=");
+ BN_print(bio_err, g);
+ BIO_printf(bio_err, "\n");
+ }
+
+ if (SRP_check_known_gN_param(g, N))
+ return 1;
+
+ if (srp_arg->amp == 1) {
+ if (srp_arg->debug)
+ BIO_printf(bio_err,
+ "SRP param N and g are not known params, going to check deeper.\n");
+
+ /*
+ * The srp_moregroups is a real debugging feature. Implementors
+ * should rather add the value to the known ones. The minimal size
+ * has already been tested.
+ */
+ if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g))
+ return 1;
+ }
+ BIO_printf(bio_err, "SRP param N and g rejected.\n");
+ return 0;
+}
+
+#define PWD_STRLEN 1024
+
+static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
+{
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer");
+ PW_CB_DATA cb_tmp;
+ int l;
+
+ cb_tmp.password = (char *)srp_arg->srppassin;
+ cb_tmp.prompt_info = "SRP user";
+ if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) {
+ BIO_printf(bio_err, "Can't read Password\n");
+ OPENSSL_free(pass);
+ return NULL;
+ }
+ *(pass + l) = '\0';
+
+ return pass;
+}
+
+int set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg,
+ int c_debug)
+{
+ if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg->srplogin)) {
+ BIO_printf(bio_err, "Unable to set SRP username\n");
+ return 0;
+ }
+ srp_arg->msg = c_msg;
+ srp_arg->debug = c_debug;
+ SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
+ SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
+ SSL_CTX_set_srp_strength(ctx, srp_arg->strength);
+ if (c_msg || c_debug || srp_arg->amp == 0)
+ SSL_CTX_set_srp_verify_param_callback(ctx, ssl_srp_verify_param_cb);
+
+ return 1;
+}
+
+static char *dummy_srp(SSL *ssl, void *arg)
+{
+ return "";
+}
+
+void set_up_dummy_srp(SSL_CTX *ctx)
+{
+ SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp);
+}
+
+/*
+ * This callback pretends to require some asynchronous logic in order to
+ * obtain a verifier. When the callback is called for a new connection we
+ * return with a negative value. This will provoke the accept etc to return
+ * with an LOOKUP_X509. The main logic of the reinvokes the suspended call
+ * (which would normally occur after a worker has finished) and we set the
+ * user parameters.
+ */
+static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
+{
+ srpsrvparm *p = (srpsrvparm *) arg;
+ int ret = SSL3_AL_FATAL;
+
+ 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;
+ }
+
+ if (p->user == NULL) {
+ BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
+ goto err;
+ }
+
+ if (SSL_set_srp_server_param
+ (s, p->user->N, p->user->g, p->user->s, p->user->v,
+ p->user->info) < 0) {
+ *ad = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ BIO_printf(bio_err,
+ "SRP parameters set: username = \"%s\" info=\"%s\" \n",
+ p->login, p->user->info);
+ ret = SSL_ERROR_NONE;
+
+ err:
+ SRP_user_pwd_free(p->user);
+ p->user = NULL;
+ p->login = NULL;
+ return ret;
+}
+
+int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm,
+ char *srpuserseed, char *srp_verifier_file)
+{
+ int ret;
+
+ srp_callback_parm->vb = SRP_VBASE_new(srpuserseed);
+ srp_callback_parm->user = NULL;
+ srp_callback_parm->login = NULL;
+
+ if (srp_callback_parm->vb == NULL) {
+ BIO_printf(bio_err, "Failed to initialize SRP verifier file \n");
+ return 0;
+ }
+ if ((ret =
+ SRP_VBASE_init(srp_callback_parm->vb,
+ srp_verifier_file)) != SRP_NO_ERROR) {
+ BIO_printf(bio_err,
+ "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
+ srp_verifier_file, ret);
+ return 0;
+ }
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
+ SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);
+ SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
+
+ return 1;
+}
+
+void lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out)
+{
+ 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 != NULL)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm->user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+}
diff --git a/apps/lib/vms_decc_argv.c b/apps/lib/vms_decc_argv.c
new file mode 100644
index 000000000000..031e5afdeca0
--- /dev/null
+++ b/apps/lib/vms_decc_argv.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 <stdlib.h>
+#include <openssl/crypto.h>
+#include "platform.h" /* for copy_argv() */
+
+char **newargv = NULL;
+
+static void cleanup_argv(void)
+{
+ OPENSSL_free(newargv);
+ newargv = NULL;
+}
+
+char **copy_argv(int *argc, char *argv[])
+{
+ /*-
+ * The note below is for historical purpose. On VMS now we always
+ * copy argv "safely."
+ *
+ * 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.
+ * 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.
+ */
+
+ int i, count = *argc;
+ char **p = newargv;
+
+ cleanup_argv();
+
+ /*
+ * We purposefully use OPENSSL_malloc() rather than app_malloc() here,
+ * to avoid symbol name clashes in test programs that would otherwise
+ * get them when linking with all of libapps.a.
+ * See comment in test/build.info.
+ */
+ newargv = OPENSSL_malloc(sizeof(*newargv) * (count + 1));
+ if (newargv == NULL)
+ return NULL;
+
+ /* Register automatic cleanup on first use */
+ if (p == NULL)
+ OPENSSL_atexit(cleanup_argv);
+
+ for (i = 0; i < count; i++)
+ newargv[i] = argv[i];
+ newargv[i] = NULL;
+ *argc = i;
+ return newargv;
+}
diff --git a/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c
new file mode 100644
index 000000000000..97fb3943265c
--- /dev/null
+++ b/apps/lib/vms_term_sock.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016 VMS Software, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 __VMS
+# define OPENSSL_SYS_VMS
+# pragma message disable DOLLARID
+
+
+# include <openssl/opensslconf.h>
+
+# if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
+/*
+ * On VMS, you need to define this to get the declaration of fileno(). The
+ * value 2 is to make sure no function defined in POSIX-2 is left undefined.
+ */
+# define _POSIX_C_SOURCE 2
+# endif
+
+# include <stdio.h>
+
+# undef _POSIX_C_SOURCE
+
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <inet.h>
+# include <unistd.h>
+# include <string.h>
+# include <errno.h>
+# include <starlet.h>
+# include <iodef.h>
+# ifdef __alpha
+# include <iosbdef.h>
+# else
+typedef struct _iosb { /* Copied from IOSBDEF.H for Alpha */
+# pragma __nomember_alignment
+ __union {
+ __struct {
+ unsigned short int iosb$w_status; /* Final I/O status */
+ __union {
+ __struct { /* 16-bit byte count variant */
+ unsigned short int iosb$w_bcnt; /* 16-bit byte count */
+ __union {
+ unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */
+ unsigned int iosb$l_pid; /* 32-bit pid */
+ } iosb$r_l;
+ } iosb$r_bcnt_16;
+ __struct { /* 32-bit byte count variant */
+ unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */
+ unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */
+ } iosb$r_bcnt_32;
+ } iosb$r_devdepend;
+ } iosb$r_io_64;
+ __struct {
+ __union {
+ unsigned int iosb$l_getxxi_status; /* Final GETxxI status */
+ unsigned int iosb$l_reg_status; /* Final $Registry status */
+ } iosb$r_l_status;
+ unsigned int iosb$l_reserved; /* Reserved field */
+ } iosb$r_get_64;
+ } iosb$r_io_get;
+} IOSB;
+
+# if !defined(__VAXC)
+# define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status
+# define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt
+# define iosb$r_l iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l
+# define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend
+# define iosb$l_pid iosb$r_l.iosb$l_pid
+# define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt
+# define iosb$w_dev_depend_high iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$w_dev_depend_high
+# define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status
+# define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status
+# endif /* #if !defined(__VAXC) */
+
+# endif /* End of IOSBDEF */
+
+# include <efndef.h>
+# include <stdlib.h>
+# include <ssdef.h>
+# include <time.h>
+# include <stdarg.h>
+# include <descrip.h>
+
+# include "vms_term_sock.h"
+
+# ifdef __alpha
+static struct _iosb TerminalDeviceIosb;
+# else
+IOSB TerminalDeviceIosb;
+# endif
+
+static char TerminalDeviceBuff[255 + 2];
+static int TerminalSocketPair[2] = {0, 0};
+static unsigned short TerminalDeviceChan = 0;
+
+static int CreateSocketPair (int, int, int, int *);
+static void SocketPairTimeoutAst (int);
+static int TerminalDeviceAst (int);
+static void LogMessage (char *, ...);
+
+/*
+** Socket Pair Timeout Value (must be 0-59 seconds)
+*/
+# define SOCKET_PAIR_TIMEOUT_VALUE 20
+
+/*
+** Socket Pair Timeout Block which is passed to timeout AST
+*/
+typedef struct _SocketPairTimeoutBlock {
+ unsigned short SockChan1;
+ unsigned short SockChan2;
+} SPTB;
+
+# ifdef TERM_SOCK_TEST
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+int main (int argc, char *argv[], char *envp[])
+{
+ char TermBuff[80];
+ int TermSock,
+ status,
+ len;
+
+ LogMessage ("Enter 'q' or 'Q' to quit ...");
+ while (OPENSSL_strcasecmp (TermBuff, "Q")) {
+ /*
+ ** Create the terminal socket
+ */
+ status = TerminalSocket (TERM_SOCK_CREATE, &TermSock);
+ if (status != TERM_SOCK_SUCCESS)
+ exit (1);
+
+ /*
+ ** Process the terminal input
+ */
+ LogMessage ("Waiting on terminal I/O ...\n");
+ len = recv (TermSock, TermBuff, sizeof(TermBuff), 0) ;
+ TermBuff[len] = '\0';
+ LogMessage ("Received terminal I/O [%s]", TermBuff);
+
+ /*
+ ** Delete the terminal socket
+ */
+ status = TerminalSocket (TERM_SOCK_DELETE, &TermSock);
+ if (status != TERM_SOCK_SUCCESS)
+ exit (1);
+ }
+
+ return 1;
+
+}
+# endif
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+int TerminalSocket (int FunctionCode, int *ReturnSocket)
+{
+ int status;
+ $DESCRIPTOR (TerminalDeviceDesc, "SYS$COMMAND");
+
+ /*
+ ** Process the requested function code
+ */
+ switch (FunctionCode) {
+ case TERM_SOCK_CREATE:
+ /*
+ ** Create a socket pair
+ */
+ status = CreateSocketPair (AF_INET, SOCK_STREAM, 0, TerminalSocketPair);
+ if (status == -1) {
+ LogMessage ("TerminalSocket: CreateSocketPair () - %08X", status);
+ if (TerminalSocketPair[0])
+ close (TerminalSocketPair[0]);
+ if (TerminalSocketPair[1])
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Assign a channel to the terminal device
+ */
+ status = sys$assign (&TerminalDeviceDesc,
+ &TerminalDeviceChan,
+ 0, 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$ASSIGN () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Queue an async IO to the terminal device
+ */
+ status = sys$qio (EFN$C_ENF,
+ TerminalDeviceChan,
+ IO$_READVBLK,
+ &TerminalDeviceIosb,
+ TerminalDeviceAst,
+ 0,
+ TerminalDeviceBuff,
+ sizeof(TerminalDeviceBuff) - 2,
+ 0, 0, 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$QIO () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Return the input side of the socket pair
+ */
+ *ReturnSocket = TerminalSocketPair[1];
+ break;
+
+ case TERM_SOCK_DELETE:
+ /*
+ ** Cancel any pending IO on the terminal channel
+ */
+ status = sys$cancel (TerminalDeviceChan);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$CANCEL () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Deassign the terminal channel
+ */
+ status = sys$dassgn (TerminalDeviceChan);
+ if (! (status & 1)) {
+ LogMessage ("TerminalSocket: SYS$DASSGN () - %08X", status);
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+ return TERM_SOCK_FAILURE;
+ }
+
+ /*
+ ** Close the terminal socket pair
+ */
+ close (TerminalSocketPair[0]);
+ close (TerminalSocketPair[1]);
+
+ /*
+ ** Return the initialized socket
+ */
+ *ReturnSocket = 0;
+ break;
+
+ default:
+ /*
+ ** Invalid function code
+ */
+ LogMessage ("TerminalSocket: Invalid Function Code - %d", FunctionCode);
+ return TERM_SOCK_FAILURE;
+ break;
+ }
+
+ /*
+ ** Return success
+ */
+ return TERM_SOCK_SUCCESS;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static int CreateSocketPair (int SocketFamily,
+ int SocketType,
+ int SocketProtocol,
+ int *SocketPair)
+{
+ struct dsc$descriptor AscTimeDesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
+ static const char* LocalHostAddr = {"127.0.0.1"};
+ unsigned short TcpAcceptChan = 0,
+ TcpDeviceChan = 0;
+ unsigned long BinTimeBuff[2];
+ struct sockaddr_in sin;
+ char AscTimeBuff[32];
+ short LocalHostPort;
+ int status;
+ unsigned int slen;
+
+# ifdef __alpha
+ struct _iosb iosb;
+# else
+ IOSB iosb;
+# endif
+
+ int SockDesc1 = 0,
+ SockDesc2 = 0;
+ SPTB sptb;
+ $DESCRIPTOR (TcpDeviceDesc, "TCPIP$DEVICE");
+
+ /*
+ ** Create a socket
+ */
+ SockDesc1 = socket (SocketFamily, SocketType, 0);
+ if (SockDesc1 < 0) {
+ LogMessage ("CreateSocketPair: socket () - %d", errno);
+ return -1;
+ }
+
+ /*
+ ** Initialize the socket information
+ */
+ slen = sizeof(sin);
+ memset ((char *) &sin, 0, slen);
+ sin.sin_family = SocketFamily;
+ sin.sin_addr.s_addr = inet_addr (LocalHostAddr);
+ sin.sin_port = 0;
+
+ /*
+ ** Bind the socket to the local IP
+ */
+ status = bind (SockDesc1, (struct sockaddr *) &sin, slen);
+ if (status < 0) {
+ LogMessage ("CreateSocketPair: bind () - %d", errno);
+ close (SockDesc1);
+ return -1;
+ }
+
+ /*
+ ** Get the socket name so we can save the port number
+ */
+ status = getsockname (SockDesc1, (struct sockaddr *) &sin, &slen);
+ if (status < 0) {
+ LogMessage ("CreateSocketPair: getsockname () - %d", errno);
+ close (SockDesc1);
+ return -1;
+ } else
+ LocalHostPort = sin.sin_port;
+
+ /*
+ ** Setup a listen for the socket
+ */
+ listen (SockDesc1, 5);
+
+ /*
+ ** Get the binary (64-bit) time of the specified timeout value
+ */
+ sprintf (AscTimeBuff, "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE);
+ AscTimeDesc.dsc$w_length = strlen (AscTimeBuff);
+ AscTimeDesc.dsc$a_pointer = AscTimeBuff;
+ status = sys$bintim (&AscTimeDesc, BinTimeBuff);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$BINTIM () - %08X", status);
+ close (SockDesc1);
+ return -1;
+ }
+
+ /*
+ ** Assign another channel to the TCP/IP device for the accept.
+ ** This is the channel that ends up being connected to.
+ */
+ status = sys$assign (&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$ASSIGN () - %08X", status);
+ close (SockDesc1);
+ return -1;
+ }
+
+ /*
+ ** Get the channel of the first socket for the accept
+ */
+ TcpAcceptChan = decc$get_sdc (SockDesc1);
+
+ /*
+ ** Perform the accept using $QIO so we can do this asynchronously
+ */
+ status = sys$qio (EFN$C_ENF,
+ TcpAcceptChan,
+ IO$_ACCESS | IO$M_ACCEPT,
+ &iosb,
+ 0, 0, 0, 0, 0,
+ &TcpDeviceChan,
+ 0, 0);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$QIO () - %08X", status);
+ close (SockDesc1);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Create the second socket to do the connect
+ */
+ SockDesc2 = socket (SocketFamily, SocketType, 0);
+ if (SockDesc2 < 0) {
+ LogMessage ("CreateSocketPair: socket () - %d", errno);
+ sys$cancel (TcpAcceptChan);
+ close (SockDesc1);
+ sys$dassgn (TcpDeviceChan);
+ return (-1) ;
+ }
+
+ /*
+ ** Setup the Socket Pair Timeout Block
+ */
+ sptb.SockChan1 = TcpAcceptChan;
+ sptb.SockChan2 = decc$get_sdc (SockDesc2);
+
+ /*
+ ** Before we block on the connect, set a timer that can cancel I/O on our
+ ** two sockets if it never connects.
+ */
+ status = sys$setimr (EFN$C_ENF,
+ BinTimeBuff,
+ SocketPairTimeoutAst,
+ &sptb,
+ 0);
+ if (! (status & 1)) {
+ LogMessage ("CreateSocketPair: SYS$SETIMR () - %08X", status);
+ sys$cancel (TcpAcceptChan);
+ close (SockDesc1);
+ close (SockDesc2);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Now issue the connect
+ */
+ memset ((char *) &sin, 0, sizeof(sin)) ;
+ sin.sin_family = SocketFamily;
+ sin.sin_addr.s_addr = inet_addr (LocalHostAddr) ;
+ sin.sin_port = LocalHostPort ;
+
+ status = connect (SockDesc2, (struct sockaddr *) &sin, sizeof(sin));
+ if (status < 0 ) {
+ LogMessage ("CreateSocketPair: connect () - %d", errno);
+ sys$cantim (&sptb, 0);
+ sys$cancel (TcpAcceptChan);
+ close (SockDesc1);
+ close (SockDesc2);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Wait for the asynch $QIO to finish. Note that if the I/O was aborted
+ ** (SS$_ABORT), then we probably canceled it from the AST routine - so log
+ ** a timeout.
+ */
+ status = sys$synch (EFN$C_ENF, &iosb);
+ if (! (iosb.iosb$w_status & 1)) {
+ if (iosb.iosb$w_status == SS$_ABORT)
+ LogMessage ("CreateSocketPair: SYS$QIO(iosb) timeout");
+ else {
+ LogMessage ("CreateSocketPair: SYS$QIO(iosb) - %d",
+ iosb.iosb$w_status);
+ sys$cantim (&sptb, 0);
+ }
+ close (SockDesc1);
+ close (SockDesc2);
+ sys$dassgn (TcpDeviceChan);
+ return -1;
+ }
+
+ /*
+ ** Here we're successfully connected, so cancel the timer, convert the
+ ** I/O channel to a socket fd, close the listener socket and return the
+ ** connected pair.
+ */
+ sys$cantim (&sptb, 0);
+
+ close (SockDesc1) ;
+ SocketPair[0] = SockDesc2 ;
+ SocketPair[1] = socket_fd (TcpDeviceChan);
+
+ return (0) ;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static void SocketPairTimeoutAst (int astparm)
+{
+ SPTB *sptb = (SPTB *) astparm;
+
+ sys$cancel (sptb->SockChan2); /* Cancel the connect() */
+ sys$cancel (sptb->SockChan1); /* Cancel the accept() */
+
+ return;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static int TerminalDeviceAst (int astparm)
+{
+ int status;
+
+ /*
+ ** Terminate the terminal buffer
+ */
+ TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0';
+ strcat (TerminalDeviceBuff, "\n");
+
+ /*
+ ** Send the data read from the terminal device through the socket pair
+ */
+ send (TerminalSocketPair[0], TerminalDeviceBuff,
+ TerminalDeviceIosb.iosb$w_bcnt + 1, 0);
+
+ /*
+ ** Queue another async IO to the terminal device
+ */
+ status = sys$qio (EFN$C_ENF,
+ TerminalDeviceChan,
+ IO$_READVBLK,
+ &TerminalDeviceIosb,
+ TerminalDeviceAst,
+ 0,
+ TerminalDeviceBuff,
+ sizeof(TerminalDeviceBuff) - 1,
+ 0, 0, 0, 0);
+
+ /*
+ ** Return status
+ */
+ return status;
+
+}
+
+/*----------------------------------------------------------------------------*/
+/* */
+/*----------------------------------------------------------------------------*/
+static void LogMessage (char *msg, ...)
+{
+ char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ static unsigned int pid = 0;
+ va_list args;
+ time_t CurTime;
+ struct tm *LocTime;
+ char MsgBuff[256];
+
+ /*
+ ** Get the process pid
+ */
+ if (pid == 0)
+ pid = getpid ();
+
+ /*
+ ** Convert the current time into local time
+ */
+ CurTime = time (NULL);
+ LocTime = localtime (&CurTime);
+
+ /*
+ ** Format the message buffer
+ */
+ sprintf (MsgBuff, "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n",
+ LocTime->tm_mday, Month[LocTime->tm_mon],
+ (LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min,
+ LocTime->tm_sec, pid, msg);
+
+ /*
+ ** Get any variable arguments and add them to the print of the message
+ ** buffer
+ */
+ va_start (args, msg);
+ vfprintf (stderr, MsgBuff, args);
+ va_end (args);
+
+ /*
+ ** Flush standard error output
+ */
+ fsync (fileno (stderr));
+
+ return;
+
+}
+#endif
diff --git a/apps/lib/win32_init.c b/apps/lib/win32_init.c
new file mode 100644
index 000000000000..6d2be0c62942
--- /dev/null
+++ b/apps/lib/win32_init.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+
+#if defined(CP_UTF8)
+
+static UINT saved_cp;
+static int newargc;
+static char **newargv;
+
+static void cleanup(void)
+{
+ int i;
+
+ SetConsoleOutputCP(saved_cp);
+
+ for (i = 0; i < newargc; i++)
+ free(newargv[i]);
+
+ free(newargv);
+}
+
+/*
+ * Incrementally [re]allocate newargv and keep it NULL-terminated.
+ */
+static int validate_argv(int argc)
+{
+ static int size = 0;
+
+ if (argc >= size) {
+ char **ptr;
+
+ while (argc >= size)
+ size += 64;
+
+ ptr = realloc(newargv, size * sizeof(newargv[0]));
+ if (ptr == NULL)
+ return 0;
+
+ (newargv = ptr)[argc] = NULL;
+ } else {
+ newargv[argc] = NULL;
+ }
+
+ return 1;
+}
+
+static int process_glob(WCHAR *wstr, int wlen)
+{
+ int i, slash, udlen;
+ WCHAR saved_char;
+ WIN32_FIND_DATAW data;
+ HANDLE h;
+
+ /*
+ * Note that we support wildcard characters only in filename part
+ * of the path, and not in directories. Windows users are used to
+ * this, that's why recursive glob processing is not implemented.
+ */
+ /*
+ * Start by looking for last slash or backslash, ...
+ */
+ for (slash = 0, i = 0; i < wlen; i++)
+ if (wstr[i] == L'/' || wstr[i] == L'\\')
+ slash = i + 1;
+ /*
+ * ... then look for asterisk or question mark in the file name.
+ */
+ for (i = slash; i < wlen; i++)
+ if (wstr[i] == L'*' || wstr[i] == L'?')
+ break;
+
+ if (i == wlen)
+ return 0; /* definitely not a glob */
+
+ saved_char = wstr[wlen];
+ wstr[wlen] = L'\0';
+ h = FindFirstFileW(wstr, &data);
+ wstr[wlen] = saved_char;
+ if (h == INVALID_HANDLE_VALUE)
+ return 0; /* not a valid glob, just pass... */
+
+ if (slash)
+ udlen = WideCharToMultiByte(CP_UTF8, 0, wstr, slash,
+ NULL, 0, NULL, NULL);
+ else
+ udlen = 0;
+
+ do {
+ int uflen;
+ char *arg;
+
+ /*
+ * skip over . and ..
+ */
+ if (data.cFileName[0] == L'.') {
+ if ((data.cFileName[1] == L'\0') ||
+ (data.cFileName[1] == L'.' && data.cFileName[2] == L'\0'))
+ continue;
+ }
+
+ if (!validate_argv(newargc + 1))
+ break;
+
+ /*
+ * -1 below means "scan for trailing '\0' *and* count it",
+ * so that |uflen| covers even trailing '\0'.
+ */
+ uflen = WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1,
+ NULL, 0, NULL, NULL);
+
+ arg = malloc(udlen + uflen);
+ if (arg == NULL)
+ break;
+
+ if (udlen)
+ WideCharToMultiByte(CP_UTF8, 0, wstr, slash,
+ arg, udlen, NULL, NULL);
+
+ WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1,
+ arg + udlen, uflen, NULL, NULL);
+
+ newargv[newargc++] = arg;
+ } while (FindNextFileW(h, &data));
+
+ CloseHandle(h);
+
+ return 1;
+}
+
+void win32_utf8argv(int *argc, char **argv[])
+{
+ const WCHAR *wcmdline;
+ WCHAR *warg, *wend, *p;
+ int wlen, ulen, valid = 1;
+ char *arg;
+
+ if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) == 0)
+ return;
+
+ newargc = 0;
+ newargv = NULL;
+ if (!validate_argv(newargc))
+ return;
+
+ wcmdline = GetCommandLineW();
+ if (wcmdline == NULL) return;
+
+ /*
+ * make a copy of the command line, since we might have to modify it...
+ */
+ wlen = wcslen(wcmdline);
+ p = _alloca((wlen + 1) * sizeof(WCHAR));
+ wcscpy(p, wcmdline);
+
+ while (*p != L'\0') {
+ int in_quote = 0;
+
+ if (*p == L' ' || *p == L'\t') {
+ p++; /* skip over whitespace */
+ continue;
+ }
+
+ /*
+ * Note: because we may need to fiddle with the number of backslashes,
+ * the argument string is copied into itself. This is safe because
+ * the number of characters will never expand.
+ */
+ warg = wend = p;
+ while (*p != L'\0'
+ && (in_quote || (*p != L' ' && *p != L'\t'))) {
+ switch (*p) {
+ case L'\\':
+ /*
+ * Microsoft documentation on how backslashes are treated
+ * is:
+ *
+ * + Backslashes are interpreted literally, unless they
+ * immediately precede a double quotation mark.
+ * + If an even number of backslashes is followed by a double
+ * quotation mark, one backslash is placed in the argv array
+ * for every pair of backslashes, and the double quotation
+ * mark is interpreted as a string delimiter.
+ * + If an odd number of backslashes is followed by a double
+ * quotation mark, one backslash is placed in the argv array
+ * for every pair of backslashes, and the double quotation
+ * mark is "escaped" by the remaining backslash, causing a
+ * literal double quotation mark (") to be placed in argv.
+ *
+ * Ref: https://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+ *
+ * Though referred page doesn't mention it, multiple qouble
+ * quotes are also special. Pair of double quotes in quoted
+ * string is counted as single double quote.
+ */
+ {
+ const WCHAR *q = p;
+ int i;
+
+ while (*p == L'\\')
+ p++;
+
+ if (*p == L'"') {
+ int i;
+
+ for (i = (p - q) / 2; i > 0; i--)
+ *wend++ = L'\\';
+
+ /*
+ * if odd amount of backslashes before the quote,
+ * said quote is part of the argument, not a delimiter
+ */
+ if ((p - q) % 2 == 1)
+ *wend++ = *p++;
+ } else {
+ for (i = p - q; i > 0; i--)
+ *wend++ = L'\\';
+ }
+ }
+ break;
+ case L'"':
+ /*
+ * Without the preceding backslash (or when preceded with an
+ * even number of backslashes), the double quote is a simple
+ * string delimiter and just slightly change the parsing state
+ */
+ if (in_quote && p[1] == L'"')
+ *wend++ = *p++;
+ else
+ in_quote = !in_quote;
+ p++;
+ break;
+ default:
+ /*
+ * Any other non-delimiter character is just taken verbatim
+ */
+ *wend++ = *p++;
+ }
+ }
+
+ wlen = wend - warg;
+
+ if (wlen == 0 || !process_glob(warg, wlen)) {
+ if (!validate_argv(newargc + 1)) {
+ valid = 0;
+ break;
+ }
+
+ ulen = 0;
+ if (wlen > 0) {
+ ulen = WideCharToMultiByte(CP_UTF8, 0, warg, wlen,
+ NULL, 0, NULL, NULL);
+ if (ulen <= 0)
+ continue;
+ }
+
+ arg = malloc(ulen + 1);
+ if (arg == NULL) {
+ valid = 0;
+ break;
+ }
+
+ if (wlen > 0)
+ WideCharToMultiByte(CP_UTF8, 0, warg, wlen,
+ arg, ulen, NULL, NULL);
+ arg[ulen] = '\0';
+
+ newargv[newargc++] = arg;
+ }
+ }
+
+ if (valid) {
+ saved_cp = GetConsoleOutputCP();
+ SetConsoleOutputCP(CP_UTF8);
+
+ *argc = newargc;
+ *argv = newargv;
+
+ atexit(cleanup);
+ } else if (newargv != NULL) {
+ int i;
+
+ for (i = 0; i < newargc; i++)
+ free(newargv[i]);
+
+ free(newargv);
+
+ newargc = 0;
+ newargv = NULL;
+ }
+
+ return;
+}
+#else
+void win32_utf8argv(int *argc, char **argv[])
+{ return; }
+#endif
diff --git a/apps/list.c b/apps/list.c
new file mode 100644
index 000000000000..514abacfc835
--- /dev/null
+++ b/apps/list.c
@@ -0,0 +1,1706 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/provider.h>
+#include <openssl/safestack.h>
+#include <openssl/kdf.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include <openssl/store.h>
+#include <openssl/core_names.h>
+#include <openssl/rand.h>
+#include "apps.h"
+#include "app_params.h"
+#include "progs.h"
+#include "opt.h"
+#include "names.h"
+
+static int verbose = 0;
+static const char *select_name = NULL;
+
+/* Checks to see if algorithms are fetchable */
+#define IS_FETCHABLE(type, TYPE) \
+ static int is_ ## type ## _fetchable(const TYPE *alg) \
+ { \
+ TYPE *impl; \
+ const char *propq = app_get0_propq(); \
+ OSSL_LIB_CTX *libctx = app_get0_libctx(); \
+ const char *name = TYPE ## _get0_name(alg); \
+ \
+ ERR_set_mark(); \
+ impl = TYPE ## _fetch(libctx, name, propq); \
+ ERR_pop_to_mark(); \
+ if (impl == NULL) \
+ return 0; \
+ TYPE ## _free(impl); \
+ return 1; \
+ }
+IS_FETCHABLE(cipher, EVP_CIPHER)
+IS_FETCHABLE(digest, EVP_MD)
+IS_FETCHABLE(mac, EVP_MAC)
+IS_FETCHABLE(kdf, EVP_KDF)
+IS_FETCHABLE(rand, EVP_RAND)
+IS_FETCHABLE(keymgmt, EVP_KEYMGMT)
+IS_FETCHABLE(signature, EVP_SIGNATURE)
+IS_FETCHABLE(kem, EVP_KEM)
+IS_FETCHABLE(asym_cipher, EVP_ASYM_CIPHER)
+IS_FETCHABLE(keyexch, EVP_KEYEXCH)
+IS_FETCHABLE(decoder, OSSL_DECODER)
+IS_FETCHABLE(encoder, OSSL_ENCODER)
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+static int include_legacy(void)
+{
+ return app_get0_propq() == NULL;
+}
+
+static void legacy_cipher_fn(const EVP_CIPHER *c,
+ const char *from, const char *to, void *arg)
+{
+ if (select_name != NULL
+ && (c == NULL
+ || OPENSSL_strcasecmp(select_name, EVP_CIPHER_get0_name(c)) != 0))
+ return;
+ if (c != NULL) {
+ BIO_printf(arg, " %s\n", EVP_CIPHER_get0_name(c));
+ } else {
+ if (from == NULL)
+ from = "<undefined>";
+ if (to == NULL)
+ to = "<undefined>";
+ BIO_printf(arg, " %s => %s\n", from, to);
+ }
+}
+#endif
+
+DEFINE_STACK_OF(EVP_CIPHER)
+static int cipher_cmp(const EVP_CIPHER * const *a,
+ const EVP_CIPHER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(*b)));
+}
+
+static void collect_ciphers(EVP_CIPHER *cipher, void *stack)
+{
+ STACK_OF(EVP_CIPHER) *cipher_stack = stack;
+
+ if (is_cipher_fetchable(cipher)
+ && sk_EVP_CIPHER_push(cipher_stack, cipher) > 0)
+ EVP_CIPHER_up_ref(cipher);
+}
+
+static void list_ciphers(void)
+{
+ STACK_OF(EVP_CIPHER) *ciphers = sk_EVP_CIPHER_new(cipher_cmp);
+ int i;
+
+ if (ciphers == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ EVP_CIPHER_do_all_sorted(legacy_cipher_fn, bio_out);
+ }
+#endif
+
+ BIO_printf(bio_out, "Provided:\n");
+ EVP_CIPHER_do_all_provided(app_get0_libctx(), collect_ciphers, ciphers);
+ sk_EVP_CIPHER_sort(ciphers);
+ for (i = 0; i < sk_EVP_CIPHER_num(ciphers); i++) {
+ const EVP_CIPHER *c = sk_EVP_CIPHER_value(ciphers, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_CIPHER_is_a(c, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_CIPHER_names_do_all(c, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(c)));
+
+ if (verbose) {
+ const char *desc = EVP_CIPHER_get0_description(c);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_CIPHER_gettable_params(c), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_CIPHER_gettable_ctx_params(c), 4);
+ print_param_types("settable operation parameters",
+ EVP_CIPHER_settable_ctx_params(c), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_CIPHER_pop_free(ciphers, EVP_CIPHER_free);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+static void legacy_md_fn(const EVP_MD *m,
+ const char *from, const char *to, void *arg)
+{
+ if (m != NULL) {
+ BIO_printf(arg, " %s\n", EVP_MD_get0_name(m));
+ } else {
+ if (from == NULL)
+ from = "<undefined>";
+ if (to == NULL)
+ to = "<undefined>";
+ BIO_printf((BIO *)arg, " %s => %s\n", from, to);
+ }
+}
+#endif
+
+DEFINE_STACK_OF(EVP_MD)
+static int md_cmp(const EVP_MD * const *a, const EVP_MD * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(*b)));
+}
+
+static void collect_digests(EVP_MD *digest, void *stack)
+{
+ STACK_OF(EVP_MD) *digest_stack = stack;
+
+ if (is_digest_fetchable(digest)
+ && sk_EVP_MD_push(digest_stack, digest) > 0)
+ EVP_MD_up_ref(digest);
+}
+
+static void list_digests(void)
+{
+ STACK_OF(EVP_MD) *digests = sk_EVP_MD_new(md_cmp);
+ int i;
+
+ if (digests == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ EVP_MD_do_all_sorted(legacy_md_fn, bio_out);
+ }
+#endif
+
+ BIO_printf(bio_out, "Provided:\n");
+ EVP_MD_do_all_provided(app_get0_libctx(), collect_digests, digests);
+ sk_EVP_MD_sort(digests);
+ for (i = 0; i < sk_EVP_MD_num(digests); i++) {
+ const EVP_MD *m = sk_EVP_MD_value(digests, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_MD_is_a(m, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_MD_names_do_all(m, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(m)));
+
+ if (verbose) {
+ const char *desc = EVP_MD_get0_description(m);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_MD_gettable_params(m), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_MD_gettable_ctx_params(m), 4);
+ print_param_types("settable operation parameters",
+ EVP_MD_settable_ctx_params(m), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_MD_pop_free(digests, EVP_MD_free);
+}
+
+DEFINE_STACK_OF(EVP_MAC)
+static int mac_cmp(const EVP_MAC * const *a, const EVP_MAC * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(*b)));
+}
+
+static void collect_macs(EVP_MAC *mac, void *stack)
+{
+ STACK_OF(EVP_MAC) *mac_stack = stack;
+
+ if (is_mac_fetchable(mac)
+ && sk_EVP_MAC_push(mac_stack, mac) > 0)
+ EVP_MAC_up_ref(mac);
+}
+
+static void list_macs(void)
+{
+ STACK_OF(EVP_MAC) *macs = sk_EVP_MAC_new(mac_cmp);
+ int i;
+
+ if (macs == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided MACs:\n");
+ EVP_MAC_do_all_provided(app_get0_libctx(), collect_macs, macs);
+ sk_EVP_MAC_sort(macs);
+ for (i = 0; i < sk_EVP_MAC_num(macs); i++) {
+ const EVP_MAC *m = sk_EVP_MAC_value(macs, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_MAC_is_a(m, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_MAC_names_do_all(m, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(m)));
+
+ if (verbose) {
+ const char *desc = EVP_MAC_get0_description(m);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_MAC_gettable_params(m), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_MAC_gettable_ctx_params(m), 4);
+ print_param_types("settable operation parameters",
+ EVP_MAC_settable_ctx_params(m), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_MAC_pop_free(macs, EVP_MAC_free);
+}
+
+/*
+ * KDFs and PRFs
+ */
+DEFINE_STACK_OF(EVP_KDF)
+static int kdf_cmp(const EVP_KDF * const *a, const EVP_KDF * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(*b)));
+}
+
+static void collect_kdfs(EVP_KDF *kdf, void *stack)
+{
+ STACK_OF(EVP_KDF) *kdf_stack = stack;
+
+ if (is_kdf_fetchable(kdf)
+ && sk_EVP_KDF_push(kdf_stack, kdf) > 0)
+ EVP_KDF_up_ref(kdf);
+}
+
+static void list_kdfs(void)
+{
+ STACK_OF(EVP_KDF) *kdfs = sk_EVP_KDF_new(kdf_cmp);
+ int i;
+
+ if (kdfs == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided KDFs and PDFs:\n");
+ EVP_KDF_do_all_provided(app_get0_libctx(), collect_kdfs, kdfs);
+ sk_EVP_KDF_sort(kdfs);
+ for (i = 0; i < sk_EVP_KDF_num(kdfs); i++) {
+ const EVP_KDF *k = sk_EVP_KDF_value(kdfs, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KDF_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KDF_names_do_all(k, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_KDF_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_KDF_gettable_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KDF_gettable_ctx_params(k), 4);
+ print_param_types("settable operation parameters",
+ EVP_KDF_settable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KDF_pop_free(kdfs, EVP_KDF_free);
+}
+
+/*
+ * RANDs
+ */
+DEFINE_STACK_OF(EVP_RAND)
+
+static int rand_cmp(const EVP_RAND * const *a, const EVP_RAND * const *b)
+{
+ int ret = OPENSSL_strcasecmp(EVP_RAND_get0_name(*a), EVP_RAND_get0_name(*b));
+
+ if (ret == 0)
+ ret = strcmp(OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(*b)));
+
+ return ret;
+}
+
+static void collect_rands(EVP_RAND *rand, void *stack)
+{
+ STACK_OF(EVP_RAND) *rand_stack = stack;
+
+ if (is_rand_fetchable(rand)
+ && sk_EVP_RAND_push(rand_stack, rand) > 0)
+ EVP_RAND_up_ref(rand);
+}
+
+static void list_random_generators(void)
+{
+ STACK_OF(EVP_RAND) *rands = sk_EVP_RAND_new(rand_cmp);
+ int i;
+
+ if (rands == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided RNGs and seed sources:\n");
+ EVP_RAND_do_all_provided(app_get0_libctx(), collect_rands, rands);
+ sk_EVP_RAND_sort(rands);
+ for (i = 0; i < sk_EVP_RAND_num(rands); i++) {
+ const EVP_RAND *m = sk_EVP_RAND_value(rands, i);
+
+ if (select_name != NULL
+ && OPENSSL_strcasecmp(EVP_RAND_get0_name(m), select_name) != 0)
+ continue;
+ BIO_printf(bio_out, " %s", EVP_RAND_get0_name(m));
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(m)));
+
+ if (verbose) {
+ const char *desc = EVP_RAND_get0_description(m);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("retrievable algorithm parameters",
+ EVP_RAND_gettable_params(m), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_RAND_gettable_ctx_params(m), 4);
+ print_param_types("settable operation parameters",
+ EVP_RAND_settable_ctx_params(m), 4);
+ }
+ }
+ sk_EVP_RAND_pop_free(rands, EVP_RAND_free);
+}
+
+static void display_random(const char *name, EVP_RAND_CTX *drbg)
+{
+ EVP_RAND *rand;
+ uint64_t u;
+ const char *p;
+ const OSSL_PARAM *gettables;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ unsigned char buf[1000];
+
+ BIO_printf(bio_out, "%s:\n", name);
+ if (drbg != NULL) {
+ rand = EVP_RAND_CTX_get0_rand(drbg);
+
+ BIO_printf(bio_out, " %s", EVP_RAND_get0_name(rand));
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(rand)));
+
+ switch (EVP_RAND_get_state(drbg)) {
+ case EVP_RAND_STATE_UNINITIALISED:
+ p = "uninitialised";
+ break;
+ case EVP_RAND_STATE_READY:
+ p = "ready";
+ break;
+ case EVP_RAND_STATE_ERROR:
+ p = "error";
+ break;
+ default:
+ p = "unknown";
+ break;
+ }
+ BIO_printf(bio_out, " state = %s\n", p);
+
+ gettables = EVP_RAND_gettable_ctx_params(rand);
+ if (gettables != NULL)
+ for (; gettables->key != NULL; gettables++) {
+ /* State has been dealt with already, so ignore */
+ if (OPENSSL_strcasecmp(gettables->key, OSSL_RAND_PARAM_STATE) == 0)
+ continue;
+ /* Outside of verbose mode, we skip non-string values */
+ if (gettables->data_type != OSSL_PARAM_UTF8_STRING
+ && gettables->data_type != OSSL_PARAM_UTF8_PTR
+ && !verbose)
+ continue;
+ params->key = gettables->key;
+ params->data_type = gettables->data_type;
+ if (gettables->data_type == OSSL_PARAM_UNSIGNED_INTEGER
+ || gettables->data_type == OSSL_PARAM_INTEGER) {
+ params->data = &u;
+ params->data_size = sizeof(u);
+ } else {
+ params->data = buf;
+ params->data_size = sizeof(buf);
+ }
+ params->return_size = 0;
+ if (EVP_RAND_CTX_get_params(drbg, params))
+ print_param_value(params, 2);
+ }
+ }
+}
+
+static void list_random_instances(void)
+{
+ display_random("primary", RAND_get0_primary(NULL));
+ display_random("public", RAND_get0_public(NULL));
+ display_random("private", RAND_get0_private(NULL));
+}
+
+/*
+ * Encoders
+ */
+DEFINE_STACK_OF(OSSL_ENCODER)
+static int encoder_cmp(const OSSL_ENCODER * const *a,
+ const OSSL_ENCODER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(*b)));
+}
+
+static void collect_encoders(OSSL_ENCODER *encoder, void *stack)
+{
+ STACK_OF(OSSL_ENCODER) *encoder_stack = stack;
+
+ if (is_encoder_fetchable(encoder)
+ && sk_OSSL_ENCODER_push(encoder_stack, encoder) > 0)
+ OSSL_ENCODER_up_ref(encoder);
+}
+
+static void list_encoders(void)
+{
+ STACK_OF(OSSL_ENCODER) *encoders;
+ int i;
+
+ encoders = sk_OSSL_ENCODER_new(encoder_cmp);
+ if (encoders == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided ENCODERs:\n");
+ OSSL_ENCODER_do_all_provided(app_get0_libctx(), collect_encoders,
+ encoders);
+ sk_OSSL_ENCODER_sort(encoders);
+
+ for (i = 0; i < sk_OSSL_ENCODER_num(encoders); i++) {
+ OSSL_ENCODER *k = sk_OSSL_ENCODER_value(encoders, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !OSSL_ENCODER_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && OSSL_ENCODER_names_do_all(k, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s (%s)\n",
+ OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(k)),
+ OSSL_ENCODER_get0_properties(k));
+
+ if (verbose) {
+ const char *desc = OSSL_ENCODER_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ OSSL_ENCODER_settable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_OSSL_ENCODER_pop_free(encoders, OSSL_ENCODER_free);
+}
+
+/*
+ * Decoders
+ */
+DEFINE_STACK_OF(OSSL_DECODER)
+static int decoder_cmp(const OSSL_DECODER * const *a,
+ const OSSL_DECODER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(*b)));
+}
+
+static void collect_decoders(OSSL_DECODER *decoder, void *stack)
+{
+ STACK_OF(OSSL_DECODER) *decoder_stack = stack;
+
+ if (is_decoder_fetchable(decoder)
+ && sk_OSSL_DECODER_push(decoder_stack, decoder) > 0)
+ OSSL_DECODER_up_ref(decoder);
+}
+
+static void list_decoders(void)
+{
+ STACK_OF(OSSL_DECODER) *decoders;
+ int i;
+
+ decoders = sk_OSSL_DECODER_new(decoder_cmp);
+ if (decoders == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided DECODERs:\n");
+ OSSL_DECODER_do_all_provided(app_get0_libctx(), collect_decoders,
+ decoders);
+ sk_OSSL_DECODER_sort(decoders);
+
+ for (i = 0; i < sk_OSSL_DECODER_num(decoders); i++) {
+ OSSL_DECODER *k = sk_OSSL_DECODER_value(decoders, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !OSSL_DECODER_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && OSSL_DECODER_names_do_all(k, collect_names, names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s (%s)\n",
+ OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(k)),
+ OSSL_DECODER_get0_properties(k));
+
+ if (verbose) {
+ const char *desc = OSSL_DECODER_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ OSSL_DECODER_settable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_OSSL_DECODER_pop_free(decoders, OSSL_DECODER_free);
+}
+
+DEFINE_STACK_OF(EVP_KEYMGMT)
+static int keymanager_cmp(const EVP_KEYMGMT * const *a,
+ const EVP_KEYMGMT * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(*b)));
+}
+
+static void collect_keymanagers(EVP_KEYMGMT *km, void *stack)
+{
+ STACK_OF(EVP_KEYMGMT) *km_stack = stack;
+
+ if (is_keymgmt_fetchable(km)
+ && sk_EVP_KEYMGMT_push(km_stack, km) > 0)
+ EVP_KEYMGMT_up_ref(km);
+}
+
+static void list_keymanagers(void)
+{
+ int i;
+ STACK_OF(EVP_KEYMGMT) *km_stack = sk_EVP_KEYMGMT_new(keymanager_cmp);
+
+ EVP_KEYMGMT_do_all_provided(app_get0_libctx(), collect_keymanagers,
+ km_stack);
+ sk_EVP_KEYMGMT_sort(km_stack);
+
+ for (i = 0; i < sk_EVP_KEYMGMT_num(km_stack); i++) {
+ EVP_KEYMGMT *k = sk_EVP_KEYMGMT_value(km_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KEYMGMT_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KEYMGMT_names_do_all(k, collect_names, names)) {
+ const char *desc = EVP_KEYMGMT_get0_description(k);
+
+ BIO_printf(bio_out, " Name: ");
+ if (desc != NULL)
+ BIO_printf(bio_out, "%s", desc);
+ else
+ BIO_printf(bio_out, "%s", sk_OPENSSL_CSTRING_value(names, 0));
+ BIO_printf(bio_out, "\n");
+ BIO_printf(bio_out, " Type: Provider Algorithm\n");
+ BIO_printf(bio_out, " IDs: ");
+ print_names(bio_out, names);
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(k)));
+
+ if (verbose) {
+ print_param_types("settable key generation parameters",
+ EVP_KEYMGMT_gen_settable_params(k), 4);
+ print_param_types("settable operation parameters",
+ EVP_KEYMGMT_settable_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KEYMGMT_gettable_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KEYMGMT_pop_free(km_stack, EVP_KEYMGMT_free);
+}
+
+DEFINE_STACK_OF(EVP_SIGNATURE)
+static int signature_cmp(const EVP_SIGNATURE * const *a,
+ const EVP_SIGNATURE * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*b)));
+}
+
+static void collect_signatures(EVP_SIGNATURE *sig, void *stack)
+{
+ STACK_OF(EVP_SIGNATURE) *sig_stack = stack;
+
+ if (is_signature_fetchable(sig)
+ && sk_EVP_SIGNATURE_push(sig_stack, sig) > 0)
+ EVP_SIGNATURE_up_ref(sig);
+}
+
+static void list_signatures(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_SIGNATURE) *sig_stack = sk_EVP_SIGNATURE_new(signature_cmp);
+
+ EVP_SIGNATURE_do_all_provided(app_get0_libctx(), collect_signatures,
+ sig_stack);
+ sk_EVP_SIGNATURE_sort(sig_stack);
+
+ for (i = 0; i < sk_EVP_SIGNATURE_num(sig_stack); i++) {
+ EVP_SIGNATURE *k = sk_EVP_SIGNATURE_value(sig_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_SIGNATURE_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_SIGNATURE_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_SIGNATURE_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_SIGNATURE_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_SIGNATURE_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_SIGNATURE_pop_free(sig_stack, EVP_SIGNATURE_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+DEFINE_STACK_OF(EVP_KEM)
+static int kem_cmp(const EVP_KEM * const *a,
+ const EVP_KEM * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*b)));
+}
+
+static void collect_kem(EVP_KEM *kem, void *stack)
+{
+ STACK_OF(EVP_KEM) *kem_stack = stack;
+
+ if (is_kem_fetchable(kem)
+ && sk_EVP_KEM_push(kem_stack, kem) > 0)
+ EVP_KEM_up_ref(kem);
+}
+
+static void list_kems(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_KEM) *kem_stack = sk_EVP_KEM_new(kem_cmp);
+
+ EVP_KEM_do_all_provided(app_get0_libctx(), collect_kem, kem_stack);
+ sk_EVP_KEM_sort(kem_stack);
+
+ for (i = 0; i < sk_EVP_KEM_num(kem_stack); i++) {
+ EVP_KEM *k = sk_EVP_KEM_value(kem_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KEM_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KEM_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_KEM_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_KEM_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KEM_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KEM_pop_free(kem_stack, EVP_KEM_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+DEFINE_STACK_OF(EVP_ASYM_CIPHER)
+static int asymcipher_cmp(const EVP_ASYM_CIPHER * const *a,
+ const EVP_ASYM_CIPHER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(*b)));
+}
+
+static void collect_asymciph(EVP_ASYM_CIPHER *asym_cipher, void *stack)
+{
+ STACK_OF(EVP_ASYM_CIPHER) *asym_cipher_stack = stack;
+
+ if (is_asym_cipher_fetchable(asym_cipher)
+ && sk_EVP_ASYM_CIPHER_push(asym_cipher_stack, asym_cipher) > 0)
+ EVP_ASYM_CIPHER_up_ref(asym_cipher);
+}
+
+static void list_asymciphers(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_ASYM_CIPHER) *asymciph_stack =
+ sk_EVP_ASYM_CIPHER_new(asymcipher_cmp);
+
+ EVP_ASYM_CIPHER_do_all_provided(app_get0_libctx(), collect_asymciph,
+ asymciph_stack);
+ sk_EVP_ASYM_CIPHER_sort(asymciph_stack);
+
+ for (i = 0; i < sk_EVP_ASYM_CIPHER_num(asymciph_stack); i++) {
+ EVP_ASYM_CIPHER *k = sk_EVP_ASYM_CIPHER_value(asymciph_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_ASYM_CIPHER_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL
+ && EVP_ASYM_CIPHER_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_ASYM_CIPHER_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_ASYM_CIPHER_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_ASYM_CIPHER_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_ASYM_CIPHER_pop_free(asymciph_stack, EVP_ASYM_CIPHER_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+DEFINE_STACK_OF(EVP_KEYEXCH)
+static int kex_cmp(const EVP_KEYEXCH * const *a,
+ const EVP_KEYEXCH * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(*b)));
+}
+
+static void collect_kex(EVP_KEYEXCH *kex, void *stack)
+{
+ STACK_OF(EVP_KEYEXCH) *kex_stack = stack;
+
+ if (is_keyexch_fetchable(kex)
+ && sk_EVP_KEYEXCH_push(kex_stack, kex) > 0)
+ EVP_KEYEXCH_up_ref(kex);
+}
+
+static void list_keyexchanges(void)
+{
+ int i, count = 0;
+ STACK_OF(EVP_KEYEXCH) *kex_stack = sk_EVP_KEYEXCH_new(kex_cmp);
+
+ EVP_KEYEXCH_do_all_provided(app_get0_libctx(), collect_kex, kex_stack);
+ sk_EVP_KEYEXCH_sort(kex_stack);
+
+ for (i = 0; i < sk_EVP_KEYEXCH_num(kex_stack); i++) {
+ EVP_KEYEXCH *k = sk_EVP_KEYEXCH_value(kex_stack, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !EVP_KEYEXCH_is_a(k, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && EVP_KEYEXCH_names_do_all(k, collect_names, names)) {
+ count++;
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(k)));
+
+ if (verbose) {
+ const char *desc = EVP_KEYEXCH_get0_description(k);
+
+ if (desc != NULL)
+ BIO_printf(bio_out, " description: %s\n", desc);
+ print_param_types("settable operation parameters",
+ EVP_KEYEXCH_settable_ctx_params(k), 4);
+ print_param_types("retrievable operation parameters",
+ EVP_KEYEXCH_gettable_ctx_params(k), 4);
+ }
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_EVP_KEYEXCH_pop_free(kex_stack, EVP_KEYEXCH_free);
+ if (count == 0)
+ BIO_printf(bio_out, " -\n");
+}
+
+static void list_objects(void)
+{
+ int max_nid = OBJ_new_nid(0);
+ int i;
+ char *oid_buf = NULL;
+ int oid_size = 0;
+
+ /* Skip 0, since that's NID_undef */
+ for (i = 1; i < max_nid; i++) {
+ const ASN1_OBJECT *obj = OBJ_nid2obj(i);
+ const char *sn = OBJ_nid2sn(i);
+ const char *ln = OBJ_nid2ln(i);
+ int n = 0;
+
+ /*
+ * If one of the retrieved objects somehow generated an error,
+ * we ignore it. The check for NID_undef below will detect the
+ * error and simply skip to the next NID.
+ */
+ ERR_clear_error();
+
+ if (OBJ_obj2nid(obj) == NID_undef)
+ continue;
+
+ if ((n = OBJ_obj2txt(NULL, 0, obj, 1)) == 0) {
+ BIO_printf(bio_out, "# None-OID object: %s, %s\n", sn, ln);
+ continue;
+ }
+ if (n < 0)
+ break; /* Error */
+
+ if (n > oid_size) {
+ oid_buf = OPENSSL_realloc(oid_buf, n + 1);
+ if (oid_buf == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ break; /* Error */
+ }
+ oid_size = n + 1;
+ }
+ if (OBJ_obj2txt(oid_buf, oid_size, obj, 1) < 0)
+ break; /* Error */
+ if (ln == NULL || strcmp(sn, ln) == 0)
+ BIO_printf(bio_out, "%s = %s\n", sn, oid_buf);
+ else
+ BIO_printf(bio_out, "%s = %s, %s\n", sn, ln, oid_buf);
+ }
+
+ OPENSSL_free(oid_buf);
+}
+
+static void list_options_for_command(const char *command)
+{
+ const FUNCTION *fp;
+ const OPTIONS *o;
+
+ 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++) {
+ char c = o->valtype;
+
+ if (o->name == OPT_PARAM_STR)
+ break;
+
+ if (o->name == OPT_HELP_STR
+ || o->name == OPT_MORE_STR
+ || o->name == OPT_SECTION_STR
+ || o->name[0] == '\0')
+ continue;
+ BIO_printf(bio_out, "%s %c\n", o->name, c == '\0' ? '-' : c);
+ }
+ /* Always output the -- marker since it is sometimes documented. */
+ BIO_printf(bio_out, "- -\n");
+}
+
+static int is_md_available(const char *name)
+{
+ EVP_MD *md;
+ const char *propq = app_get0_propq();
+
+ /* Look through providers' digests */
+ ERR_set_mark();
+ md = EVP_MD_fetch(app_get0_libctx(), name, propq);
+ ERR_pop_to_mark();
+ if (md != NULL) {
+ EVP_MD_free(md);
+ return 1;
+ }
+
+ return propq != NULL || get_digest_from_engine(name) == NULL ? 0 : 1;
+}
+
+static int is_cipher_available(const char *name)
+{
+ EVP_CIPHER *cipher;
+ const char *propq = app_get0_propq();
+
+ /* Look through providers' ciphers */
+ ERR_set_mark();
+ cipher = EVP_CIPHER_fetch(app_get0_libctx(), name, propq);
+ ERR_pop_to_mark();
+ if (cipher != NULL) {
+ EVP_CIPHER_free(cipher);
+ return 1;
+ }
+
+ return propq != NULL || get_cipher_from_engine(name) == NULL ? 0 : 1;
+}
+
+static void list_type(FUNC_TYPE ft, int one)
+{
+ FUNCTION *fp;
+ int i = 0;
+ DISPLAY_COLUMNS dc;
+
+ memset(&dc, 0, sizeof(dc));
+ if (!one)
+ calculate_columns(functions, &dc);
+
+ for (fp = functions; fp->name != NULL; fp++) {
+ if (fp->type != ft)
+ continue;
+ switch (ft) {
+ case FT_cipher:
+ if (!is_cipher_available(fp->name))
+ continue;
+ break;
+ case FT_md:
+ if (!is_md_available(fp->name))
+ continue;
+ break;
+ default:
+ break;
+ }
+ 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 void list_pkey(void)
+{
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ int i;
+
+ if (select_name == NULL && include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ int pkey_id, pkey_base_id, pkey_flags;
+ const char *pinfo, *pem_str;
+ ameth = EVP_PKEY_asn1_get0(i);
+ EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
+ &pinfo, &pem_str, ameth);
+ if (pkey_flags & ASN1_PKEY_ALIAS) {
+ 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(bio_out, " Name: %s\n", pinfo);
+ BIO_printf(bio_out, "\tType: %s Algorithm\n",
+ pkey_flags & ASN1_PKEY_DYNAMIC ?
+ "External" : "Builtin");
+ BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
+ if (pem_str == NULL)
+ pem_str = "(none)";
+ BIO_printf(bio_out, "\tPEM string: %s\n", pem_str);
+ }
+ }
+ }
+#endif
+ BIO_printf(bio_out, "Provided:\n");
+ BIO_printf(bio_out, " Key Managers:\n");
+ list_keymanagers();
+}
+
+static void list_pkey_meth(void)
+{
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ size_t i;
+ size_t meth_count = EVP_PKEY_meth_get_count();
+
+ if (select_name == NULL && include_legacy()) {
+ BIO_printf(bio_out, "Legacy:\n");
+ 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");
+ }
+ }
+#endif
+ BIO_printf(bio_out, "Provided:\n");
+ BIO_printf(bio_out, " Encryption:\n");
+ list_asymciphers();
+ BIO_printf(bio_out, " Key Exchange:\n");
+ list_keyexchanges();
+ BIO_printf(bio_out, " Signatures:\n");
+ list_signatures();
+ BIO_printf(bio_out, " Key encapsulation:\n");
+ list_kems();
+}
+
+DEFINE_STACK_OF(OSSL_STORE_LOADER)
+static int store_cmp(const OSSL_STORE_LOADER * const *a,
+ const OSSL_STORE_LOADER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(*a)),
+ OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(*b)));
+}
+
+static void collect_store_loaders(OSSL_STORE_LOADER *store, void *stack)
+{
+ STACK_OF(OSSL_STORE_LOADER) *store_stack = stack;
+
+ if (sk_OSSL_STORE_LOADER_push(store_stack, store) > 0)
+ OSSL_STORE_LOADER_up_ref(store);
+}
+
+static void list_store_loaders(void)
+{
+ STACK_OF(OSSL_STORE_LOADER) *stores = sk_OSSL_STORE_LOADER_new(store_cmp);
+ int i;
+
+ if (stores == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Provided STORE LOADERs:\n");
+ OSSL_STORE_LOADER_do_all_provided(app_get0_libctx(), collect_store_loaders,
+ stores);
+ sk_OSSL_STORE_LOADER_sort(stores);
+ for (i = 0; i < sk_OSSL_STORE_LOADER_num(stores); i++) {
+ const OSSL_STORE_LOADER *m = sk_OSSL_STORE_LOADER_value(stores, i);
+ STACK_OF(OPENSSL_CSTRING) *names = NULL;
+
+ if (select_name != NULL && !OSSL_STORE_LOADER_is_a(m, select_name))
+ continue;
+
+ names = sk_OPENSSL_CSTRING_new(name_cmp);
+ if (names != NULL && OSSL_STORE_LOADER_names_do_all(m, collect_names,
+ names)) {
+ BIO_printf(bio_out, " ");
+ print_names(bio_out, names);
+
+ BIO_printf(bio_out, " @ %s\n",
+ OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(m)));
+ }
+ sk_OPENSSL_CSTRING_free(names);
+ }
+ sk_OSSL_STORE_LOADER_pop_free(stores, OSSL_STORE_LOADER_free);
+}
+
+DEFINE_STACK_OF(OSSL_PROVIDER)
+static int provider_cmp(const OSSL_PROVIDER * const *a,
+ const OSSL_PROVIDER * const *b)
+{
+ return strcmp(OSSL_PROVIDER_get0_name(*a), OSSL_PROVIDER_get0_name(*b));
+}
+
+static int collect_providers(OSSL_PROVIDER *provider, void *stack)
+{
+ STACK_OF(OSSL_PROVIDER) *provider_stack = stack;
+
+ sk_OSSL_PROVIDER_push(provider_stack, provider);
+ return 1;
+}
+
+static void list_provider_info(void)
+{
+ STACK_OF(OSSL_PROVIDER) *providers = sk_OSSL_PROVIDER_new(provider_cmp);
+ OSSL_PARAM params[5];
+ char *name, *version, *buildinfo;
+ int status;
+ int i;
+
+ if (providers == NULL) {
+ BIO_printf(bio_err, "ERROR: Memory allocation\n");
+ return;
+ }
+ BIO_printf(bio_out, "Providers:\n");
+ OSSL_PROVIDER_do_all(NULL, &collect_providers, providers);
+ sk_OSSL_PROVIDER_sort(providers);
+ for (i = 0; i < sk_OSSL_PROVIDER_num(providers); i++) {
+ const OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(providers, i);
+
+ /* Query the "known" information parameters, the order matches below */
+ params[0] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_NAME,
+ &name, 0);
+ params[1] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION,
+ &version, 0);
+ params[2] = OSSL_PARAM_construct_int(OSSL_PROV_PARAM_STATUS, &status);
+ params[3] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_BUILDINFO,
+ &buildinfo, 0);
+ params[4] = OSSL_PARAM_construct_end();
+ OSSL_PARAM_set_all_unmodified(params);
+ if (!OSSL_PROVIDER_get_params(prov, params)) {
+ BIO_printf(bio_err, "ERROR: Unable to query provider parameters\n");
+ return;
+ }
+
+ /* Print out the provider information, the params order matches above */
+ BIO_printf(bio_out, " %s\n", OSSL_PROVIDER_get0_name(prov));
+ if (OSSL_PARAM_modified(params))
+ BIO_printf(bio_out, " name: %s\n", name);
+ if (OSSL_PARAM_modified(params + 1))
+ BIO_printf(bio_out, " version: %s\n", version);
+ if (OSSL_PARAM_modified(params + 2))
+ BIO_printf(bio_out, " status: %sactive\n", status ? "" : "in");
+ if (verbose) {
+ if (OSSL_PARAM_modified(params + 3))
+ BIO_printf(bio_out, " build info: %s\n", buildinfo);
+ print_param_types("gettable provider parameters",
+ OSSL_PROVIDER_gettable_params(prov), 4);
+ }
+ }
+ sk_OSSL_PROVIDER_free(providers);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+static void list_engines(void)
+{
+# ifndef OPENSSL_NO_ENGINE
+ ENGINE *e;
+
+ BIO_puts(bio_out, "Engines:\n");
+ e = ENGINE_get_first();
+ while (e) {
+ BIO_printf(bio_out, "%s\n", ENGINE_get_id(e));
+ e = ENGINE_get_next(e);
+ }
+# else
+ BIO_puts(bio_out, "Engine support is disabled.\n");
+# endif
+}
+#endif
+
+static void list_disabled(void)
+{
+ 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
+#if defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
+ BIO_puts(bio_out, "ENGINE\n");
+#endif
+#ifdef OPENSSL_NO_GOST
+ BIO_puts(bio_out, "GOST\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_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
+}
+
+/* Unified enum for help and list commands. */
+typedef enum HELPLIST_CHOICE {
+ OPT_COMMON,
+ OPT_ONE, OPT_VERBOSE,
+ OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_MAC_ALGORITHMS, OPT_OPTIONS,
+ OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
+ OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED,
+ OPT_KDF_ALGORITHMS, OPT_RANDOM_INSTANCES, OPT_RANDOM_GENERATORS,
+ OPT_ENCODERS, OPT_DECODERS, OPT_KEYMANAGERS, OPT_KEYEXCHANGE_ALGORITHMS,
+ OPT_KEM_ALGORITHMS, OPT_SIGNATURE_ALGORITHMS, OPT_ASYM_CIPHER_ALGORITHMS,
+ OPT_STORE_LOADERS, OPT_PROVIDER_INFO,
+ OPT_OBJECTS, OPT_SELECT_NAME,
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ OPT_ENGINES,
+#endif
+ OPT_PROV_ENUM
+} HELPLIST_CHOICE;
+
+const OPTIONS list_options[] = {
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
+ {"1", OPT_ONE, '-', "List in one column"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose listing"},
+ {"select", OPT_SELECT_NAME, 's', "Select a single algorithm"},
+ {"commands", OPT_COMMANDS, '-', "List of standard commands"},
+ {"standard-commands", OPT_COMMANDS, '-', "List of standard commands"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"digest-commands", OPT_DIGEST_COMMANDS, '-',
+ "List of message digest commands (deprecated)"},
+#endif
+ {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-',
+ "List of message digest algorithms"},
+ {"kdf-algorithms", OPT_KDF_ALGORITHMS, '-',
+ "List of key derivation and pseudo random function algorithms"},
+ {"random-instances", OPT_RANDOM_INSTANCES, '-',
+ "List the primary, public and private random number generator details"},
+ {"random-generators", OPT_RANDOM_GENERATORS, '-',
+ "List of random number generators"},
+ {"mac-algorithms", OPT_MAC_ALGORITHMS, '-',
+ "List of message authentication code algorithms"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"cipher-commands", OPT_CIPHER_COMMANDS, '-',
+ "List of cipher commands (deprecated)"},
+#endif
+ {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-',
+ "List of symmetric cipher algorithms"},
+ {"encoders", OPT_ENCODERS, '-', "List of encoding methods" },
+ {"decoders", OPT_DECODERS, '-', "List of decoding methods" },
+ {"key-managers", OPT_KEYMANAGERS, '-', "List of key managers" },
+ {"key-exchange-algorithms", OPT_KEYEXCHANGE_ALGORITHMS, '-',
+ "List of key exchange algorithms" },
+ {"kem-algorithms", OPT_KEM_ALGORITHMS, '-',
+ "List of key encapsulation mechanism algorithms" },
+ {"signature-algorithms", OPT_SIGNATURE_ALGORITHMS, '-',
+ "List of signature algorithms" },
+ {"asymcipher-algorithms", OPT_ASYM_CIPHER_ALGORITHMS, '-',
+ "List of asymmetric cipher algorithms" },
+ {"public-key-algorithms", OPT_PK_ALGORITHMS, '-',
+ "List of public key algorithms"},
+ {"public-key-methods", OPT_PK_METHOD, '-',
+ "List of public key methods"},
+ {"store-loaders", OPT_STORE_LOADERS, '-',
+ "List of store loaders"},
+ {"providers", OPT_PROVIDER_INFO, '-',
+ "List of provider information"},
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ {"engines", OPT_ENGINES, '-',
+ "List of loaded engines"},
+#endif
+ {"disabled", OPT_DISABLED, '-', "List of disabled features"},
+ {"options", OPT_OPTIONS, 's',
+ "List options for specified command"},
+ {"objects", OPT_OBJECTS, '-',
+ "List built in objects (OID<->name mappings)"},
+
+ OPT_PROV_OPTIONS,
+ {NULL}
+};
+
+int list_main(int argc, char **argv)
+{
+ char *prog;
+ HELPLIST_CHOICE o;
+ int one = 0, done = 0;
+ struct {
+ unsigned int commands:1;
+ unsigned int random_instances:1;
+ unsigned int random_generators:1;
+ unsigned int digest_commands:1;
+ unsigned int digest_algorithms:1;
+ unsigned int kdf_algorithms:1;
+ unsigned int mac_algorithms:1;
+ unsigned int cipher_commands:1;
+ unsigned int cipher_algorithms:1;
+ unsigned int encoder_algorithms:1;
+ unsigned int decoder_algorithms:1;
+ unsigned int keymanager_algorithms:1;
+ unsigned int signature_algorithms:1;
+ unsigned int keyexchange_algorithms:1;
+ unsigned int kem_algorithms:1;
+ unsigned int asym_cipher_algorithms:1;
+ unsigned int pk_algorithms:1;
+ unsigned int pk_method:1;
+ unsigned int store_loaders:1;
+ unsigned int provider_info:1;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ unsigned int engines:1;
+#endif
+ unsigned int disabled:1;
+ unsigned int objects:1;
+ unsigned int options:1;
+ } todo = { 0, };
+
+ verbose = 0; /* Clear a possible previous call */
+
+ 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);
+ return 0;
+ case OPT_ONE:
+ one = 1;
+ break;
+ case OPT_COMMANDS:
+ todo.commands = 1;
+ break;
+ case OPT_DIGEST_COMMANDS:
+ todo.digest_commands = 1;
+ break;
+ case OPT_DIGEST_ALGORITHMS:
+ todo.digest_algorithms = 1;
+ break;
+ case OPT_KDF_ALGORITHMS:
+ todo.kdf_algorithms = 1;
+ break;
+ case OPT_RANDOM_INSTANCES:
+ todo.random_instances = 1;
+ break;
+ case OPT_RANDOM_GENERATORS:
+ todo.random_generators = 1;
+ break;
+ case OPT_MAC_ALGORITHMS:
+ todo.mac_algorithms = 1;
+ break;
+ case OPT_CIPHER_COMMANDS:
+ todo.cipher_commands = 1;
+ break;
+ case OPT_CIPHER_ALGORITHMS:
+ todo.cipher_algorithms = 1;
+ break;
+ case OPT_ENCODERS:
+ todo.encoder_algorithms = 1;
+ break;
+ case OPT_DECODERS:
+ todo.decoder_algorithms = 1;
+ break;
+ case OPT_KEYMANAGERS:
+ todo.keymanager_algorithms = 1;
+ break;
+ case OPT_SIGNATURE_ALGORITHMS:
+ todo.signature_algorithms = 1;
+ break;
+ case OPT_KEYEXCHANGE_ALGORITHMS:
+ todo.keyexchange_algorithms = 1;
+ break;
+ case OPT_KEM_ALGORITHMS:
+ todo.kem_algorithms = 1;
+ break;
+ case OPT_ASYM_CIPHER_ALGORITHMS:
+ todo.asym_cipher_algorithms = 1;
+ break;
+ case OPT_PK_ALGORITHMS:
+ todo.pk_algorithms = 1;
+ break;
+ case OPT_PK_METHOD:
+ todo.pk_method = 1;
+ break;
+ case OPT_STORE_LOADERS:
+ todo.store_loaders = 1;
+ break;
+ case OPT_PROVIDER_INFO:
+ todo.provider_info = 1;
+ break;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ case OPT_ENGINES:
+ todo.engines = 1;
+ break;
+#endif
+ case OPT_DISABLED:
+ todo.disabled = 1;
+ break;
+ case OPT_OBJECTS:
+ todo.objects = 1;
+ break;
+ case OPT_OPTIONS:
+ list_options_for_command(opt_arg());
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
+ case OPT_SELECT_NAME:
+ select_name = opt_arg();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ return 1;
+ break;
+ }
+ done = 1;
+ }
+
+ /* No extra arguments. */
+ if (opt_num_rest() != 0)
+ goto opthelp;
+
+ if (todo.commands)
+ list_type(FT_general, one);
+ if (todo.random_instances)
+ list_random_instances();
+ if (todo.random_generators)
+ list_random_generators();
+ if (todo.digest_commands)
+ list_type(FT_md, one);
+ if (todo.digest_algorithms)
+ list_digests();
+ if (todo.kdf_algorithms)
+ list_kdfs();
+ if (todo.mac_algorithms)
+ list_macs();
+ if (todo.cipher_commands)
+ list_type(FT_cipher, one);
+ if (todo.cipher_algorithms)
+ list_ciphers();
+ if (todo.encoder_algorithms)
+ list_encoders();
+ if (todo.decoder_algorithms)
+ list_decoders();
+ if (todo.keymanager_algorithms)
+ list_keymanagers();
+ if (todo.signature_algorithms)
+ list_signatures();
+ if (todo.asym_cipher_algorithms)
+ list_asymciphers();
+ if (todo.keyexchange_algorithms)
+ list_keyexchanges();
+ if (todo.kem_algorithms)
+ list_kems();
+ if (todo.pk_algorithms)
+ list_pkey();
+ if (todo.pk_method)
+ list_pkey_meth();
+ if (todo.store_loaders)
+ list_store_loaders();
+ if (todo.provider_info)
+ list_provider_info();
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (todo.engines)
+ list_engines();
+#endif
+ if (todo.disabled)
+ list_disabled();
+ if (todo.objects)
+ list_objects();
+
+ if (!done)
+ goto opthelp;
+
+ return 0;
+}
diff --git a/apps/mac.c b/apps/mac.c
new file mode 100644
index 000000000000..a9b6a265f49a
--- /dev/null
+++ b/apps/mac.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+
+#undef BUFSIZE
+#define BUFSIZE 1024*8
+
+typedef enum OPTION_choice {
+ OPT_COMMON,
+ OPT_MACOPT, OPT_BIN, OPT_IN, OPT_OUT,
+ OPT_CIPHER, OPT_DIGEST,
+ OPT_PROV_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS mac_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] mac_name\n"},
+
+ OPT_SECTION("General"),
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form"},
+ {"cipher", OPT_CIPHER, 's', "Cipher"},
+ {"digest", OPT_DIGEST, 's', "Digest"},
+ {OPT_MORE_STR, 1, '-', "See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file to MAC (default is stdin)"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
+ {"binary", OPT_BIN, '-',
+ "Output in binary format (default is hexadecimal)"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"mac_name", 0, 0, "MAC algorithm"},
+ {NULL}
+};
+
+static char *alloc_mac_algorithm_name(STACK_OF(OPENSSL_STRING) **optp,
+ const char *name, const char *arg)
+{
+ size_t len = strlen(name) + strlen(arg) + 2;
+ char *res;
+
+ if (*optp == NULL)
+ *optp = sk_OPENSSL_STRING_new_null();
+ if (*optp == NULL)
+ return NULL;
+
+ res = app_malloc(len, "algorithm name");
+ BIO_snprintf(res, len, "%s:%s", name, arg);
+ if (sk_OPENSSL_STRING_push(*optp, res))
+ return res;
+ OPENSSL_free(res);
+ return NULL;
+}
+
+int mac_main(int argc, char **argv)
+{
+ int ret = 1;
+ char *prog;
+ EVP_MAC *mac = NULL;
+ OPTION_CHOICE o;
+ EVP_MAC_CTX *ctx = NULL;
+ STACK_OF(OPENSSL_STRING) *opts = NULL;
+ unsigned char *buf = NULL;
+ size_t len;
+ int i;
+ BIO *in = NULL, *out = NULL;
+ const char *outfile = NULL;
+ const char *infile = NULL;
+ int out_bin = 0;
+ int inform = FORMAT_BINARY;
+ char *digest = NULL, *cipher = NULL;
+ OSSL_PARAM *params = NULL;
+
+ prog = opt_init(argc, argv, mac_options);
+ buf = app_malloc(BUFSIZE, "I/O buffer");
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ default:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto err;
+ case OPT_HELP:
+ opt_help(mac_options);
+ ret = 0;
+ goto err;
+ case OPT_BIN:
+ out_bin = 1;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_MACOPT:
+ if (opts == NULL)
+ opts = sk_OPENSSL_STRING_new_null();
+ if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_CIPHER:
+ OPENSSL_free(cipher);
+ cipher = alloc_mac_algorithm_name(&opts, "cipher", opt_arg());
+ if (cipher == NULL)
+ goto opthelp;
+ break;
+ case OPT_DIGEST:
+ OPENSSL_free(digest);
+ digest = alloc_mac_algorithm_name(&opts, "digest", opt_arg());
+ if (digest == NULL)
+ goto opthelp;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto err;
+ break;
+ }
+ }
+
+ /* One argument, the MAC name. */
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc != 1)
+ goto opthelp;
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), argv[0], app_get0_propq());
+ if (mac == NULL) {
+ BIO_printf(bio_err, "Invalid MAC name %s\n", argv[0]);
+ goto opthelp;
+ }
+
+ ctx = EVP_MAC_CTX_new(mac);
+ if (ctx == NULL)
+ goto err;
+
+ if (opts != NULL) {
+ int ok = 1;
+
+ params = app_params_new_from_opts(opts,
+ EVP_MAC_settable_ctx_params(mac));
+ if (params == NULL)
+ goto err;
+
+ if (!EVP_MAC_CTX_set_params(ctx, params)) {
+ BIO_printf(bio_err, "MAC parameter error\n");
+ ERR_print_errors(bio_err);
+ ok = 0;
+ }
+ app_params_free(params);
+ if (!ok)
+ goto err;
+ }
+
+ in = bio_open_default(infile, 'r', inform);
+ if (in == NULL)
+ goto err;
+
+ out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
+ if (out == NULL)
+ goto err;
+
+ if (!EVP_MAC_init(ctx, NULL, 0, NULL)) {
+ BIO_printf(bio_err, "EVP_MAC_Init failed\n");
+ goto err;
+ }
+
+ while (BIO_pending(in) || !BIO_eof(in)) {
+ i = BIO_read(in, (char *)buf, BUFSIZE);
+ if (i < 0) {
+ BIO_printf(bio_err, "Read Error in '%s'\n", infile);
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+ if (i == 0)
+ break;
+ if (!EVP_MAC_update(ctx, buf, i)) {
+ BIO_printf(bio_err, "EVP_MAC_update failed\n");
+ goto err;
+ }
+ }
+
+ if (!EVP_MAC_final(ctx, NULL, &len, 0)) {
+ BIO_printf(bio_err, "EVP_MAC_final failed\n");
+ goto err;
+ }
+ if (len > BUFSIZE) {
+ BIO_printf(bio_err, "output len is too large\n");
+ goto err;
+ }
+
+ if (!EVP_MAC_final(ctx, buf, &len, BUFSIZE)) {
+ BIO_printf(bio_err, "EVP_MAC_final failed\n");
+ goto err;
+ }
+
+ if (out_bin) {
+ BIO_write(out, buf, len);
+ } else {
+ for (i = 0; i < (int)len; ++i)
+ BIO_printf(out, "%02X", buf[i]);
+ if (outfile == NULL)
+ BIO_printf(out,"\n");
+ }
+
+ ret = 0;
+err:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ OPENSSL_clear_free(buf, BUFSIZE);
+ OPENSSL_free(cipher);
+ OPENSSL_free(digest);
+ sk_OPENSSL_STRING_free(opts);
+ BIO_free(in);
+ BIO_free(out);
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(mac);
+ return ret;
+}
diff --git a/apps/nseq.c b/apps/nseq.c
index a067c915926f..d5524370f26c 100644
--- a/apps/nseq.c
+++ b/apps/nseq.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -15,15 +15,23 @@
#include <openssl/err.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_TOSEQ, OPT_IN, OPT_OUT
+ OPT_COMMON,
+ OPT_TOSEQ, OPT_IN, OPT_OUT,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS nseq_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"},
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
+
+ OPT_SECTION("Output"),
+ {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"},
{"out", OPT_OUT, '>', "Output file"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -57,8 +65,14 @@ int nseq_main(int argc, char **argv)
case OPT_OUT:
outfile = opt_arg();
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -77,8 +91,10 @@ int nseq_main(int argc, char **argv)
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);
+ while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
+ if (!sk_X509_push(seq->certs, x509))
+ goto end;
+ }
if (!sk_X509_num(seq->certs)) {
BIO_printf(bio_err, "%s: Error reading certs file %s\n",
diff --git a/apps/ocsp.c b/apps/ocsp.c
index 8f20864cea51..821e224c6ce4 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -1,7 +1,7 @@
/*
* Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -10,8 +10,8 @@
#include <openssl/opensslconf.h>
#ifdef OPENSSL_SYS_VMS
-# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined
- * on OpenVMS */
+ /* So fd_set and friends get properly defined on OpenVMS */
+# define _XOPEN_SOURCE_EXTENDED
#endif
#include <stdio.h>
@@ -22,6 +22,7 @@
/* Needs to be included before the openssl headers */
#include "apps.h"
+#include "http_server.h"
#include "progs.h"
#include "internal/sockets.h"
#include <openssl/e_os2.h>
@@ -31,37 +32,11 @@
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
-#include <openssl/rand.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 HAVE_FORK
-#undef NO_FORK
-#else
-#define NO_FORK
-#endif
-
-#if !defined(NO_FORK) && !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
+#if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_fork)>
+# endif
#endif
#if defined(OPENSSL_SYS_VXWORKS)
@@ -87,7 +62,7 @@ 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 void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
+static int 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);
@@ -96,76 +71,118 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
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);
+ int nmin, int ndays, int badsig,
+ const EVP_MD *resp_md);
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, int timeout);
-static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
-static void log_message(int level, const char *fmt, ...);
+static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
+ const char *port, int timeout);
+static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp);
static char *prog;
-static int multi = 0;
-#ifdef OCSP_DAEMON
-static int acfd = (int) INVALID_SOCKET;
+#ifdef HTTP_DAEMON
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 socket_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
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT,
+#ifndef OPENSSL_NO_SOCK
+ OPT_PROXY, OPT_NO_PROXY,
+#endif
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_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE,
+ OPT_NOCAPATH, OPT_NOCASTORE,
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_PASSIN,
+ OPT_RCID,
OPT_V_ENUM,
OPT_MD,
- OPT_MULTI
+ OPT_MULTI, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ocsp_options[] = {
+ OPT_SECTION("General"),
{"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"},
+ {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
+ {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"},
+ {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+
+ OPT_SECTION("Responder"),
+ {"timeout", OPT_TIMEOUT, 'p',
+ "Connection timeout (in seconds) to the OCSP responder"},
{"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
+#ifdef HTTP_DAEMON
{"multi", OPT_MULTI, 'p', "run multiple responder processes"},
#endif
{"no_certs", OPT_NO_CERTS, '-',
"Don't include any certificates in signed request"},
+ {"badsig", OPT_BADSIG, '-',
+ "Corrupt last byte of loaded OCSP response signature (for test)"},
+ {"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)"},
+ {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"},
+ {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"},
+ {"sign_other", OPT_SIGN_OTHER, '<',
+ "Additional certificates to include in signed request"},
+ {"index", OPT_INDEX, '<', "Certificate status index file"},
+ {"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"},
+ {"passin", OPT_PASSIN, 's', "Responder key pass phrase source"},
+ {"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"},
+ {"rcid", OPT_RCID, 's', "Use specified algorithm for cert id in response"},
+ {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"},
+
+ OPT_SECTION("Client"),
+ {"url", OPT_URL, 's', "Responder URL"},
+ {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"},
+ {"port", OPT_PORT, 'N', "Port to run responder on"},
+ {"path", OPT_PATH, 's', "Path to use in OCSP request"},
+#ifndef OPENSSL_NO_SOCK
+ {"proxy", OPT_PROXY, 's',
+ "[http[s]://]host[:port][/path] of HTTP(S) proxy to use; path is ignored"},
+ {"no_proxy", OPT_NO_PROXY, 's',
+ "List of addresses of servers not to use HTTP(S) proxy for"},
+ {OPT_MORE_STR, 0, 0,
+ "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
+#endif
+ {"out", OPT_OUTFILE, '>', "Output filename"},
+ {"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"},
{"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-',
"Don't check signature on response"},
+ {"resp_key_id", OPT_RESP_KEY_ID, '-',
+ "Identify response by signing certificate key ID"},
{"no_cert_verify", OPT_NO_CERT_VERIFY, '-',
"Don't check signing certificate"},
+ {"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"},
{"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"},
@@ -175,57 +192,29 @@ const OPTIONS ocsp_options[] = {
"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 OCSP 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"},
+ {"cert", OPT_CERT, '<', "Certificate to check"},
+ {"serial", OPT_SERIAL, 's', "Serial number to check"},
{"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, ... )"},
+ {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
+
OPT_V_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
int ocsp_main(int argc, char **argv)
{
BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
- const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
+ EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
STACK_OF(OPENSSL_STRING) *rsign_sigopts = NULL;
int trailing_md = 0;
CA_DB *rdb = NULL;
@@ -240,35 +229,37 @@ int ocsp_main(int argc, char **argv)
STACK_OF(X509) *issuers = NULL;
X509 *issuer = NULL, *cert = NULL;
STACK_OF(X509) *rca_cert = NULL;
+ EVP_MD *resp_certid_md = NULL;
X509 *signer = NULL, *rsigner = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
- const char *CAfile = NULL, *CApath = NULL;
- char *header, *value;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
+ char *header, *value, *respdigname = NULL;
char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
+#ifndef OPENSSL_NO_SOCK
+ char *opt_proxy = NULL;
+ char *opt_no_proxy = NULL;
+#endif
char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
char *rsignfile = NULL, *rkeyfile = NULL;
+ char *passinarg = NULL, *passin = 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 noCAfile = 0, noCApath = 0, noCAstore = 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_text = 0, resp_text = 0, res, ret = 1;
int req_timeout = -1;
long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
OPTION_CHOICE o;
- reqnames = sk_OPENSSL_STRING_new_null();
- if (reqnames == NULL)
- goto end;
- ids = sk_OCSP_CERTID_new_null();
- if (ids == NULL)
+ if ((reqnames = sk_OPENSSL_STRING_new_null()) == NULL
+ || (ids = sk_OCSP_CERTID_new_null()) == NULL
+ || (vpm = X509_VERIFY_PARAM_new()) == 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) {
@@ -295,8 +286,10 @@ int ocsp_main(int argc, char **argv)
OPENSSL_free(tport);
OPENSSL_free(tpath);
thost = tport = tpath = NULL;
- if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
- BIO_printf(bio_err, "%s Error parsing URL\n", prog);
+ if (!OSSL_HTTP_parse_url(opt_arg(), &use_ssl, NULL /* userinfo */,
+ &host, &port, NULL /* port_num */,
+ &path, NULL /* qry */, NULL /* frag */)) {
+ BIO_printf(bio_err, "%s Error parsing -url argument\n", prog);
goto end;
}
thost = host;
@@ -309,6 +302,17 @@ int ocsp_main(int argc, char **argv)
case OPT_PORT:
port = opt_arg();
break;
+ case OPT_PATH:
+ path = opt_arg();
+ break;
+#ifndef OPENSSL_NO_SOCK
+ case OPT_PROXY:
+ opt_proxy = opt_arg();
+ break;
+ case OPT_NO_PROXY:
+ opt_no_proxy = opt_arg();
+ break;
+#endif
case OPT_IGNORE_ERR:
ignore_err = 1;
break;
@@ -388,12 +392,18 @@ int ocsp_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
@@ -414,26 +424,24 @@ int ocsp_main(int argc, char **argv)
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");
+ issuer = load_cert(opt_arg(), FORMAT_UNDEF, "issuer certificate");
if (issuer == NULL)
goto end;
if (issuers == NULL) {
if ((issuers = sk_X509_new_null()) == NULL)
goto end;
}
- sk_X509_push(issuers, issuer);
+ if (!sk_X509_push(issuers, issuer))
+ goto end;
break;
case OPT_CERT:
X509_free(cert);
- cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
+ cert = load_cert(opt_arg(), FORMAT_UNDEF, "certificate");
if (cert == NULL)
goto end;
if (cert_id_md == NULL)
- cert_id_md = EVP_sha1();
+ cert_id_md = (EVP_MD *)EVP_sha1();
if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
goto end;
if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
@@ -442,7 +450,7 @@ int ocsp_main(int argc, char **argv)
break;
case OPT_SERIAL:
if (cert_id_md == NULL)
- cert_id_md = EVP_sha1();
+ cert_id_md = (EVP_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()))
@@ -456,12 +464,12 @@ int ocsp_main(int argc, char **argv)
rca_filename = opt_arg();
break;
case OPT_NMIN:
- opt_int(opt_arg(), &nmin);
+ nmin = opt_int_arg();
if (ndays == -1)
ndays = 0;
break;
case OPT_REQUEST:
- opt_int(opt_arg(), &accept_count);
+ accept_count = opt_int_arg();
break;
case OPT_NDAYS:
ndays = atoi(opt_arg());
@@ -472,17 +480,20 @@ int ocsp_main(int argc, char **argv)
case OPT_RKEY:
rkeyfile = opt_arg();
break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
case OPT_ROTHER:
rcertfile = opt_arg();
break;
case OPT_RMD: /* Response MessageDigest */
- if (!opt_md(opt_arg(), &rsign_md))
- goto end;
+ respdigname = opt_arg();
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()))
+ if (rsign_sigopts == NULL
+ || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg()))
goto end;
break;
case OPT_HEADER:
@@ -496,6 +507,10 @@ int ocsp_main(int argc, char **argv)
if (!X509V3_add_value(header, value, &headers))
goto end;
break;
+ case OPT_RCID:
+ if (!opt_md(opt_arg(), &resp_certid_md))
+ goto opthelp;
+ break;
case OPT_MD:
if (trailing_md) {
BIO_printf(bio_err,
@@ -508,20 +523,32 @@ int ocsp_main(int argc, char **argv)
trailing_md = 1;
break;
case OPT_MULTI:
-#ifdef OCSP_DAEMON
+#ifdef HTTP_DAEMON
multi = atoi(opt_arg());
#endif
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
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 (respdigname != NULL) {
+ if (!opt_md(respdigname, &rsign_md))
+ goto end;
+ }
/* Have we anything to do? */
if (req == NULL && reqin == NULL
@@ -548,28 +575,36 @@ int ocsp_main(int argc, char **argv)
}
if (req == NULL && port != NULL) {
- acbio = init_responder(port);
+#ifndef OPENSSL_NO_SOCK
+ acbio = http_server_init_bio(prog, port);
if (acbio == NULL)
goto end;
+#else
+ BIO_printf(bio_err, "Cannot act as server - sockets not supported\n");
+ goto end;
+#endif
}
if (rsignfile != NULL) {
if (rkeyfile == NULL)
rkeyfile = rsignfile;
- rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
+ rsigner = load_cert(rsignfile, FORMAT_UNDEF, "responder certificate");
if (rsigner == NULL) {
BIO_printf(bio_err, "Error loading responder certificate\n");
goto end;
}
- if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM,
- NULL, "CA certificate"))
+ if (!load_certs(rca_filename, 0, &rca_cert, NULL, "CA certificates"))
goto end;
if (rcertfile != NULL) {
- if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
+ if (!load_certs(rcertfile, 0, &rother, NULL,
"responder other certificates"))
goto end;
}
- rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+ rkey = load_key(rkeyfile, FORMAT_UNDEF, 0, passin, NULL,
"responder private key");
if (rkey == NULL)
goto end;
@@ -585,25 +620,28 @@ int ocsp_main(int argc, char **argv)
if (ridx_filename != NULL) {
rdb = load_index(ridx_filename, NULL);
if (rdb == NULL || index_index(rdb) <= 0) {
+ BIO_printf(bio_err,
+ "Problem with index file: %s (could not load/parse file)\n",
+ ridx_filename);
ret = 1;
goto end;
}
}
-#ifdef OCSP_DAEMON
+#ifdef HTTP_DAEMON
if (multi && acbio != NULL)
- spawn_loop();
+ spawn_loop(prog);
if (acbio != NULL && req_timeout > 0)
signal(SIGALRM, socket_timeout);
#endif
if (acbio != NULL)
- log_message(LOG_INFO, "waiting for OCSP client connections...");
+ log_message(prog, LOG_INFO, "waiting for OCSP client connections...");
redo_accept:
if (acbio != NULL) {
-#ifdef OCSP_DAEMON
+#ifdef HTTP_DAEMON
if (index_changed(rdb)) {
CA_DB *newrdb = load_index(ridx_filename, NULL);
@@ -612,21 +650,24 @@ redo_accept:
rdb = newrdb;
} else {
free_index(newrdb);
- log_message(LOG_ERR, "error reloading updated index: %s",
+ log_message(prog, LOG_ERR, "error reloading updated index: %s",
ridx_filename);
}
}
#endif
req = NULL;
- if (!do_responder(&req, &cbio, acbio, req_timeout))
+ res = do_responder(&req, &cbio, acbio, port, req_timeout);
+ if (res == 0)
goto redo_accept;
if (req == NULL) {
- resp =
- OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
- NULL);
- send_ocsp_response(cbio, resp);
+ if (res == 1) {
+ resp =
+ OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
+ NULL);
+ send_ocsp_response(cbio, resp);
+ }
goto done_resp;
}
}
@@ -646,23 +687,23 @@ redo_accept:
if (signfile != NULL) {
if (keyfile == NULL)
keyfile = signfile;
- signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
+ signer = load_cert(signfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL) {
BIO_printf(bio_err, "Error loading signer certificate\n");
goto end;
}
if (sign_certfile != NULL) {
- if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
+ if (!load_certs(sign_certfile, 0, &sign_other, NULL,
"signer certificates"))
goto end;
}
- key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
+ key = load_key(keyfile, FORMAT_UNDEF, 0, NULL, NULL,
"signer private key");
if (key == NULL)
goto end;
- if (!OCSP_request_sign
- (req, signer, key, NULL, sign_other, sign_flags)) {
+ if (!OCSP_request_sign(req, signer, key, NULL,
+ sign_other, sign_flags)) {
BIO_printf(bio_err, "Error signing OCSP request\n");
goto end;
}
@@ -681,18 +722,21 @@ redo_accept:
if (rdb != NULL) {
make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey,
- rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig);
+ rsign_md, rsign_sigopts, rother, rflags, nmin, ndays,
+ badsig, resp_certid_md);
+ if (resp == NULL)
+ goto end;
if (cbio != NULL)
send_ocsp_response(cbio, resp);
} else if (host != NULL) {
#ifndef OPENSSL_NO_SOCK
- resp = process_responder(req, host, path,
- port, use_ssl, headers, req_timeout);
+ resp = process_responder(req, host, port, path, opt_proxy, opt_no_proxy,
+ use_ssl, headers, req_timeout);
if (resp == NULL)
goto end;
#else
BIO_printf(bio_err,
- "Error creating connect BIO - sockets not supported.\n");
+ "Error creating connect BIO - sockets not supported\n");
goto end;
#endif
} else if (respin != NULL) {
@@ -752,15 +796,16 @@ redo_accept:
}
if (store == NULL) {
- store = setup_verify(CAfile, CApath, noCAfile, noCApath);
+ store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore);
if (!store)
goto end;
}
if (vpmtouched)
X509_STORE_set1_param(store, vpm);
if (verify_certfile != NULL) {
- if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
- "validator certificate"))
+ if (!load_certs(verify_certfile, 0, &verify_other, NULL,
+ "validator certificates"))
goto end;
}
@@ -798,7 +843,8 @@ redo_accept:
}
}
- print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);
+ if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
+ ret = 1;
end:
ERR_print_errors(bio_err);
@@ -808,6 +854,9 @@ redo_accept:
sk_OPENSSL_STRING_free(rsign_sigopts);
EVP_PKEY_free(key);
EVP_PKEY_free(rkey);
+ EVP_MD_free(cert_id_md);
+ EVP_MD_free(rsign_md);
+ EVP_MD_free(resp_certid_md);
X509_free(cert);
sk_X509_pop_free(issuers, X509_free);
X509_free(rsigner);
@@ -831,41 +880,7 @@ redo_accept:
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;
-}
+#ifdef HTTP_DAEMON
static int index_changed(CA_DB *rdb)
{
@@ -883,131 +898,6 @@ static int index_changed(CA_DB *rdb)
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);
- OPENSSL_free(kidpids);
- sleep(1);
- exit(ret);
-}
-
-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 */
- OPENSSL_free(kidpids);
- 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;
- }
- }
-
- /* 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,
@@ -1041,7 +931,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
STACK_OF(OCSP_CERTID) *ids)
{
OCSP_CERTID *id;
- X509_NAME *iname;
+ const X509_NAME *iname;
ASN1_BIT_STRING *ikey;
ASN1_INTEGER *sno;
@@ -1073,7 +963,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
return 0;
}
-static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
+static int 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)
@@ -1082,10 +972,13 @@ static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
const char *name;
int i, status, reason;
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ int ret = 1;
- if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names)
- || !sk_OCSP_CERTID_num(ids))
- return;
+ if (req == NULL || !sk_OPENSSL_STRING_num(names))
+ return 1;
+
+ if (bs == NULL || !sk_OCSP_CERTID_num(ids))
+ return 0;
for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) {
id = sk_OCSP_CERTID_value(ids, i);
@@ -1095,6 +988,7 @@ static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
if (!OCSP_resp_find_status(bs, id, &status, &reason,
&rev, &thisupd, &nextupd)) {
BIO_puts(out, "ERROR: No Status found.\n");
+ ret = 0;
continue;
}
@@ -1128,6 +1022,7 @@ static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
ASN1_GENERALIZEDTIME_print(out, rev);
BIO_puts(out, "\n");
}
+ return ret;
}
static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req,
@@ -1135,7 +1030,8 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
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)
+ int nmin, int ndays, int badsig,
+ const EVP_MD *resp_md)
{
ASN1_TIME *thisupd = NULL, *nextupd = NULL;
OCSP_CERTID *cid;
@@ -1166,6 +1062,8 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
int found = 0;
ASN1_OBJECT *cert_id_md_oid;
const EVP_MD *cert_id_md;
+ OCSP_CERTID *cid_resp_md = NULL;
+
one = OCSP_request_onereq_get0(req, i);
cid = OCSP_onereq_get0_id(one);
@@ -1181,11 +1079,18 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
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)
+ if (OCSP_id_issuer_cmp(ca_id, cid) == 0) {
found = 1;
-
+ if (resp_md != NULL)
+ cid_resp_md = OCSP_cert_to_id(resp_md, NULL, ca_cert);
+ }
OCSP_CERTID_free(ca_id);
}
+ OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
+ inf = lookup_serial(db, serial);
+
+ /* at this point, we can have cid be an alias of cid_resp_md */
+ cid = (cid_resp_md != NULL) ? cid_resp_md : cid;
if (!found) {
OCSP_basic_add1_status(bs, cid,
@@ -1193,8 +1098,6 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
0, NULL, thisupd, nextupd);
continue;
}
- OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
- inf = lookup_serial(db, serial);
if (inf == NULL) {
OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_UNKNOWN,
@@ -1209,10 +1112,16 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
ASN1_GENERALIZEDTIME *invtm = NULL;
OCSP_SINGLERESP *single;
int reason = -1;
+
unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
single = OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_REVOKED,
reason, revtm, thisupd, nextupd);
+ if (single == NULL) {
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
+ NULL);
+ goto end;
+ }
if (invtm != NULL)
OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date,
invtm, 0, 0);
@@ -1224,6 +1133,7 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
ASN1_TIME_free(revtm);
ASN1_GENERALIZEDTIME_free(invtm);
}
+ OCSP_CERTID_free(cid_resp_md);
}
OCSP_copy_nonce(bs, req);
@@ -1273,10 +1183,12 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
bn = ASN1_INTEGER_to_BN(ser, NULL);
OPENSSL_assert(bn); /* FIXME: should report an error at this
* point and abort */
- if (BN_is_zero(bn))
+ if (BN_is_zero(bn)) {
itmp = OPENSSL_strdup("00");
- else
+ OPENSSL_assert(itmp);
+ } else {
itmp = BN_bn2hex(bn);
+ }
row[DB_serial] = itmp;
BN_free(bn);
rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
@@ -1284,339 +1196,66 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
return rrow;
}
-/* Quick and dirty OCSP server: read in and parse input request */
-
-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 == NULL)
- goto err;
- 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) {
- log_message(LOG_ERR, "Error starting accept");
- goto err;
- }
-
- return acbio;
-
- err:
- 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 socket_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,
- int timeout)
+ const char *port, int timeout)
{
-#ifdef OPENSSL_NO_SOCK
- return 0;
+#ifndef OPENSSL_NO_SOCK
+ return http_server_get_asn1_req(ASN1_ITEM_rptr(OCSP_REQUEST),
+ (ASN1_VALUE **)preq, NULL, pcbio, acbio,
+ NULL /* found_keep_alive */,
+ prog, port, 1 /* accept_get */, timeout);
#else
- int len;
- OCSP_REQUEST *req = NULL;
- char inbuf[2048], reqbuf[2048];
- char *p, *q;
- BIO *cbio = NULL, *getbio = NULL, *b64 = NULL;
- const char *client;
-
+ BIO_printf(bio_err,
+ "Error getting OCSP request - sockets not supported\n");
*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. Note:
- * 'p' was incremented above to point to the first byte *after* the
- * leading slash, so with 'GET / ' it is now an empty string.
- */
- if (p[0] == '\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)
- goto out;
- if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
- break;
- }
-
-# ifdef OCSP_DAEMON
- /* Clear alarm before we close the client socket */
- alarm(0);
- timeout = 0;
-# endif
-
- /* 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;
+ return 0;
#endif
}
-static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
+static int send_ocsp_response(BIO *cbio, const 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 == NULL)
- return 0;
- BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
- i2d_OCSP_RESPONSE_bio(cbio, resp);
- (void)BIO_flush(cbio);
- return 1;
-}
-
#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;
- struct timeval tv;
-
- if (req_timeout != -1)
- BIO_set_nbio(cbio, 1);
-
- rv = BIO_do_connect(cbio);
-
- if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
- BIO_puts(bio_err, "Error connecting BIO\n");
- return NULL;
- }
-
- if (BIO_get_fd(cbio, &fd) < 0) {
- BIO_puts(bio_err, "Can't get connection fd\n");
- goto err;
- }
-
- if (req_timeout != -1 && rv <= 0) {
- FD_ZERO(&confds);
- openssl_fdset(fd, &confds);
- tv.tv_usec = 0;
- tv.tv_sec = req_timeout;
- rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
- if (rv == 0) {
- BIO_puts(bio_err, "Timeout on connect\n");
- return NULL;
- }
- }
-
- ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
- 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;
-
- for (;;) {
- rv = OCSP_sendreq_nbio(&rsp, ctx);
- if (rv != -1)
- break;
- if (req_timeout == -1)
- continue;
- FD_ZERO(&confds);
- openssl_fdset(fd, &confds);
- tv.tv_usec = 0;
- tv.tv_sec = req_timeout;
- if (BIO_should_read(cbio)) {
- rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
- } else if (BIO_should_write(cbio)) {
- rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
- } else {
- BIO_puts(bio_err, "Unexpected retry condition\n");
- goto err;
- }
- if (rv == 0) {
- BIO_puts(bio_err, "Timeout on request\n");
- break;
- }
- if (rv == -1) {
- BIO_puts(bio_err, "Select error\n");
- break;
- }
-
- }
- err:
- OCSP_REQ_CTX_free(ctx);
-
- return rsp;
+ return http_server_send_asn1_resp(cbio,
+ 0 /* no keep-alive */,
+ "application/ocsp-response",
+ ASN1_ITEM_rptr(OCSP_RESPONSE),
+ (const ASN1_VALUE *)resp);
+#else
+ BIO_printf(bio_err,
+ "Error sending OCSP response - sockets not supported\n");
+ return 0;
+#endif
}
-OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
- const char *host, const char *path,
- const char *port, int use_ssl,
- STACK_OF(CONF_VALUE) *headers,
+#ifndef OPENSSL_NO_SOCK
+OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host,
+ const char *port, const char *path,
+ const char *proxy, const char *no_proxy,
+ int use_ssl, 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 == NULL) {
- BIO_printf(bio_err, "Error creating connect BIO\n");
- goto end;
- }
- if (port != NULL)
- BIO_set_conn_port(cbio, port);
if (use_ssl == 1) {
- BIO *sbio;
ctx = SSL_CTX_new(TLS_client_method());
if (ctx == NULL) {
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(cbio, host, path, headers, req, req_timeout);
+ resp = (OCSP_RESPONSE *)
+ app_http_post_asn1(host, port, path, proxy, no_proxy,
+ ctx, headers, "application/ocsp-request",
+ (ASN1_VALUE *)req, ASN1_ITEM_rptr(OCSP_REQUEST),
+ "application/ocsp-response",
+ req_timeout, ASN1_ITEM_rptr(OCSP_RESPONSE));
+
if (resp == NULL)
BIO_printf(bio_err, "Error querying OCSP responder\n");
+
end:
- BIO_free_all(cbio);
SSL_CTX_free(ctx);
return resp;
}
diff --git a/apps/openssl.c b/apps/openssl.c
index f35d57f2648c..a3056c799f85 100644
--- a/apps/openssl.c
+++ b/apps/openssl.c
@@ -1,18 +1,18 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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>
#include <openssl/bio.h>
#include <openssl/crypto.h>
+#include <openssl/trace.h>
#include <openssl/lhash.h>
#include <openssl/conf.h>
#include <openssl/x509.h>
@@ -27,20 +27,8 @@
# 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
* the base prototypes (we cast each variable inside the function to the
@@ -49,32 +37,27 @@ typedef struct {
*/
static LHASH_OF(FUNCTION) *prog_init(void);
static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]);
-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;
BIO *bio_in = NULL;
BIO *bio_out = NULL;
BIO *bio_err = NULL;
-static void calculate_columns(DISPLAY_COLUMNS *dc)
+static void warn_deprecated(const FUNCTION *fp)
{
- FUNCTION *f;
- int len, maxlen = 0;
-
- 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;
-
- dc->width = maxlen + 2;
- dc->columns = (80 - 1) / dc->width;
+ if (fp->deprecated_version != NULL)
+ BIO_printf(bio_err, "The command %s was deprecated in version %s.",
+ fp->name, fp->deprecated_version);
+ else
+ BIO_printf(bio_err, "The command %s is deprecated.", fp->name);
+ if (strcmp(fp->deprecated_alternative, DEPRECATED_NO_ALTERNATIVE) != 0)
+ BIO_printf(bio_err, " Use '%s' instead.", fp->deprecated_alternative);
+ BIO_printf(bio_err, "\n");
}
static int apps_startup(void)
{
+ const char *use_libctx = NULL;
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
@@ -84,53 +67,186 @@ static int apps_startup(void)
| OPENSSL_INIT_LOAD_CONFIG, NULL))
return 0;
- setup_ui_method();
+ (void)setup_ui_method();
+ (void)setup_engine_loader();
+
+ /*
+ * NOTE: This is an undocumented feature required for testing only.
+ * There are no guarantees that it will exist in future builds.
+ */
+ use_libctx = getenv("OPENSSL_TEST_LIBCTX");
+ if (use_libctx != NULL) {
+ /* Set this to "1" to create a global libctx */
+ if (strcmp(use_libctx, "1") == 0) {
+ if (app_create_libctx() == NULL)
+ return 0;
+ }
+ }
return 1;
}
static void apps_shutdown(void)
{
+ app_providers_cleanup();
+ OSSL_LIB_CTX_free(app_get0_libctx());
+ destroy_engine_loader();
destroy_ui_method();
- destroy_prefix_method();
}
-static char *make_config_name(void)
+
+#ifndef OPENSSL_NO_TRACE
+typedef struct tracedata_st {
+ BIO *bio;
+ unsigned int ingroup:1;
+} tracedata;
+
+static size_t internal_trace_cb(const char *buf, size_t cnt,
+ int category, int cmd, void *vdata)
{
- 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);
+ int ret = 0;
+ tracedata *trace_data = vdata;
+ char buffer[256], *hex;
+ CRYPTO_THREAD_ID tid;
+
+ switch (cmd) {
+ case OSSL_TRACE_CTRL_BEGIN:
+ if (trace_data->ingroup) {
+ BIO_printf(bio_err, "ERROR: tracing already started\n");
+ return 0;
+ }
+ trace_data->ingroup = 1;
+
+ tid = CRYPTO_THREAD_get_current_id();
+ hex = OPENSSL_buf2hexstr((const unsigned char *)&tid, sizeof(tid));
+ BIO_snprintf(buffer, sizeof(buffer), "TRACE[%s]:%s: ",
+ hex == NULL ? "<null>" : hex,
+ OSSL_trace_get_category_name(category));
+ OPENSSL_free(hex);
+ BIO_set_prefix(trace_data->bio, buffer);
+ break;
+ case OSSL_TRACE_CTRL_WRITE:
+ if (!trace_data->ingroup) {
+ BIO_printf(bio_err, "ERROR: writing when tracing not started\n");
+ return 0;
+ }
+
+ ret = BIO_write(trace_data->bio, buf, cnt);
+ break;
+ case OSSL_TRACE_CTRL_END:
+ if (!trace_data->ingroup) {
+ BIO_printf(bio_err, "ERROR: finishing when tracing not started\n");
+ return 0;
+ }
+ trace_data->ingroup = 0;
+
+ BIO_set_prefix(trace_data->bio, NULL);
+
+ break;
+ }
+
+ return ret < 0 ? 0 : ret;
+}
+
+DEFINE_STACK_OF(tracedata)
+static STACK_OF(tracedata) *trace_data_stack;
- return p;
+static void tracedata_free(tracedata *data)
+{
+ BIO_free_all(data->bio);
+ OPENSSL_free(data);
}
+static STACK_OF(tracedata) *trace_data_stack;
+
+static void cleanup_trace(void)
+{
+ sk_tracedata_pop_free(trace_data_stack, tracedata_free);
+}
+
+static void setup_trace_category(int category)
+{
+ BIO *channel;
+ tracedata *trace_data;
+ BIO *bio = NULL;
+
+ if (OSSL_trace_enabled(category))
+ return;
+
+ bio = BIO_new(BIO_f_prefix());
+ channel = BIO_push(bio, dup_bio_err(FORMAT_TEXT));
+ trace_data = OPENSSL_zalloc(sizeof(*trace_data));
+
+ if (trace_data == NULL
+ || bio == NULL
+ || (trace_data->bio = channel) == NULL
+ || OSSL_trace_set_callback(category, internal_trace_cb,
+ trace_data) == 0
+ || sk_tracedata_push(trace_data_stack, trace_data) == 0) {
+
+ fprintf(stderr,
+ "warning: unable to setup trace callback for category '%s'.\n",
+ OSSL_trace_get_category_name(category));
+
+ OSSL_trace_set_callback(category, NULL, NULL);
+ BIO_free_all(channel);
+ }
+}
+
+static void setup_trace(const char *str)
+{
+ char *val;
+
+ /*
+ * We add this handler as early as possible to ensure it's executed
+ * as late as possible, i.e. after the TRACE code has done its cleanup
+ * (which happens last in OPENSSL_cleanup).
+ */
+ atexit(cleanup_trace);
+
+ trace_data_stack = sk_tracedata_new_null();
+ val = OPENSSL_strdup(str);
+
+ if (val != NULL) {
+ char *valp = val;
+ char *item;
+
+ for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) {
+ int category = OSSL_trace_get_category_num(item);
+
+ if (category == OSSL_TRACE_CATEGORY_ALL) {
+ while (++category < OSSL_TRACE_CATEGORY_NUM)
+ setup_trace_category(category);
+ break;
+ } else if (category > 0) {
+ setup_trace_category(category);
+ } else {
+ fprintf(stderr,
+ "warning: unknown trace category: '%s'.\n", item);
+ }
+ }
+ }
+
+ OPENSSL_free(val);
+}
+#endif /* OPENSSL_NO_TRACE */
+
+static char *help_argv[] = { "help", NULL };
+
int main(int argc, char *argv[])
{
FUNCTION f, *fp;
LHASH_OF(FUNCTION) *prog = NULL;
- char *p, *pname;
- char buf[1024];
- const char *prompt;
+ char *pname;
+ const char *fname;
ARGS arg;
- int first, n, i, ret = 0;
+ int global_help = 0;
+ int ret = 0;
arg.argv = NULL;
arg.size = 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);
@@ -138,319 +254,75 @@ int main(int argc, char *argv[])
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
argv = copy_argv(&argc, argv);
#elif defined(_WIN32)
- /*
- * Replace argv[] with UTF-8 encoded strings.
- */
+ /* Replace argv[] with UTF-8 encoded strings. */
win32_utf8argv(&argc, &argv);
#endif
- 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 (getenv("OPENSSL_FIPS")) {
- BIO_printf(bio_err, "FIPS mode not supported.\n");
- return 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;
- }
+#ifndef OPENSSL_NO_TRACE
+ setup_trace(getenv("OPENSSL_TRACE"));
+#endif
- prog = prog_init();
- if (prog == NULL) {
+ if ((fname = "apps_startup", !apps_startup())
+ || (fname = "prog_init", (prog = prog_init()) == NULL)) {
BIO_printf(bio_err,
- "FATAL: Startup failure (dev note: prog_init() failed)\n");
+ "FATAL: Startup failure (dev note: %s()) for %s\n",
+ fname, argv[0]);
ERR_print_errors(bio_err);
ret = 1;
goto end;
}
pname = opt_progname(argv[0]);
+ default_config_file = CONF_get1_default_config_file();
+ if (default_config_file == NULL)
+ app_bail_out("%s: could not get default config file\n", pname);
+
/* first check the program name */
f.name = pname;
fp = lh_FUNCTION_retrieve(prog, &f);
- if (fp != NULL) {
- argv[0] = pname;
- ret = fp->func(argc, argv);
- goto end;
- }
-
- /* If there is stuff on the command line, run with that. */
- if (argc != 1) {
+ if (fp == NULL) {
+ /* We assume we've been called as 'openssl ...' */
+ global_help = argc > 1
+ && (strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0
+ || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0);
argc--;
argv++;
- ret = do_cmd(prog, argc, argv);
- if (ret < 0)
- ret = 0;
- goto end;
+ opt_appname(argc == 1 || global_help ? "help" : argv[0]);
+ } else {
+ argv[0] = pname;
}
- /* ok, lets enter interactive mode */
- for (;;) {
- ret = 0;
- /* 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';
-#ifndef READLINE
- fputs(prompt, stdout);
- fflush(stdout);
- if (!fgets(p, n, stdin))
- goto end;
- if (p[0] == '\0')
- goto end;
- i = strlen(p);
- if (i <= 1)
- break;
- if (p[i - 2] != '\\')
- break;
- 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 there's a command, run with that, otherwise "help". */
+ ret = argc == 0 || global_help
+ ? do_cmd(prog, 1, help_argv)
+ : do_cmd(prog, argc, argv);
- if (!chopup_args(&arg, buf)) {
- BIO_printf(bio_err, "Can't parse (no memory?)\n");
- break;
- }
-
- 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", arg.argv[0]);
- (void)BIO_flush(bio_out);
- (void)BIO_flush(bio_err);
- }
- ret = 1;
end:
OPENSSL_free(default_config_file);
lh_FUNCTION_free(prog);
OPENSSL_free(arg.argv);
- app_RAND_write();
+ if (!app_RAND_write())
+ ret = EXIT_FAILURE;
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);
+ BIO_free_all(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);
- }
-}
-
-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);
- }
-}
-
-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;
-
- 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);
- }
-}
-
-
-/* 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"},
+ {OPT_HELP_STR, 1, '-', "Usage: help [options] [command]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_hHELP, '-', "Display this summary"},
+
+ OPT_PARAMETERS(),
+ {"command", 0, 0, "Name of command to display help (optional)"},
{NULL}
};
@@ -463,6 +335,7 @@ int help_main(int argc, char **argv)
char *prog;
HELP_CHOICE o;
DISPLAY_COLUMNS dc;
+ char *new_argv[3];
prog = opt_init(argc, argv, help_options);
while ((o = opt_next()) != OPT_hEOF) {
@@ -477,9 +350,8 @@ int help_main(int argc, char **argv)
}
}
+ /* One optional argument, the command to get help for. */
if (opt_num_rest() == 1) {
- char *new_argv[3];
-
new_argv[0] = opt_rest()[0];
new_argv[1] = "--help";
new_argv[2] = NULL;
@@ -490,8 +362,8 @@ int help_main(int argc, char **argv)
return 1;
}
- calculate_columns(&dc);
- BIO_printf(bio_err, "Standard commands");
+ calculate_columns(functions, &dc);
+ BIO_printf(bio_err, "%s:\n\nStandard commands", prog);
i = 0;
tp = FT_none;
for (fp = functions; fp->name != NULL; fp++) {
@@ -520,37 +392,13 @@ int help_main(int argc, char **argv)
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;
if (argc <= 0 || argv[0] == NULL)
return 0;
+ memset(&f, 0, sizeof(f));
f.name = argv[0];
fp = lh_FUNCTION_retrieve(prog, &f);
if (fp == NULL) {
@@ -565,6 +413,8 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
}
}
if (fp != NULL) {
+ if (fp->deprecated_alternative != NULL)
+ warn_deprecated(fp);
return fp->func(argc, argv);
}
if ((strncmp(argv[0], "no-", 3)) == 0) {
@@ -580,61 +430,12 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
BIO_printf(bio_out, "%s\n", argv[0] + 3);
return 1;
}
- 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;
BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
argv[0]);
return 1;
}
-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;
- const char *pinfo, *pem_str;
- ameth = EVP_PKEY_asn1_get0(i);
- EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
- &pinfo, &pem_str, ameth);
- if (pkey_flags & ASN1_PKEY_ALIAS) {
- 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(bio_out, "Name: %s\n", pinfo);
- BIO_printf(bio_out, "\tType: %s Algorithm\n",
- pkey_flags & ASN1_PKEY_DYNAMIC ?
- "External" : "Builtin");
- BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
- if (pem_str == NULL)
- pem_str = "(none)";
- BIO_printf(bio_out, "\tPEM string: %s\n", pem_str);
- }
-
- }
-}
-
-static void list_pkey_meth(void)
-{
- 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 int function_cmp(const FUNCTION * a, const FUNCTION * b)
{
return strncmp(a->name, b->name, 8);
@@ -655,155 +456,6 @@ static int SortFnByName(const void *_f1, const void *_f2)
return strcmp(f1->name, f2->name);
}
-static void list_disabled(void)
-{
- 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 LHASH_OF(FUNCTION) *prog_init(void)
{
static LHASH_OF(FUNCTION) *ret = NULL;
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index 4acca4b0446f..03330e0120a2 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -1,7 +1,9 @@
#
# OpenSSL example configuration file.
-# This is mostly being used for generation of certificate requests.
+# See doc/man5/config.pod for more info.
#
+# This is mostly being used for generation of certificate requests,
+# but may be used for auto loading of providers
# Note that you can include other files from the main configuration
# file using the .include directive.
@@ -11,9 +13,15 @@
# defined.
HOME = .
+ # Use this in order to automatically load providers.
+openssl_conf = openssl_init
+
+# Comment out the next line to ignore configuration errors
+config_diagnostics = 1
+
# Extra OBJECT IDENTIFIER info:
-#oid_file = $ENV::HOME/.oid
-oid_section = new_oids
+# oid_file = $ENV::HOME/.oid
+oid_section = new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
@@ -23,7 +31,6 @@ oid_section = new_oids
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
-
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
@@ -35,6 +42,36 @@ tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
+# For FIPS
+# Optionally include a file that is generated by the OpenSSL fipsinstall
+# application. This file contains configuration data required by the OpenSSL
+# fips provider. It contains a named section e.g. [fips_sect] which is
+# referenced from the [provider_sect] below.
+# Refer to the OpenSSL security policy for more information.
+# .include fipsmodule.cnf
+
+[openssl_init]
+providers = provider_sect
+
+# List of providers to load
+[provider_sect]
+default = default_sect
+# The fips section name should match the section name inside the
+# included fipsmodule.cnf.
+# fips = fips_sect
+
+# If no providers are activated explicitly, the default one is activated implicitly.
+# See man 7 OSSL_PROVIDER-default for more details.
+#
+# If you add a section explicitly activating any other provider(s), you most
+# probably need to explicitly activate the default provider, otherwise it
+# becomes unavailable in openssl. As a consequence applications depending on
+# OpenSSL may not work correctly which could lead to significant system
+# problems including inability to remotely access the system.
+[default_sect]
+# activate = 1
+
+
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
@@ -171,27 +208,9 @@ unstructuredName = An optional company name
basicConstraints=CA:FALSE
-# Here are some examples of the usage of nsCertType. If it is omitted
-# the certificate can be used for anything *except* object signing.
-
-# This is OK for an SSL server.
-# nsCertType = server
-
-# For an object signing certificate this would be used.
-# nsCertType = objsign
-
-# For normal client use this is typical
-# nsCertType = client, email
-
-# and for everything including object signing:
-# nsCertType = client, email, objsign
-
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
-# This will be displayed in Netscape's comment listbox.
-nsComment = "OpenSSL Generated Certificate"
-
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -206,13 +225,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
-#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
-#nsBaseUrl
-#nsRevocationUrl
-#nsRenewalUrl
-#nsCaPolicyUrl
-#nsSslServerName
-
# This is required for TSA certificates.
# extendedKeyUsage = critical,timeStamping
@@ -242,9 +254,6 @@ basicConstraints = critical,CA:true
# left out by default.
# keyUsage = cRLSign, keyCertSign
-# Some might want this also
-# nsCertType = sslCA, emailCA
-
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
@@ -272,27 +281,9 @@ authorityKeyIdentifier=keyid:always
basicConstraints=CA:FALSE
-# Here are some examples of the usage of nsCertType. If it is omitted
-# the certificate can be used for anything *except* object signing.
-
-# This is OK for an SSL server.
-# nsCertType = server
-
-# For an object signing certificate this would be used.
-# nsCertType = objsign
-
-# For normal client use this is typical
-# nsCertType = client, email
-
-# and for everything including object signing:
-# nsCertType = client, email, objsign
-
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
-# This will be displayed in Netscape's comment listbox.
-nsComment = "OpenSSL Generated Certificate"
-
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
@@ -307,13 +298,6 @@ authorityKeyIdentifier=keyid,issuer
# Copy subject details
# issuerAltName=issuer:copy
-#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
-#nsBaseUrl
-#nsRevocationUrl
-#nsRenewalUrl
-#nsCaPolicyUrl
-#nsSslServerName
-
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
@@ -348,3 +332,59 @@ 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)
+
+[insta] # CMP using Insta Demo CA
+# Message transfer
+server = pki.certificate.fi:8700
+# proxy = # set this as far as needed, e.g., http://192.168.1.1:8080
+# tls_use = 0
+path = pkix/
+
+# Server authentication
+recipient = "/C=FI/O=Insta Demo/CN=Insta Demo CA" # or set srvcert or issuer
+ignore_keyusage = 1 # potentially needed quirk
+unprotected_errors = 1 # potentially needed quirk
+extracertsout = insta.extracerts.pem
+
+# Client authentication
+ref = 3078 # user identification
+secret = pass:insta # can be used for both client and server side
+
+# Generic message options
+cmd = ir # default operation, can be overridden on cmd line with, e.g., kur
+
+# Certificate enrollment
+subject = "/CN=openssl-cmp-test"
+newkey = insta.priv.pem
+out_trusted = insta.ca.crt
+certout = insta.cert.pem
+
+[pbm] # Password-based protection for Insta CA
+# Server and client authentication
+ref = $insta::ref # 3078
+secret = $insta::secret # pass:insta
+
+[signature] # Signature-based protection for Insta CA
+# Server authentication
+trusted = insta.ca.crt # does not include keyUsage digitalSignature
+
+# Client authentication
+secret = # disable PBM
+key = $insta::newkey # insta.priv.pem
+cert = $insta::certout # insta.cert.pem
+
+[ir]
+cmd = ir
+
+[cr]
+cmd = cr
+
+[kur]
+# Certificate update
+cmd = kur
+oldcert = $insta::certout # insta.cert.pem
+
+[rr]
+# Certificate revocation
+cmd = rr
+oldcert = $insta::certout # insta.cert.pem
diff --git a/apps/passwd.c b/apps/passwd.c
index af08ccd4ac0f..64b2e76c147a 100644
--- a/apps/passwd.c
+++ b/apps/passwd.c
@@ -1,7 +1,7 @@
/*
* Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -16,13 +16,13 @@
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
-#ifndef OPENSSL_NO_DES
+#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0)
# include <openssl/des.h>
#endif
#include <openssl/md5.h>
#include <openssl/sha.h>
-static unsigned const char cov_2char[64] = {
+static const unsigned char cov_2char[64] = {
/* from crypto/des/fcrypt.c */
0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
@@ -38,7 +38,6 @@ static const char ascii_dollar[] = { 0x24, 0x00 };
typedef enum {
passwd_unset = 0,
- passwd_crypt,
passwd_md5,
passwd_apr1,
passwd_sha256,
@@ -51,32 +50,43 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
int reverse, size_t pw_maxlen, passwd_modes mode);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_1, OPT_5, OPT_6, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS passwd_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [password]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Read passwords from file"},
{"noverify", OPT_NOVERIFY, '-',
"Never verify when reading password from terminal"},
+ {"stdin", OPT_STDIN, '-', "Read passwords from stdin"},
+
+ OPT_SECTION("Output"),
{"quiet", OPT_QUIET, '-', "No warnings"},
{"table", OPT_TABLE, '-', "Format output as table"},
{"reverse", OPT_REVERSE, '-', "Switch table columns"},
+
+ OPT_SECTION("Cryptographic"),
{"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,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"password", 0, 0, "Password text to digest (optional)"},
{NULL}
};
@@ -154,13 +164,6 @@ int passwd_main(int argc, char **argv)
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();
@@ -175,11 +178,16 @@ int passwd_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* All remaining arguments are the password text */
argc = opt_num_rest();
argv = opt_rest();
-
if (*argv != NULL) {
if (pw_source_defined)
goto opthelp;
@@ -187,16 +195,14 @@ int passwd_main(int argc, char **argv)
passwds = argv;
}
+ if (!app_RAND_load())
+ goto end;
+
if (mode == passwd_unset) {
/* use default */
- mode = passwd_crypt;
+ mode = passwd_md5;
}
-#ifdef OPENSSL_NO_DES
- if (mode == passwd_crypt)
- goto opthelp;
-#endif
-
if (infile != NULL && in_stdin) {
BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog);
goto end;
@@ -212,9 +218,6 @@ int passwd_main(int argc, char **argv)
goto end;
}
- if (mode == passwd_crypt)
- pw_maxlen = 8;
-
if (passwds == NULL) {
/* no passwords on the command line */
@@ -413,7 +416,7 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt)
if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL))
goto err;
if (!EVP_DigestUpdate(md2,
- (i & 1) ? (unsigned const char *)passwd : buf,
+ (i & 1) ? (const unsigned char *)passwd : buf,
(i & 1) ? passwd_len : sizeof(buf)))
goto err;
if (i % 3) {
@@ -425,7 +428,7 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt)
goto err;
}
if (!EVP_DigestUpdate(md2,
- (i & 1) ? buf : (unsigned const char *)passwd,
+ (i & 1) ? buf : (const unsigned char *)passwd,
(i & 1) ? sizeof(buf) : passwd_len))
goto err;
if (!EVP_DigestFinal_ex(md2, buf, NULL))
@@ -515,7 +518,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
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 */
+ unsigned int rounds = ROUNDS_DEFAULT; /* Default */
char rounds_custom = 0;
char *p_bytes = NULL;
char *s_bytes = NULL;
@@ -627,7 +630,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
n = passwd_len;
while (n) {
if (!EVP_DigestUpdate(md,
- (n & 1) ? buf : (unsigned const char *)passwd,
+ (n & 1) ? buf : (const unsigned char *)passwd,
(n & 1) ? buf_size : passwd_len))
goto err;
n >>= 1;
@@ -673,7 +676,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
if (!EVP_DigestInit_ex(md2, sha, NULL))
goto err;
if (!EVP_DigestUpdate(md2,
- (n & 1) ? (unsigned const char *)p_bytes : buf,
+ (n & 1) ? (const unsigned char *)p_bytes : buf,
(n & 1) ? passwd_len : buf_size))
goto err;
if (n % 3) {
@@ -685,7 +688,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt)
goto err;
}
if (!EVP_DigestUpdate(md2,
- (n & 1) ? buf : (unsigned const char *)p_bytes,
+ (n & 1) ? buf : (const unsigned char *)p_bytes,
(n & 1) ? buf_size : passwd_len))
goto err;
if (!EVP_DigestFinal_ex(md2, buf, NULL))
@@ -785,11 +788,6 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
size_t saltlen = 0;
size_t i;
-#ifndef OPENSSL_NO_DES
- if (mode == passwd_crypt)
- saltlen = 2;
-#endif /* !OPENSSL_NO_DES */
-
if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5)
saltlen = 8;
@@ -828,10 +826,6 @@ 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 (mode == passwd_crypt)
- hash = DES_crypt(passwd, *salt_p);
-#endif
if (mode == passwd_md5 || mode == passwd_apr1)
hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p);
if (mode == passwd_aixmd5)
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 8c5d963b8c65..b442d358f8b7 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -1,13 +1,14 @@
/*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -17,6 +18,8 @@
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
+#include <openssl/provider.h>
+#include <openssl/kdf.h>
#define NOKEYS 0x1
#define NOCERTS 0x2
@@ -26,7 +29,13 @@
#define PASSWD_BUF_SIZE 2048
+#define WARN_EXPORT(opt) \
+ BIO_printf(bio_err, "Warning: -%s option ignored with -export\n", opt);
+#define WARN_NO_EXPORT(opt) \
+ BIO_printf(bio_err, "Warning: -%s option ignored without -export\n", opt);
+
static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) *untrusted_certs,
STACK_OF(X509) **chain);
int dump_certs_keys_p12(BIO *out, const PKCS12 *p12,
const char *pass, int passlen, int options,
@@ -46,100 +55,131 @@ int cert_load(BIO *in, STACK_OF(X509) *sk);
static int set_pbe(int *ppbe, const char *str);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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,
+#ifndef OPENSSL_NO_DES
+ OPT_DESCERT,
+#endif
+ OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
+ OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
+ OPT_INKEY, OPT_CERTFILE, OPT_UNTRUSTED, OPT_PASSCERTS,
+ 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
+ OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE,
+ OPT_R_ENUM, OPT_PROV_ENUM,
+#ifndef OPENSSL_NO_DES
+ OPT_LEGACY_ALG
+#endif
} OPTION_CHOICE;
const OPTIONS pkcs12_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"password", OPT_PASSWORD, 's', "Set PKCS#12 import/export password source"},
+ {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
{"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)"},
+ {"noout", OPT_NOOUT, '-', "Don't output anything, just verify PKCS#12 input"},
+#ifndef OPENSSL_NO_DES
+ {"legacy", OPT_LEGACY_ALG, '-',
+# ifdef OPENSSL_NO_RC2
+ "Use legacy encryption algorithm 3DES_CBC for keys and certs"
+# else
+ "Use legacy encryption: 3DES_CBC for keys, RC2_CBC for certs"
+# endif
+ },
#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)"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ OPT_PROV_OPTIONS,
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"},
+
+ OPT_SECTION("PKCS#12 import (parsing PKCS#12)"),
+ {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
+ {"nomacver", OPT_NOMACVER, '-', "Don't verify integrity MAC"},
+ {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
+ {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
+ {"", OPT_CIPHER, '-', "Any supported cipher for output encryption"},
+ {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
+ {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
+
+ OPT_SECTION("PKCS#12 output (export)"),
+ {"export", OPT_EXPORT, '-', "Create PKCS12 file"},
+ {"inkey", OPT_INKEY, 's', "Private key, else read from -in input file"},
+ {"certfile", OPT_CERTFILE, '<', "Extra certificates for PKCS12 output"},
+ {"passcerts", OPT_PASSCERTS, 's', "Certificate file pass phrase source"},
+ {"chain", OPT_CHAIN, '-', "Build and add certificate chain for EE cert,"},
+ {OPT_MORE_STR, 0, 0,
+ "which is the 1st cert from -in matching the private key (if given)"},
+ {"untrusted", OPT_UNTRUSTED, '<', "Untrusted certificates for chain building"},
{"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"},
+ {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store 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"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
+ {"name", OPT_NAME, 's', "Use name as friendly name"},
+ {"caname", OPT_CANAME, 's',
+ "Use name as CA friendly name (can be repeated)"},
+ {"CSP", OPT_CSP, 's', "Microsoft CSP name"},
+ {"LMK", OPT_LMK, '-',
+ "Add local machine keyset attribute to private key"},
+ {"keyex", OPT_KEYEX, '-', "Set key type to MS key exchange"},
+ {"keysig", OPT_KEYSIG, '-', "Set key type to MS key signature"},
+ {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default AES-256 CBC)"},
+ {"certpbe", OPT_CERTPBE, 's',
+ "Certificate PBE algorithm (default PBES2 with PBKDF2 and AES-256 CBC)"},
+#ifndef OPENSSL_NO_DES
+ {"descert", OPT_DESCERT, '-',
+ "Encrypt output with 3DES (default PBES2 with PBKDF2 and AES-256 CBC)"},
#endif
+ {"macalg", OPT_MACALG, 's',
+ "Digest algorithm to use in MAC (default SHA256)"},
+ {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"},
+ {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
+ {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration)"},
+ {"maciter", OPT_MACITER, '-', "Unused, kept for backwards compatibility"},
+ {"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
{NULL}
};
int pkcs12_main(int argc, char **argv)
{
char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
+ char *untrusted = NULL, *ciphername = NULL, *enc_flag = NULL;
+ char *passcertsarg = NULL, *passcerts = 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;
+ int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
+#ifndef OPENSSL_NO_DES
+ int use_legacy = 0;
#endif
- int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ /* use library defaults for the iter, maciter, cert, and key PBE */
+ int iter = 0, maciter = 0;
+ int cert_pbe = NID_undef;
+ int key_pbe = NID_undef;
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;
+ const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL, *prog;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL;
PKCS12 *p12 = NULL;
STACK_OF(OPENSSL_STRING) *canames = NULL;
- const EVP_CIPHER *enc = EVP_des_ede3_cbc();
+ EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_aes_256_cbc();
+ EVP_CIPHER *enc = (EVP_CIPHER *)default_enc;
OPTION_CHOICE o;
prog = opt_init(argc, argv, pkcs12_options);
@@ -187,34 +227,47 @@ int pkcs12_main(int argc, char **argv)
case OPT_NOMACVER:
macver = 0;
break;
+#ifndef OPENSSL_NO_DES
case OPT_DESCERT:
cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
break;
+#endif
case OPT_EXPORT:
- export_cert = 1;
+ export_pkcs12 = 1;
+ break;
+ case OPT_NODES:
+ case OPT_NOENC:
+ /*
+ * |enc_flag| stores the name of the option used so it
+ * can be printed if an error message is output.
+ */
+ enc_flag = opt_flag() + 1;
+ enc = NULL;
+ ciphername = NULL;
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto opthelp;
+ ciphername = opt_unknown();
+ enc_flag = opt_unknown();
+ break;
+ case OPT_ITER:
+ maciter = iter = opt_int_arg();
break;
case OPT_NOITER:
iter = 1;
break;
case OPT_MACITER:
- maciter = PKCS12_DEFAULT_ITER;
+ /* no-op */
break;
case OPT_NOMACITER:
maciter = 1;
break;
case OPT_NOMAC:
+ cert_pbe = -1;
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;
@@ -233,6 +286,12 @@ int pkcs12_main(int argc, char **argv)
case OPT_CERTFILE:
certfile = opt_arg();
break;
+ case OPT_UNTRUSTED:
+ untrusted = opt_arg();
+ break;
+ case OPT_PASSCERTS:
+ passcertsarg = opt_arg();
+ break;
case OPT_NAME:
name = opt_arg();
break;
@@ -266,28 +325,145 @@ int pkcs12_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
+#ifndef OPENSSL_NO_DES
+ case OPT_LEGACY_ALG:
+ use_legacy = 1;
+ break;
+#endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
+ if (ciphername != NULL) {
+ if (!opt_cipher_any(ciphername, &enc))
+ goto opthelp;
+ }
+ if (export_pkcs12) {
+ if ((options & INFO) != 0)
+ WARN_EXPORT("info");
+ if (macver == 0)
+ WARN_EXPORT("nomacver");
+ if ((options & CLCERTS) != 0)
+ WARN_EXPORT("clcerts");
+ if ((options & CACERTS) != 0)
+ WARN_EXPORT("cacerts");
+ if (enc != default_enc)
+ BIO_printf(bio_err,
+ "Warning: output encryption option -%s ignored with -export\n", enc_flag);
+ } else {
+ if (keyname != NULL)
+ WARN_NO_EXPORT("inkey");
+ if (certfile != NULL)
+ WARN_NO_EXPORT("certfile");
+ if (passcertsarg != NULL)
+ WARN_NO_EXPORT("passcerts");
+ if (chain)
+ WARN_NO_EXPORT("chain");
+ if (untrusted != NULL)
+ WARN_NO_EXPORT("untrusted");
+ if (CAfile != NULL)
+ WARN_NO_EXPORT("CAfile");
+ if (CApath != NULL)
+ WARN_NO_EXPORT("CApath");
+ if (CAstore != NULL)
+ WARN_NO_EXPORT("CAstore");
+ if (noCAfile)
+ WARN_NO_EXPORT("no-CAfile");
+ if (noCApath)
+ WARN_NO_EXPORT("no-CApath");
+ if (noCAstore)
+ WARN_NO_EXPORT("no-CAstore");
+ if (name != NULL)
+ WARN_NO_EXPORT("name");
+ if (canames != NULL)
+ WARN_NO_EXPORT("caname");
+ if (csp_name != NULL)
+ WARN_NO_EXPORT("CSP");
+ if (add_lmk)
+ WARN_NO_EXPORT("LMK");
+ if (keytype == KEY_EX)
+ WARN_NO_EXPORT("keyex");
+ if (keytype == KEY_SIG)
+ WARN_NO_EXPORT("keysig");
+ if (key_pbe != NID_undef)
+ WARN_NO_EXPORT("keypbe");
+ if (cert_pbe != NID_undef && cert_pbe != -1)
+ WARN_NO_EXPORT("certpbe and -descert");
+ if (macalg != NULL)
+ WARN_NO_EXPORT("macalg");
+ if (iter != 0)
+ WARN_NO_EXPORT("iter and -noiter");
+ if (maciter == 1)
+ WARN_NO_EXPORT("nomaciter");
+ if (cert_pbe == -1 && maciter == -1)
+ WARN_NO_EXPORT("nomac");
+ }
+#ifndef OPENSSL_NO_DES
+ if (use_legacy) {
+ /* load the legacy provider if not loaded already*/
+ if (!OSSL_PROVIDER_available(app_get0_libctx(), "legacy")) {
+ if (!app_provider_load(app_get0_libctx(), "legacy"))
+ goto end;
+ /* load the default provider explicitly */
+ if (!app_provider_load(app_get0_libctx(), "default"))
+ goto end;
+ }
+ if (cert_pbe == NID_undef) {
+ /* Adapt default algorithm */
+# ifndef OPENSSL_NO_RC2
+ cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
+# else
+ cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+# endif
+ }
+
+ if (key_pbe == NID_undef)
+ key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ if (enc == default_enc)
+ enc = (EVP_CIPHER *)EVP_des_ede3_cbc();
+ if (macalg == NULL)
+ macalg = "sha1";
+ }
+#endif
+
private = 1;
+ if (!app_passwd(passcertsarg, NULL, &passcerts, NULL)) {
+ BIO_printf(bio_err, "Error getting certificate file password\n");
+ goto end;
+ }
+
if (passarg != NULL) {
- if (export_cert)
+ if (export_pkcs12)
passoutarg = passarg;
else
passinarg = passarg;
@@ -299,7 +475,7 @@ int pkcs12_main(int argc, char **argv)
}
if (cpass == NULL) {
- if (export_cert)
+ if (export_pkcs12)
cpass = passout;
else
cpass = passin;
@@ -309,7 +485,7 @@ int pkcs12_main(int argc, char **argv)
mpass = cpass;
noprompt = 1;
if (twopass) {
- if (export_cert)
+ if (export_pkcs12)
BIO_printf(bio_err, "Option -twopass cannot be used with -passout or -password\n");
else
BIO_printf(bio_err, "Option -twopass cannot be used with -passin or -password\n");
@@ -325,7 +501,7 @@ int pkcs12_main(int argc, char **argv)
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
if (EVP_read_pw_string(
- macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) {
+ macpass, sizeof(macpass), "Enter MAC Password:", export_pkcs12)) {
BIO_printf(bio_err, "Can't read Password\n");
goto end;
}
@@ -336,96 +512,126 @@ int pkcs12_main(int argc, char **argv)
}
}
- if (export_cert) {
+ if (export_pkcs12) {
EVP_PKEY *key = NULL;
- X509 *ucert = NULL, *x = NULL;
+ X509 *ee_cert = NULL, *x = NULL;
STACK_OF(X509) *certs = NULL;
- const EVP_MD *macmd = NULL;
+ STACK_OF(X509) *untrusted_certs = NULL;
+ EVP_MD *macmd = NULL;
unsigned char *catmp = NULL;
int i;
if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
- BIO_printf(bio_err, "Nothing to do!\n");
+ BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n");
goto export_end;
}
- if (options & NOCERTS)
+ if ((options & NOCERTS) != 0) {
chain = 0;
+ BIO_printf(bio_err, "Warning: -chain option ignored with -nocerts\n");
+ }
if (!(options & NOKEYS)) {
key = load_key(keyname ? keyname : infile,
- FORMAT_PEM, 1, passin, e, "private key");
+ FORMAT_PEM, 1, passin, e,
+ keyname ?
+ "private key from -inkey file" :
+ "private key from -in file");
if (key == NULL)
goto export_end;
}
- /* Load in all certs in input file */
+ /* Load all certs in input file */
if (!(options & NOCERTS)) {
- if (!load_certs(infile, &certs, FORMAT_PEM, NULL,
- "certificates"))
+ if (!load_certs(infile, 1, &certs, passin,
+ "certificates from -in file"))
goto export_end;
+ if (sk_X509_num(certs) < 1) {
+ BIO_printf(bio_err, "No certificate in -in file %s\n", infile);
+ goto export_end;
+ }
if (key != NULL) {
/* Look for matching private key */
for (i = 0; i < sk_X509_num(certs); i++) {
x = sk_X509_value(certs, i);
if (X509_check_private_key(x, key)) {
- ucert = x;
+ ee_cert = x;
/* Zero keyid and alias */
- X509_keyid_set1(ucert, NULL, 0);
- X509_alias_set1(ucert, NULL, 0);
+ X509_keyid_set1(ee_cert, NULL, 0);
+ X509_alias_set1(ee_cert, NULL, 0);
/* Remove from list */
(void)sk_X509_delete(certs, i);
break;
}
}
- if (ucert == NULL) {
+ if (ee_cert == NULL) {
BIO_printf(bio_err,
- "No certificate matches private key\n");
+ "No cert in -in file '%s' matches private key\n",
+ infile);
goto export_end;
}
}
-
}
- /* Add any more certificates asked for */
- if (certfile != NULL) {
- if (!load_certs(certfile, &certs, FORMAT_PEM, NULL,
- "certificates from certfile"))
+ /* Load any untrusted certificates for chain building */
+ if (untrusted != NULL) {
+ if (!load_certs(untrusted, 0, &untrusted_certs, passcerts,
+ "untrusted certificates"))
goto export_end;
}
- /* If chaining get chain from user cert */
+ /* If chaining get chain from end entity cert */
if (chain) {
int vret;
STACK_OF(X509) *chain2;
X509_STORE *store;
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath))
+ X509 *ee_cert_tmp = ee_cert;
+
+ /* Assume the first cert if we haven't got anything else */
+ if (ee_cert_tmp == NULL && certs != NULL)
+ ee_cert_tmp = sk_X509_value(certs, 0);
+
+ if (ee_cert_tmp == NULL) {
+ BIO_printf(bio_err,
+ "No end entity certificate to check with -chain\n");
+ goto export_end;
+ }
+
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore))
== NULL)
goto export_end;
- vret = get_cert_chain(ucert, store, &chain2);
+ vret = get_cert_chain(ee_cert_tmp, store, untrusted_certs, &chain2);
X509_STORE_free(store);
if (vret == X509_V_OK) {
- /* Exclude verified certificate */
- for (i = 1; i < sk_X509_num(chain2); i++)
- sk_X509_push(certs, sk_X509_value(chain2, i));
- /* Free first certificate */
- X509_free(sk_X509_value(chain2, 0));
- sk_X509_free(chain2);
+ int add_certs;
+ /* Remove from chain2 the first (end entity) certificate */
+ X509_free(sk_X509_shift(chain2));
+ /* Add the remaining certs (except for duplicates) */
+ add_certs = X509_add_certs(certs, chain2, X509_ADD_FLAG_UP_REF
+ | X509_ADD_FLAG_NO_DUP);
+ sk_X509_pop_free(chain2, X509_free);
+ if (!add_certs)
+ goto export_end;
} else {
if (vret != X509_V_ERR_UNSPECIFIED)
- BIO_printf(bio_err, "Error %s getting chain.\n",
+ BIO_printf(bio_err, "Error getting chain: %s\n",
X509_verify_cert_error_string(vret));
- else
- ERR_print_errors(bio_err);
goto export_end;
}
}
- /* Add any CA names */
+ /* Add any extra certificates asked for */
+ if (certfile != NULL) {
+ if (!load_certs(certfile, 0, &certs, passcerts,
+ "extra certificates from -certfile"))
+ goto export_end;
+ }
+ /* Add any CA names */
for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
@@ -439,7 +645,7 @@ int pkcs12_main(int argc, char **argv)
if (add_lmk && key != NULL)
EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
- if (!noprompt) {
+ if (!noprompt && !(enc == NULL && maciter == -1)) {
/* To avoid bit rot */
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
@@ -458,21 +664,27 @@ int pkcs12_main(int argc, char **argv)
if (!twopass)
OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
- p12 = PKCS12_create(cpass, name, key, ucert, certs,
- key_pbe, cert_pbe, iter, -1, keytype);
+ p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs,
+ key_pbe, cert_pbe, iter, -1, keytype,
+ app_get0_libctx(), app_get0_propq());
- if (!p12) {
- ERR_print_errors(bio_err);
+ if (p12 == NULL) {
+ BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n",
+ outfile);
goto export_end;
}
- if (macalg) {
+ if (macalg != NULL) {
if (!opt_md(macalg, &macmd))
goto opthelp;
}
if (maciter != -1)
- PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);
+ if (!PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd)) {
+ BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n");
+ BIO_printf(bio_err, "Use -nomac if MAC not required and PKCS12KDF support not available.\n");
+ goto export_end;
+ }
assert(private);
@@ -487,9 +699,12 @@ int pkcs12_main(int argc, char **argv)
export_end:
EVP_PKEY_free(key);
+ EVP_MD_free(macmd);
sk_X509_pop_free(certs, X509_free);
- X509_free(ucert);
+ sk_X509_pop_free(untrusted_certs, X509_free);
+ X509_free(ee_cert);
+ ERR_print_errors(bio_err);
goto end;
}
@@ -501,7 +716,12 @@ int pkcs12_main(int argc, char **argv)
if (out == NULL)
goto end;
- if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) {
+ p12 = PKCS12_init_ex(NID_pkcs7_data, app_get0_libctx(), app_get0_propq());
+ if (p12 == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if ((p12 = d2i_PKCS12_bio(in, &p12)) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
@@ -544,6 +764,16 @@ int pkcs12_main(int argc, char **argv)
tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
}
if (macver) {
+ EVP_KDF *pkcs12kdf;
+
+ pkcs12kdf = EVP_KDF_fetch(app_get0_libctx(), "PKCS12KDF",
+ app_get0_propq());
+ if (pkcs12kdf == NULL) {
+ BIO_printf(bio_err, "Error verifying PKCS12 MAC; no PKCS12KDF support.\n");
+ BIO_printf(bio_err, "Use -nomacver if MAC verification is not required.\n");
+ goto end;
+ }
+ EVP_KDF_free(pkcs12kdf);
/* 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 */
@@ -557,6 +787,14 @@ int pkcs12_main(int argc, char **argv)
*/
unsigned char *utmp;
int utmplen;
+ unsigned long err = ERR_peek_error();
+
+ if (ERR_GET_LIB(err) == ERR_LIB_PKCS12
+ && ERR_GET_REASON(err) == PKCS12_R_MAC_ABSENT) {
+ BIO_printf(bio_err, "Warning: MAC is absent!\n");
+ goto dump;
+ }
+
utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen);
if (utmp == NULL)
goto end;
@@ -574,6 +812,7 @@ int pkcs12_main(int argc, char **argv)
}
}
+ dump:
assert(private);
if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
BIO_printf(bio_err, "Error outputting keys and certificates\n");
@@ -588,6 +827,7 @@ int pkcs12_main(int argc, char **argv)
BIO_free_all(out);
sk_OPENSSL_STRING_free(canames);
OPENSSL_free(badpass);
+ OPENSSL_free(passcerts);
OPENSSL_free(passin);
OPENSSL_free(passout);
return ret;
@@ -725,6 +965,16 @@ int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
X509_free(x509);
break;
+ case NID_secretBag:
+ if (options & INFO)
+ BIO_printf(bio_err, "Secret bag\n");
+ print_attribs(out, attrs, "Bag Attributes");
+ BIO_printf(bio_err, "Bag Type: ");
+ i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_bag_type(bag));
+ BIO_printf(bio_err, "\nBag Value: ");
+ print_attribute(out, PKCS12_SAFEBAG_get0_bag_obj(bag));
+ return 1;
+
case NID_safeContentsBag:
if (options & INFO)
BIO_printf(bio_err, "Safe Contents bag\n");
@@ -744,18 +994,19 @@ int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
/* Given a single certificate return a verified chain or NULL if error */
static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) *untrusted_certs,
STACK_OF(X509) **chain)
{
X509_STORE_CTX *store_ctx = NULL;
STACK_OF(X509) *chn = NULL;
int i = 0;
- store_ctx = X509_STORE_CTX_new();
+ store_ctx = X509_STORE_CTX_new_ex(app_get0_libctx(), app_get0_propq());
if (store_ctx == NULL) {
i = X509_V_ERR_UNSPECIFIED;
goto end;
}
- if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) {
+ if (!X509_STORE_CTX_init(store_ctx, store, cert, untrusted_certs)) {
i = X509_V_ERR_UNSPECIFIED;
goto end;
}
@@ -863,12 +1114,13 @@ static int alg_print(const X509_ALGOR *alg)
int cert_load(BIO *in, STACK_OF(X509) *sk)
{
- int ret;
+ int ret = 0;
X509 *cert;
- ret = 0;
+
while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
ret = 1;
- sk_X509_push(sk, cert);
+ if (!sk_X509_push(sk, cert))
+ return 0;
}
if (ret)
ERR_clear_error();
@@ -889,6 +1141,11 @@ void print_attribute(BIO *out, const ASN1_TYPE *av)
OPENSSL_free(value);
break;
+ case V_ASN1_UTF8STRING:
+ BIO_printf(out, "%.*s\n", av->value.utf8string->length,
+ av->value.utf8string->data);
+ break;
+
case V_ASN1_OCTET_STRING:
hex_prin(out, av->value.octet_string->data,
av->value.octet_string->length);
diff --git a/apps/pkcs7.c b/apps/pkcs7.c
index c3e9f5c69260..ba11e8151ae9 100644
--- a/apps/pkcs7.c
+++ b/apps/pkcs7.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -21,15 +21,24 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT,
- OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE
+ OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkcs7_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+
+ OPT_SECTION("Output"),
{"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
{"out", OPT_OUT, '>', "Output file"},
{"noout", OPT_NOOUT, '-', "Don't output encoded data"},
@@ -37,21 +46,21 @@ const OPTIONS pkcs7_options[] = {
{"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
+
+ OPT_PROV_OPTIONS,
{NULL}
};
int pkcs7_main(int argc, char **argv)
{
ENGINE *e = NULL;
- PKCS7 *p7 = NULL;
+ PKCS7 *p7 = NULL, *p7i;
BIO *in = NULL, *out = 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;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
prog = opt_init(argc, argv, pkcs7_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -94,8 +103,14 @@ int pkcs7_main(int argc, char **argv)
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -104,11 +119,18 @@ int pkcs7_main(int argc, char **argv)
if (in == NULL)
goto end;
+ p7 = PKCS7_new_ex(libctx, app_get0_propq());
+ if (p7 == NULL) {
+ BIO_printf(bio_err, "unable to allocate PKCS7 object\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
if (informat == FORMAT_ASN1)
- p7 = d2i_PKCS7_bio(in, NULL);
+ p7i = d2i_PKCS7_bio(in, &p7);
else
- p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
- if (p7 == NULL) {
+ p7i = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
+ if (p7i == NULL) {
BIO_printf(bio_err, "unable to load PKCS7 object\n");
ERR_print_errors(bio_err);
goto end;
diff --git a/apps/pkcs8.c b/apps/pkcs8.c
index 205536560ac1..6b09b909eb7a 100644
--- a/apps/pkcs8.c
+++ b/apps/pkcs8.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -18,7 +18,7 @@
#include <openssl/pkcs12.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT,
#ifndef OPENSSL_NO_SCRYPT
@@ -26,35 +26,44 @@ typedef enum OPTION_choice {
#endif
OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
OPT_TRADITIONAL,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkcs8_options[] = {
+ OPT_SECTION("General"),
{"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"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
{"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"},
+ {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 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"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"},
+ {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"},
{"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
+ {"iter", OPT_ITER, 'p', "Specify the iteration count"},
+ {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"},
+
#ifndef OPENSSL_NO_SCRYPT
+ OPT_SECTION("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
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -65,8 +74,8 @@ int pkcs8_main(int argc, char **argv)
EVP_PKEY *pkey = NULL;
PKCS8_PRIV_KEY_INFO *p8inf = NULL;
X509_SIG *p8 = NULL;
- const EVP_CIPHER *cipher = NULL;
- char *infile = NULL, *outfile = NULL;
+ EVP_CIPHER *cipher = NULL;
+ char *infile = NULL, *outfile = NULL, *ciphername = NULL;
char *passinarg = NULL, *passoutarg = NULL, *prog;
#ifndef OPENSSL_NO_UI_CONSOLE
char pass[APP_PASS_LEN];
@@ -74,7 +83,7 @@ int pkcs8_main(int argc, char **argv)
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 informat = FORMAT_UNDEF, 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;
@@ -119,12 +128,15 @@ int pkcs8_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_TRADITIONAL:
traditional = 1;
break;
case OPT_V2:
- if (!opt_cipher(opt_arg(), &cipher))
- goto opthelp;
+ ciphername = opt_arg();
break;
case OPT_V1:
pbe_nid = OBJ_txt2nid(opt_arg());
@@ -142,11 +154,10 @@ int pkcs8_main(int argc, char **argv)
goto opthelp;
}
if (cipher == NULL)
- cipher = EVP_aes_256_cbc();
+ cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
break;
case OPT_ITER:
- if (!opt_int(opt_arg(), &iter))
- goto opthelp;
+ iter = opt_int_arg();
break;
case OPT_PASSIN:
passinarg = opt_arg();
@@ -163,7 +174,7 @@ int pkcs8_main(int argc, char **argv)
scrypt_r = 8;
scrypt_p = 1;
if (cipher == NULL)
- cipher = EVP_aes_256_cbc();
+ cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
break;
case OPT_SCRYPT_N:
if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0)
@@ -180,11 +191,20 @@ int pkcs8_main(int argc, char **argv)
#endif
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
private = 1;
+ if (!app_RAND_load())
+ goto end;
+
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &cipher))
+ goto opthelp;
+ }
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
@@ -192,9 +212,10 @@ int pkcs8_main(int argc, char **argv)
}
if ((pbe_nid == -1) && cipher == NULL)
- cipher = EVP_aes_256_cbc();
+ cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
- in = bio_open_default(infile, 'r', informat);
+ in = bio_open_default(infile, 'r',
+ informat == FORMAT_UNDEF ? FORMAT_PEM : informat);
if (in == NULL)
goto end;
out = bio_open_owner(outfile, outformat, private);
@@ -278,7 +299,7 @@ int pkcs8_main(int argc, char **argv)
}
if (nocrypt) {
- if (informat == FORMAT_PEM) {
+ if (informat == FORMAT_PEM || informat == FORMAT_UNDEF) {
p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
@@ -287,7 +308,7 @@ int pkcs8_main(int argc, char **argv)
goto end;
}
} else {
- if (informat == FORMAT_PEM) {
+ if (informat == FORMAT_PEM || informat == FORMAT_UNDEF) {
p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
p8 = d2i_PKCS8_bio(in, NULL);
@@ -349,6 +370,7 @@ int pkcs8_main(int argc, char **argv)
X509_SIG_free(p8);
PKCS8_PRIV_KEY_INFO_free(p8inf);
EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(cipher);
release_engine(e);
BIO_free_all(out);
BIO_free(in);
diff --git a/apps/pkey.c b/apps/pkey.c
index 0dd5590bdc0b..196678533c1d 100644
--- a/apps/pkey.c
+++ b/apps/pkey.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -11,54 +11,77 @@
#include <string.h>
#include "apps.h"
#include "progs.h"
+#include "ec_common.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/core_names.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_TEXT, OPT_NOOUT, OPT_CIPHER, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK,
+ OPT_EC_PARAM_ENC, OPT_EC_CONV_FORM,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkey_options[] = {
+ OPT_SECTION("General"),
{"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
+ OPT_PROV_OPTIONS,
+
{"check", OPT_CHECK, '-', "Check key consistency"},
{"pubcheck", OPT_PUB_CHECK, '-', "Check public key consistency"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, 's', "Input key"},
+ {"inform", OPT_INFORM, 'f',
+ "Key input format (ENGINE, other values ignored)"},
+ {"passin", OPT_PASSIN, 's', "Key input pass phrase source"},
+ {"pubin", OPT_PUBIN, '-',
+ "Read only public components from key input"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file for encoded and/or text output"},
+ {"outform", OPT_OUTFORM, 'F', "Output encoding format (DER or PEM)"},
+ {"", OPT_CIPHER, '-', "Any supported cipher to be used for encryption"},
+ {"passout", OPT_PASSOUT, 's', "Output PEM file pass phrase source"},
+ {"traditional", OPT_TRADITIONAL, '-',
+ "Use traditional format for private key PEM output"},
+ {"pubout", OPT_PUBOUT, '-', "Restrict encoded output to public components"},
+ {"noout", OPT_NOOUT, '-', "Do not output the key in encoded form"},
+ {"text", OPT_TEXT, '-', "Output key components in plaintext"},
+ {"text_pub", OPT_TEXT_PUB, '-',
+ "Output only public key components in text form"},
+ {"ec_conv_form", OPT_EC_CONV_FORM, 's',
+ "Specifies the EC point conversion form in the encoding"},
+ {"ec_param_enc", OPT_EC_PARAM_ENC, 's',
+ "Specifies the way the EC parameters are encoded"},
+
{NULL}
};
int pkey_main(int argc, char **argv)
{
- BIO *in = NULL, *out = NULL;
+ BIO *out = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
- const EVP_CIPHER *cipher = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
char *infile = NULL, *outfile = NULL, *passin = NULL, *passout = NULL;
- char *passinarg = NULL, *passoutarg = NULL, *prog;
+ char *passinarg = NULL, *passoutarg = NULL, *ciphername = 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 informat = FORMAT_UNDEF, outformat = FORMAT_PEM;
+ int pubin = 0, pubout = 0, text_pub = 0, text = 0, noout = 0, ret = 1;
int private = 0, traditional = 0, check = 0, pub_check = 0;
+#ifndef OPENSSL_NO_EC
+ char *asn1_encoding = NULL;
+ char *point_format = NULL;
+#endif
prog = opt_init(argc, argv, pkey_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -96,13 +119,13 @@ int pkey_main(int argc, char **argv)
outfile = opt_arg();
break;
case OPT_PUBIN:
- pubin = pubout = pubtext = 1;
+ pubin = pubout = 1;
break;
case OPT_PUBOUT:
pubout = 1;
break;
case OPT_TEXT_PUB:
- pubtext = text = 1;
+ text_pub = 1;
break;
case OPT_TEXT:
text = 1;
@@ -119,19 +142,69 @@ int pkey_main(int argc, char **argv)
case OPT_PUB_CHECK:
pub_check = 1;
break;
- case OPT_MD:
- if (!opt_cipher(opt_unknown(), &cipher))
+ case OPT_CIPHER:
+ ciphername = opt_unknown();
+ break;
+ case OPT_EC_CONV_FORM:
+#ifdef OPENSSL_NO_EC
+ goto opthelp;
+#else
+ point_format = opt_arg();
+ if (!opt_string(point_format, point_format_options))
goto opthelp;
+ break;
+#endif
+ case OPT_EC_PARAM_ENC:
+#ifdef OPENSSL_NO_EC
+ goto opthelp;
+#else
+ asn1_encoding = opt_arg();
+ if (!opt_string(asn1_encoding, asn1_encoding_options))
+ goto opthelp;
+ break;
+#endif
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
- private = !noout && !pubout ? 1 : 0;
- if (text && !pubtext)
- private = 1;
+ if (text && text_pub)
+ BIO_printf(bio_err,
+ "Warning: The -text option is ignored with -text_pub\n");
+ if (traditional && (noout || outformat != FORMAT_PEM))
+ BIO_printf(bio_err,
+ "Warning: The -traditional is ignored since there is no PEM output\n");
+
+ /* -pubout and -text is the same as -text_pub */
+ if (!text_pub && pubout && text) {
+ text = 0;
+ text_pub = 1;
+ }
+
+ private = (!noout && !pubout) || (text && !text_pub);
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &cipher))
+ goto opthelp;
+ }
+ if (cipher == NULL) {
+ if (passoutarg != NULL)
+ BIO_printf(bio_err,
+ "Warning: The -passout option is ignored without a cipher option\n");
+ } else {
+ if (noout || outformat != FORMAT_PEM) {
+ BIO_printf(bio_err,
+ "Error: Cipher options are supported only for PEM output\n");
+ goto end;
+ }
+ }
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
goto end;
@@ -148,9 +221,28 @@ int pkey_main(int argc, char **argv)
if (pkey == NULL)
goto end;
+#ifndef OPENSSL_NO_EC
+ if (asn1_encoding != NULL || point_format != NULL) {
+ OSSL_PARAM params[3], *p = params;
+
+ if (!EVP_PKEY_is_a(pkey, "EC"))
+ goto end;
+
+ if (asn1_encoding != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
+ asn1_encoding, 0);
+ if (point_format != NULL)
+ *p++ = OSSL_PARAM_construct_utf8_string(
+ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+ point_format, 0);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_PKEY_set_params(pkey, params) <= 0)
+ goto end;
+ }
+#endif
+
if (check || pub_check) {
int r;
- EVP_PKEY_CTX *ctx;
ctx = EVP_PKEY_CTX_new(pkey, e);
if (ctx == NULL) {
@@ -158,7 +250,7 @@ int pkey_main(int argc, char **argv)
goto end;
}
- if (check)
+ if (check && !pubin)
r = EVP_PKEY_check(ctx);
else
r = EVP_PKEY_public_check(ctx);
@@ -170,17 +262,10 @@ int pkey_main(int argc, char **argv)
* 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 */
- }
+ BIO_printf(bio_err, "Key is invalid\n");
+ ERR_print_errors(bio_err);
+ goto end;
}
- EVP_PKEY_CTX_free(ctx);
}
if (!noout) {
@@ -202,6 +287,11 @@ int pkey_main(int argc, char **argv)
}
}
} else if (outformat == FORMAT_ASN1) {
+ if (text || text_pub) {
+ BIO_printf(bio_err,
+ "Error: Text output cannot be combined with DER output\n");
+ goto end;
+ }
if (pubout) {
if (!i2d_PUBKEY_bio(out, pkey))
goto end;
@@ -216,15 +306,13 @@ int pkey_main(int argc, char **argv)
}
}
- if (text) {
- 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;
- }
+ if (text_pub) {
+ if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
+ goto end;
+ } else if (text) {
+ assert(private);
+ if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)
+ goto end;
}
ret = 0;
@@ -232,10 +320,11 @@ int pkey_main(int argc, char **argv)
end:
if (ret != 0)
ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(cipher);
release_engine(e);
BIO_free_all(out);
- BIO_free(in);
OPENSSL_free(passin);
OPENSSL_free(passout);
diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c
index 41c3f532b345..b02882ccc296 100644
--- a/apps/pkeyparam.c
+++ b/apps/pkeyparam.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "apps.h"
#include "progs.h"
#include <openssl/pem.h>
@@ -16,21 +17,29 @@
#include <openssl/evp.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT,
- OPT_ENGINE, OPT_CHECK
+ OPT_ENGINE, OPT_CHECK,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS pkeyparam_options[] = {
+ OPT_SECTION("General"),
{"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"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, '<', "Input file"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"text", OPT_TEXT, '-', "Print parameters as text"},
+ {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -39,7 +48,8 @@ int pkeyparam_main(int argc, char **argv)
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL;
EVP_PKEY *pkey = NULL;
- int text = 0, noout = 0, ret = 1, check = 0;
+ EVP_PKEY_CTX *ctx = NULL;
+ int text = 0, noout = 0, ret = EXIT_FAILURE, check = 0, r;
OPTION_CHOICE o;
char *infile = NULL, *outfile = NULL, *prog;
@@ -73,8 +83,14 @@ int pkeyparam_main(int argc, char **argv)
case OPT_CHECK:
check = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -85,7 +101,8 @@ int pkeyparam_main(int argc, char **argv)
out = bio_open_default(outfile, 'w', FORMAT_PEM);
if (out == NULL)
goto end;
- pkey = PEM_read_bio_Parameters(in, NULL);
+ pkey = PEM_read_bio_Parameters_ex(in, NULL, app_get0_libctx(),
+ app_get0_propq());
if (pkey == NULL) {
BIO_printf(bio_err, "Error reading parameters\n");
ERR_print_errors(bio_err);
@@ -93,10 +110,11 @@ int pkeyparam_main(int argc, char **argv)
}
if (check) {
- int r;
- EVP_PKEY_CTX *ctx;
-
- ctx = EVP_PKEY_CTX_new(pkey, e);
+ if (e == NULL)
+ ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey,
+ app_get0_propq());
+ else
+ ctx = EVP_PKEY_CTX_new(pkey, e);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -111,17 +129,10 @@ int pkeyparam_main(int argc, char **argv)
* 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 */
- }
+ BIO_printf(bio_err, "Parameters are invalid\n");
+ ERR_print_errors(bio_err);
+ goto end;
}
- EVP_PKEY_CTX_free(ctx);
}
if (!noout)
@@ -130,9 +141,10 @@ int pkeyparam_main(int argc, char **argv)
if (text)
EVP_PKEY_print_params(out, pkey, 0, NULL);
- ret = 0;
+ ret = EXIT_SUCCESS;
end:
+ EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
release_engine(e);
BIO_free_all(out);
diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c
index 831e14dab4b3..518a74166153 100644
--- a/apps/pkeyutl.c
+++ b/apps/pkeyutl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -13,6 +13,7 @@
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
+#include <sys/stat.h>
#define KEY_NONE 0
#define KEY_PRIVKEY 1
@@ -22,7 +23,9 @@
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
const char *keyfile, int keyform, int key_type,
char *passinarg, int pkey_op, ENGINE *e,
- const int impl);
+ const int impl, int rawin, EVP_PKEY **ppkey,
+ EVP_MD_CTX *mctx, const char *digestname,
+ OSSL_LIB_CTX *libctx, const char *propq);
static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
ENGINE *e);
@@ -31,69 +34,100 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
unsigned char *out, size_t *poutlen,
const unsigned char *in, size_t inlen);
+static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
+ EVP_PKEY *pkey, BIO *in,
+ int filesize, unsigned char *sig, int siglen,
+ unsigned char **out, size_t *poutlen);
+
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
+ OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM,
+ OPT_CONFIG,
+ OPT_RAWIN, OPT_DIGEST
} OPTION_CHOICE;
const OPTIONS pkeyutl_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#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
+ {"sign", OPT_SIGN, '-', "Sign input data with private key"},
+ {"verify", OPT_VERIFY, '-', "Verify with public key"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"},
+ {"derive", OPT_DERIVE, '-', "Derive shared secret"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file - default stdin"},
- {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
{"pubin", OPT_PUBIN, '-', "Input is a public key"},
+ {"inkey", OPT_INKEY, 's', "Input private key file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
+ {"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"},
{"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
+ {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
+ {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
+ {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
{"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"},
+
+ OPT_SECTION("Signing/Derivation"),
+ {"digest", OPT_DIGEST, 's',
+ "Specify the digest algorithm when signing the raw input data"},
+ {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+ {"pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's',
+ "Public key option that is read as a passphrase argument opt:passphrase"},
{"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
+ OPT_PROV_OPTIONS,
{NULL}
};
int pkeyutl_main(int argc, char **argv)
{
+ CONF *conf = NULL;
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL;
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;
OPTION_CHOICE o;
- int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM;
+ int buf_inlen = 0, siglen = -1;
+ int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF;
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;
+ const char *kdfalg = NULL, *digestname = NULL;
int kdflen = 0;
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
+ STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
+ int rawin = 0;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_MD *md = NULL;
+ int filesize = -1;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
prog = opt_init(argc, argv, pkeyutl_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -129,17 +163,26 @@ int pkeyutl_main(int argc, char **argv)
passinarg = opt_arg();
break;
case OPT_PEERFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform))
goto opthelp;
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
+ goto end;
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
@@ -192,12 +235,51 @@ int pkeyutl_main(int argc, char **argv)
goto end;
}
break;
+ case OPT_PKEYOPT_PASSIN:
+ if ((pkeyopts_passin == NULL &&
+ (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) ||
+ sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) {
+ BIO_puts(bio_err, "out of memory\n");
+ goto end;
+ }
+ break;
+ case OPT_RAWIN:
+ rawin = 1;
+ break;
+ case OPT_DIGEST:
+ digestname = opt_arg();
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
+ if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
+ BIO_printf(bio_err,
+ "%s: -rawin can only be used with -sign or -verify\n",
+ prog);
+ goto opthelp;
+ }
+
+ if (digestname != NULL && !rawin) {
+ BIO_printf(bio_err,
+ "%s: -digest can only be used with -rawin\n",
+ prog);
+ goto opthelp;
+ }
+
+ if (rawin && rev) {
+ BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
+ prog);
+ goto opthelp;
+ }
+
if (kdfalg != NULL) {
if (kdflen == 0) {
BIO_printf(bio_err,
@@ -213,16 +295,22 @@ int pkeyutl_main(int argc, char **argv)
"%s: no peer key given (-peerkey parameter).\n", prog);
goto opthelp;
}
+
+ if (rawin) {
+ if ((mctx = EVP_MD_CTX_new()) == NULL) {
+ BIO_printf(bio_err, "Error: out of memory\n");
+ goto end;
+ }
+ }
ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
- passinarg, pkey_op, e, engine_impl);
+ passinarg, pkey_op, e, engine_impl, rawin, &pkey,
+ mctx, digestname, libctx, app_get0_propq());
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(ctx, peerform, peerkey, e)) {
BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
- ERR_print_errors(bio_err);
goto end;
}
if (pkeyopts != NULL) {
@@ -235,11 +323,58 @@ int pkeyutl_main(int argc, char **argv)
if (pkey_ctrl_string(ctx, opt) <= 0) {
BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
prog, opt);
- ERR_print_errors(bio_err);
goto end;
}
}
}
+ if (pkeyopts_passin != NULL) {
+ int num = sk_OPENSSL_STRING_num(pkeyopts_passin);
+ int i;
+
+ for (i = 0; i < num; i++) {
+ char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i);
+ char *passin = strchr(opt, ':');
+ char *passwd;
+
+ if (passin == NULL) {
+ /* Get password interactively */
+ char passwd_buf[4096];
+ int r;
+
+ BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt);
+ r = EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1,
+ passwd_buf, 0);
+ if (r < 0) {
+ if (r == -2)
+ BIO_puts(bio_err, "user abort\n");
+ else
+ BIO_puts(bio_err, "entry failed\n");
+ goto end;
+ }
+ passwd = OPENSSL_strdup(passwd_buf);
+ if (passwd == NULL) {
+ BIO_puts(bio_err, "out of memory\n");
+ goto end;
+ }
+ } else {
+ /* Get password as a passin argument: First split option name
+ * and passphrase argument into two strings */
+ *passin = 0;
+ passin++;
+ if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
+ BIO_printf(bio_err, "failed to get '%s'\n", opt);
+ goto end;
+ }
+ }
+
+ if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) {
+ BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
+ prog, opt);
+ goto end;
+ }
+ OPENSSL_free(passwd);
+ }
+ }
if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
BIO_printf(bio_err,
@@ -255,6 +390,12 @@ int pkeyutl_main(int argc, char **argv)
if (pkey_op != EVP_PKEY_OP_DERIVE) {
in = bio_open_default(infile, 'r', FORMAT_BINARY);
+ if (infile != NULL) {
+ struct stat st;
+
+ if (stat(infile, &st) == 0 && st.st_size <= INT_MAX)
+ filesize = (int)st.st_size;
+ }
if (in == NULL)
goto end;
}
@@ -277,7 +418,8 @@ int pkeyutl_main(int argc, char **argv)
}
}
- if (in != NULL) {
+ /* Raw input data is handled elsewhere */
+ if (in != NULL && !rawin) {
/* Read the input data */
buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
if (buf_inlen < 0) {
@@ -296,8 +438,9 @@ int pkeyutl_main(int argc, char **argv)
}
}
- /* Sanity check the input */
- if (buf_inlen > EVP_MAX_MD_SIZE
+ /* Sanity check the input if the input is not raw */
+ if (!rawin
+ && buf_inlen > EVP_MAX_MD_SIZE
&& (pkey_op == EVP_PKEY_OP_SIGN
|| pkey_op == EVP_PKEY_OP_VERIFY)) {
BIO_printf(bio_err,
@@ -306,8 +449,13 @@ int pkeyutl_main(int argc, char **argv)
}
if (pkey_op == EVP_PKEY_OP_VERIFY) {
- rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
- buf_in, (size_t)buf_inlen);
+ if (rawin) {
+ rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
+ NULL, 0);
+ } else {
+ rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
+ buf_in, (size_t)buf_inlen);
+ }
if (rv == 1) {
BIO_puts(out, "Signature Verified Successfully\n");
ret = 0;
@@ -316,18 +464,24 @@ int pkeyutl_main(int argc, char **argv)
}
goto end;
}
- if (kdflen != 0) {
- buf_outlen = kdflen;
- rv = 1;
+ if (rawin) {
+ /* rawin allocates the buffer in do_raw_keyop() */
+ rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, NULL, 0,
+ &buf_out, (size_t *)&buf_outlen);
} 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 = 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 (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 = 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) {
if (pkey_op != EVP_PKEY_OP_DERIVE) {
@@ -335,14 +489,13 @@ int pkeyutl_main(int argc, char **argv)
} 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);
+ ERR_print_errors(bio_err); /* but still return success */
} else if (hexdump) {
BIO_dump(out, (char *)buf_out, buf_outlen);
} else {
@@ -350,7 +503,11 @@ int pkeyutl_main(int argc, char **argv)
}
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ EVP_MD_CTX_free(mctx);
EVP_PKEY_CTX_free(ctx);
+ EVP_MD_free(md);
release_engine(e);
BIO_free(in);
BIO_free_all(out);
@@ -358,13 +515,17 @@ int pkeyutl_main(int argc, char **argv)
OPENSSL_free(buf_out);
OPENSSL_free(sig);
sk_OPENSSL_STRING_free(pkeyopts);
+ sk_OPENSSL_STRING_free(pkeyopts_passin);
+ NCONF_free(conf);
return ret;
}
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
const char *keyfile, int keyform, int key_type,
char *passinarg, int pkey_op, ENGINE *e,
- const int engine_impl)
+ const int engine_impl, int rawin,
+ EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
@@ -372,6 +533,7 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
char *passin = NULL;
int rv = -1;
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 && kdfalg == NULL)) {
@@ -384,11 +546,11 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
}
switch (key_type) {
case KEY_PRIVKEY:
- pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key");
+ pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
break;
case KEY_PUBKEY:
- pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key");
+ pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
break;
case KEY_CERT:
@@ -420,42 +582,68 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
goto end;
}
}
- ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
+ if (impl != NULL)
+ ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
+ else
+ ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq);
} else {
if (pkey == NULL)
goto end;
- *pkeysize = EVP_PKEY_size(pkey);
- ctx = EVP_PKEY_CTX_new(pkey, impl);
+
+ *pkeysize = EVP_PKEY_get_size(pkey);
+ if (impl != NULL)
+ ctx = EVP_PKEY_CTX_new(pkey, impl);
+ else
+ ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
+ if (ppkey != NULL)
+ *ppkey = pkey;
EVP_PKEY_free(pkey);
}
if (ctx == NULL)
goto end;
- switch (pkey_op) {
- case EVP_PKEY_OP_SIGN:
- rv = EVP_PKEY_sign_init(ctx);
- break;
+ if (rawin) {
+ EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
- case EVP_PKEY_OP_VERIFY:
- rv = EVP_PKEY_verify_init(ctx);
- break;
+ switch (pkey_op) {
+ case EVP_PKEY_OP_SIGN:
+ rv = EVP_DigestSignInit_ex(mctx, NULL, digestname, libctx, propq,
+ pkey, NULL);
+ break;
- case EVP_PKEY_OP_VERIFYRECOVER:
- rv = EVP_PKEY_verify_recover_init(ctx);
- break;
+ case EVP_PKEY_OP_VERIFY:
+ rv = EVP_DigestVerifyInit_ex(mctx, NULL, digestname, libctx, propq,
+ pkey, NULL);
+ break;
+ }
- case EVP_PKEY_OP_ENCRYPT:
- rv = EVP_PKEY_encrypt_init(ctx);
- break;
+ } else {
+ switch (pkey_op) {
+ case EVP_PKEY_OP_SIGN:
+ rv = EVP_PKEY_sign_init(ctx);
+ break;
- case EVP_PKEY_OP_DECRYPT:
- rv = EVP_PKEY_decrypt_init(ctx);
- break;
+ case EVP_PKEY_OP_VERIFY:
+ rv = EVP_PKEY_verify_init(ctx);
+ break;
- case EVP_PKEY_OP_DERIVE:
- rv = EVP_PKEY_derive_init(ctx);
- break;
+ case EVP_PKEY_OP_VERIFYRECOVER:
+ rv = EVP_PKEY_verify_recover_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_ENCRYPT:
+ rv = EVP_PKEY_encrypt_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_DECRYPT:
+ rv = EVP_PKEY_decrypt_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_DERIVE:
+ rv = EVP_PKEY_derive_init(ctx);
+ break;
+ }
}
if (rv <= 0) {
@@ -478,18 +666,15 @@ static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
if (peerform == FORMAT_ENGINE)
engine = e;
- peer = load_pubkey(file, peerform, 0, NULL, engine, "Peer Key");
+ 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(bio_err);
return 0;
}
- ret = EVP_PKEY_derive_set_peer(ctx, peer);
+ ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0;
EVP_PKEY_free(peer);
- if (ret <= 0)
- ERR_print_errors(bio_err);
return ret;
}
@@ -522,3 +707,95 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
}
return rv;
}
+
+#define TBUF_MAXSIZE 2048
+
+static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
+ EVP_PKEY *pkey, BIO *in,
+ int filesize, unsigned char *sig, int siglen,
+ unsigned char **out, size_t *poutlen)
+{
+ int rv = 0;
+ unsigned char tbuf[TBUF_MAXSIZE];
+ unsigned char *mbuf = NULL;
+ int buf_len = 0;
+
+ /* Some algorithms only support oneshot digests */
+ if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519
+ || EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448) {
+ if (filesize < 0) {
+ BIO_printf(bio_err,
+ "Error: unable to determine file size for oneshot operation\n");
+ goto end;
+ }
+ mbuf = app_malloc(filesize, "oneshot sign/verify buffer");
+ switch(pkey_op) {
+ case EVP_PKEY_OP_VERIFY:
+ buf_len = BIO_read(in, mbuf, filesize);
+ if (buf_len != filesize) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
+ break;
+ case EVP_PKEY_OP_SIGN:
+ buf_len = BIO_read(in, mbuf, filesize);
+ if (buf_len != filesize) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestSign(mctx, NULL, poutlen, mbuf, buf_len);
+ if (rv == 1 && out != NULL) {
+ *out = app_malloc(*poutlen, "buffer output");
+ rv = EVP_DigestSign(mctx, *out, poutlen, mbuf, buf_len);
+ }
+ break;
+ }
+ goto end;
+ }
+
+ switch(pkey_op) {
+ case EVP_PKEY_OP_VERIFY:
+ for (;;) {
+ buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
+ if (buf_len == 0)
+ break;
+ if (buf_len < 0) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)buf_len);
+ if (rv != 1) {
+ BIO_printf(bio_err, "Error verifying raw input data\n");
+ goto end;
+ }
+ }
+ rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
+ break;
+ case EVP_PKEY_OP_SIGN:
+ for (;;) {
+ buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
+ if (buf_len == 0)
+ break;
+ if (buf_len < 0) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)buf_len);
+ if (rv != 1) {
+ BIO_printf(bio_err, "Error signing raw input data\n");
+ goto end;
+ }
+ }
+ rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
+ if (rv == 1 && out != NULL) {
+ *out = app_malloc(*poutlen, "buffer output");
+ rv = EVP_DigestSignFinal(mctx, *out, poutlen);
+ }
+ break;
+ }
+
+ end:
+ OPENSSL_free(mbuf);
+ return rv;
+}
diff --git a/apps/prime.c b/apps/prime.c
index 694479764696..e269493d5cd7 100644
--- a/apps/prime.c
+++ b/apps/prime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -14,28 +14,36 @@
#include <openssl/bn.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS
+ OPT_COMMON,
+ OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS prime_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"},
- {OPT_HELP_STR, 1, '-',
- " number Number to check for primality\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"bits", OPT_BITS, 'p', "Size of number in bits"},
+ {"checks", OPT_CHECKS, 'p', "Number of checks"},
+
+ OPT_SECTION("Output"),
{"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"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"number", 0, 0, "Number(s) to check for primality if not generating"},
{NULL}
};
int prime_main(int argc, char **argv)
{
BIGNUM *bn = NULL;
- int hex = 0, checks = 20, generate = 0, bits = 0, safe = 0, ret = 1;
+ int hex = 0, generate = 0, bits = 0, safe = 0, ret = 1;
char *prog;
OPTION_CHOICE o;
@@ -64,20 +72,23 @@ opthelp:
safe = 1;
break;
case OPT_CHECKS:
- checks = atoi(opt_arg());
+ /* ignore parameter and argument */
+ opt_arg();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
break;
}
}
+
+ /* Optional arguments are numbers to check. */
argc = opt_num_rest();
argv = opt_rest();
-
if (generate) {
- if (argc != 0) {
- BIO_printf(bio_err, "Extra arguments given.\n");
+ if (argc != 0)
goto opthelp;
- }
} else if (argc == 0) {
- BIO_printf(bio_err, "%s: No prime specified\n", prog);
goto opthelp;
}
@@ -121,7 +132,7 @@ opthelp:
BN_print(bio_out, bn);
BIO_printf(bio_out, " (%s) %s prime\n",
argv[0],
- BN_is_prime_ex(bn, checks, NULL, NULL)
+ BN_check_prime(bn, NULL, NULL)
? "is" : "is not");
}
}
diff --git a/apps/progs.pl b/apps/progs.pl
index 57671405dda0..29f9be13ca08 100644
--- a/apps/progs.pl
+++ b/apps/progs.pl
@@ -1,7 +1,7 @@
#! /usr/bin/env perl
-# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
#
-# Licensed under the OpenSSL license (the "License"). You may not use
+# Licensed under the Apache License 2.0 (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
@@ -14,17 +14,22 @@ use warnings;
use lib '.';
use configdata qw/@disablables %unified_info/;
+my $opt = shift @ARGV;
+die "Unrecognised option, must be -C or -H\n"
+ unless ($opt eq '-H' || $opt eq '-C');
+
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;
+my $YEAR = [gmtime($ENV{SOURCE_DATE_EPOCH} || time())]->[5] + 1900;
# 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$/ }
+ grep { /\.o$/
+ && !$unified_info{attributes}->{sources}->{$apps_openssl}->{$_}->{nocheck} }
@{$unified_info{sources}->{$apps_openssl}};
foreach my $filename (@openssl_source) {
@@ -38,144 +43,178 @@ foreach my $filename (@openssl_source) {
@ARGV = sort keys %commands;
-print <<"EOF";
+if ($opt eq '-H') {
+ 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
+ * Licensed under the Apache License 2.0 (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;
-
-DEFINE_LHASH_OF(FUNCTION);
+#include "function.h"
EOF
-foreach (@ARGV) {
- printf "extern int %s_main(int argc, char *argv[]);\n", $_;
-}
-print "\n";
+ 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",
-);
-
-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 (@ARGV) {
+ printf "extern const OPTIONS %s_options[];\n", $_;
}
+ print "\n";
+ print "extern FUNCTION functions[];\n";
}
-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;
+if ($opt eq '-C') {
+ print <<"EOF";
+/*
+ * WARNING: do not edit!
+ * Generated by apps/progs.pl
+ *
+ * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 "progs.h"
+
+EOF
+
+ my %cmd_disabler = (
+ ciphers => "sock",
+ genrsa => "rsa",
+ gendsa => "dsa",
+ dsaparam => "dsa",
+ gendh => "dh",
+ dhparam => "dh",
+ ecparam => "ec",
+ );
+ my %cmd_deprecated = (
+# The format of this table is:
+# [0] = alternative command to use instead
+# [1] = deprecented in this version
+# [2] = preprocessor conditional for exclusing irrespective of deprecation
+# rsa => [ "pkey", "3_0", "rsa" ],
+# genrsa => [ "genpkey", "3_0", "rsa" ],
+ rsautl => [ "pkeyutl", "3_0", "rsa" ],
+# dhparam => [ "pkeyparam", "3_0", "dh" ],
+# dsaparam => [ "pkeyparam", "3_0", "dsa" ],
+# dsa => [ "pkey", "3_0", "dsa" ],
+# gendsa => [ "genpkey", "3_0", "dsa" ],
+# ec => [ "pkey", "3_0", "ec" ],
+# ecparam => [ "pkeyparam", "3_0", "ec" ],
+ );
+
+ print "FUNCTION functions[] = {\n";
+ foreach my $cmd ( @ARGV ) {
+ my $str =
+ " {FT_general, \"$cmd\", ${cmd}_main, ${cmd}_options, NULL, NULL},\n";
+ if ($cmd =~ /^s_/) {
+ print "#ifndef OPENSSL_NO_SOCK\n${str}#endif\n";
+ } elsif (my $deprecated = $cmd_deprecated{$cmd}) {
+ my @dep = @{$deprecated};
+ my $daltprg = $dep[0];
+ my $dver = $dep[1];
+ my $dsys = $dep[2];
+ print "#if !defined(OPENSSL_NO_DEPRECATED_" . $dver . ")";
+ if ($dsys) {
+ print " && !defined(OPENSSL_NO_" . uc($dsys) . ")";
+ }
+ $dver =~ s/_/./g;
+ my $dalt = "\"" . $daltprg . "\", \"" . $dver . "\"";
+ $str =~ s/NULL, NULL/$dalt/;
+ print "\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;
+ }
}
-}
-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;
+ my %md_disabler = (
+ blake2b512 => "blake2",
+ blake2s256 => "blake2",
+ );
+ foreach my $cmd (
+ "md2", "md4", "md5",
+ "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, NULL, NULL},\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;
+ }
}
-}
-print " {0, NULL, NULL}\n};\n";
-print "#endif\n";
+ 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, NULL},\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, NULL, NULL}\n};\n";
+}
diff --git a/apps/rand.c b/apps/rand.c
index 4c6181507bd5..cbf495d5bc53 100644
--- a/apps/rand.c
+++ b/apps/rand.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -19,22 +19,30 @@
#include <openssl/rand.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS rand_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [flags] num\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] num\n"},
+
+ OPT_SECTION("General"),
{"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
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"base64", OPT_BASE64, '-', "Base64 encode output"},
+ {"hex", OPT_HEX, '-', "Hex encode output"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"num", 0, 0, "Number of bytes to generate"},
{NULL}
};
@@ -74,18 +82,26 @@ int rand_main(int argc, char **argv)
case OPT_HEX:
format = FORMAT_TEXT;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional argument is number of bytes to generate. */
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;
+ } else if (argc != 0) {
goto opthelp;
}
+ if (!app_RAND_load())
+ goto end;
+
out = bio_open_default(outfile, 'w', format);
if (out == NULL)
goto end;
diff --git a/apps/rehash.c b/apps/rehash.c
index fc1dffe97497..e4a4e14fd497 100644
--- a/apps/rehash.c
+++ b/apps/rehash.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 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
+ * Licensed under the Apache License 2.0 (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
@@ -42,7 +42,6 @@
# include <openssl/pem.h>
# include <openssl/x509.h>
-
# ifndef PATH_MAX
# define PATH_MAX 4096
# endif
@@ -169,6 +168,12 @@ static int add_entry(enum Type type, unsigned int hash, const char *filename,
*ep = nilhentry;
ep->old_id = ~0;
ep->filename = OPENSSL_strdup(filename);
+ if (ep->filename == NULL) {
+ OPENSSL_free(ep);
+ ep = NULL;
+ BIO_printf(bio_err, "out of memory\n");
+ return 1;
+ }
if (bp->last_entry)
bp->last_entry->next = ep;
if (bp->first_entry == NULL)
@@ -209,7 +214,7 @@ static int handle_symlink(const char *filename, const char *fullpath)
return -1;
for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) {
const char *suffix = suffixes[type];
- if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
+ if (OPENSSL_strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
break;
}
i += strlen(suffixes[type]);
@@ -233,7 +238,7 @@ 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;
+ const X509_NAME *name = NULL;
BIO *b;
const char *ext;
unsigned char digest[EVP_MAX_MD_SIZE];
@@ -244,7 +249,7 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h)
if ((ext = strrchr(filename, '.')) == NULL)
goto end;
for (i = 0; i < OSSL_NELEM(extensions); i++) {
- if (strcasecmp(extensions[i], ext + 1) == 0)
+ if (OPENSSL_strcasecmp(extensions[i], ext + 1) == 0)
break;
}
if (i >= OSSL_NELEM(extensions))
@@ -292,10 +297,23 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h)
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_NEW || h == HASH_BOTH) {
+ int ok;
+ unsigned long hash_value =
+ X509_NAME_hash_ex(name,
+ app_get0_libctx(), app_get0_propq(), &ok);
+
+ if (ok) {
+ errs += add_entry(type, hash_value, filename, digest, 1, ~0);
+ } else {
+ BIO_printf(bio_err, "%s: error calculating SHA1 hash value\n",
+ opt_getprog());
+ errs++;
+ }
+ }
if ((h == HASH_OLD) || (h == HASH_BOTH))
- errs += add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0);
+ errs += add_entry(type, X509_NAME_hash_old(name),
+ filename, digest, 1, ~0);
}
end:
@@ -454,19 +472,28 @@ static int do_dir(const char *dirname, enum Hash h)
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE
+ OPT_COMMON,
+ OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS rehash_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert-directory...]\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [directory...]\n"},
+
+ OPT_SECTION("General"),
{"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"},
+
+ OPT_SECTION("Output"),
{"v", OPT_VERBOSE, '-', "Verbose output"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"directory", 0, 0, "One or more directories to process (optional)"},
{NULL}
};
@@ -501,13 +528,19 @@ int rehash_main(int argc, char **argv)
case OPT_VERBOSE:
verbose = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional arguments are directories to scan. */
argc = opt_num_rest();
argv = opt_rest();
evpmd = EVP_sha1();
- evpmdsize = EVP_MD_size(evpmd);
+ evpmdsize = EVP_MD_get_size(evpmd);
if (*argv != NULL) {
while (*argv != NULL)
diff --git a/apps/req.c b/apps/req.c
index a603907cd5af..23757044ab7f 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -14,6 +14,7 @@
#include <ctype.h>
#include "apps.h"
#include "progs.h"
+#include <openssl/core_names.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
@@ -25,32 +26,29 @@
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/lhash.h>
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
+#include <openssl/rsa.h>
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
-#define SECTION "req"
-
-#define BITS "default_bits"
-#define KEYFILE "default_keyfile"
-#define PROMPT "prompt"
-#define DISTINGUISHED_NAME "distinguished_name"
-#define ATTRIBUTES "attributes"
-#define V3_EXTENSIONS "x509_extensions"
-#define REQ_EXTENSIONS "req_extensions"
-#define STRING_MASK "string_mask"
-#define UTF8_IN "utf8"
-
-#define DEFAULT_KEY_LENGTH 2048
-#define MIN_KEY_LENGTH 512
-
-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, const char *subj, unsigned long chtype,
- int multirdn);
+#define BITS "default_bits"
+#define KEYFILE "default_keyfile"
+#define PROMPT "prompt"
+#define DISTINGUISHED_NAME "distinguished_name"
+#define ATTRIBUTES "attributes"
+#define V3_EXTENSIONS "x509_extensions"
+#define REQ_EXTENSIONS "req_extensions"
+#define STRING_MASK "string_mask"
+#define UTF8_IN "utf8"
+
+#define DEFAULT_KEY_LENGTH 2048
+#define MIN_KEY_LENGTH 512
+#define DEFAULT_DAYS 30 /* default cert validity period in days */
+#define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */
+#define EXT_COPY_UNSET -1
+
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj,
+ int mutlirdn, int attribs, unsigned long chtype);
static int prompt_info(X509_REQ *req,
STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
@@ -65,91 +63,113 @@ 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 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 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);
+ char **pkeytype, long *pkeylen,
+ ENGINE *keygen_engine);
+
+static const char *section = "req";
static CONF *req_conf = NULL;
static CONF *addext_conf = NULL;
static int batch = 0;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
+ OPT_VERIFY, OPT_NOENC, 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_CA, OPT_CAKEY,
+ OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL,
+ OPT_COPY_EXTENSIONS, OPT_ADDEXT, OPT_EXTENSIONS,
OPT_REQEXTS, OPT_PRECERT, OPT_MD,
- OPT_R_ENUM
+ OPT_SECTION,
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS req_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#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
+ {"in", OPT_IN, '<', "X.509 request input file (default stdin)"},
{"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"},
+ {"verify", OPT_VERIFY, '-', "Verify self-signature on the request"},
+
+ OPT_SECTION("Certificate"),
{"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"},
+ {"section", OPT_SECTION, 's', "Config section to use (default \"req\")"},
{"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing 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"},
+ "Output an X.509 certificate structure instead of a cert request"},
+ {"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"},
+ {"CAkey", OPT_CAKEY, 's',
+ "Issuer private key to use with -CA; default is -CA arg"},
{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"},
+ {"subj", OPT_SUBJ, 's', "Set or modify subject of request or cert"},
+ {"subject", OPT_SUBJECT, '-',
+ "Print the subject of the output request or cert"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
- "Enable support for multivalued RDNs"},
+ "Deprecated; multi-valued RDNs support is always on."},
{"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
{"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
+ {"copy_extensions", OPT_COPY_EXTENSIONS, 's',
+ "copy extensions from request when using -x509"},
{"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)"},
+ {"precert", OPT_PRECERT, '-',
+ "Add a poison extension to the generated cert (implies -new)"},
+
+ OPT_SECTION("Keys and Signing"),
+ {"key", OPT_KEY, 's', "Key for signing, and to include unless -in given"},
+ {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
+ {"pubkey", OPT_PUBKEY, '-', "Output public key"},
+ {"keyout", OPT_KEYOUT, '>', "File to write private key to"},
+ {"passin", OPT_PASSIN, 's', "Private key and certificate password source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"newkey", OPT_NEWKEY, 's',
+ "Generate new key with [<alg>:]<nbits> or <alg>[:<file>] or param:<file>"},
+ {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
{"", 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
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"batch", OPT_BATCH, '-',
+ "Do not ask anything during request generation"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+ {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
+ {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
+ {"noout", OPT_NOOUT, '-', "Do not output REQ"},
+ {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"},
+ {"modulus", OPT_MODULUS, '-', "RSA modulus"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
{NULL}
};
-
/*
* An LHASH of strings, where each string is an extension name.
*/
@@ -169,9 +189,8 @@ static void exts_cleanup(OPENSSL_STRING *x)
}
/*
- * 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.
+ * 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)
{
@@ -200,7 +219,7 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
*p = '\0';
/* Finally have a clean "key"; see if it's there [by attempt to add it]. */
- p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv);
+ p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING *)kv);
if (p != NULL) {
OPENSSL_free(p);
return 1;
@@ -215,36 +234,39 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
int req_main(int argc, char **argv)
{
ASN1_INTEGER *serial = NULL;
- BIO *in = NULL, *out = NULL;
+ BIO *out = NULL;
ENGINE *e = NULL, *gen_eng = NULL;
- EVP_PKEY *pkey = NULL;
+ EVP_PKEY *pkey = NULL, *CAkey = NULL;
EVP_PKEY_CTX *genctx = NULL;
- STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
+ STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL, *vfyopts = NULL;
LHASH_OF(OPENSSL_STRING) *addexts = NULL;
- X509 *x509ss = NULL;
+ X509 *new_x509 = NULL, *CAcert = NULL;
X509_REQ *req = NULL;
- const EVP_CIPHER *cipher = NULL;
- const EVP_MD *md_alg = NULL, *digest = NULL;
+ EVP_CIPHER *cipher = NULL;
+ EVP_MD *md = NULL;
+ int ext_copy = EXT_COPY_UNSET;
BIO *addext_bio = NULL;
- char *extensions = NULL, *infile = NULL;
- char *outfile = NULL, *keyfile = NULL;
+ char *extensions = NULL;
+ const char *infile = NULL, *CAfile = NULL, *CAkeyfile = NULL;
+ char *outfile = NULL, *keyfile = NULL, *digest = 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;
+ X509_NAME *fsubj = 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;
+ int days = UNSET_DAYS;
+ int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF;
+ int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0;
+ int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0;
+ long newkey_len = -1;
unsigned long chtype = MBSTRING_ASC, reqflag = 0;
#ifndef OPENSSL_NO_DES
- cipher = EVP_des_ede3_cbc();
+ cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
#endif
prog = opt_init(argc, argv, req_options);
@@ -272,7 +294,7 @@ int req_main(int argc, char **argv)
break;
case OPT_KEYGEN_ENGINE:
#ifndef OPENSSL_NO_ENGINE
- gen_eng = ENGINE_by_id(opt_arg());
+ gen_eng = setup_engine(opt_arg(), 0);
if (gen_eng == NULL) {
BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv);
goto opthelp;
@@ -291,6 +313,9 @@ int req_main(int argc, char **argv)
case OPT_CONFIG:
template = opt_arg();
break;
+ case OPT_SECTION:
+ section = opt_arg();
+ break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
@@ -314,14 +339,19 @@ int req_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_NEWKEY:
keyalg = opt_arg();
newreq = 1;
break;
case OPT_PKEYOPT:
- if (!pkeyopts)
+ if (pkeyopts == NULL)
pkeyopts = sk_OPENSSL_STRING_new_null();
- if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg()))
+ if (pkeyopts == NULL
+ || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg()))
goto opthelp;
break;
case OPT_SIGOPT:
@@ -330,6 +360,12 @@ int req_main(int argc, char **argv)
if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto opthelp;
break;
+ case OPT_VFYOPT:
+ if (!vfyopts)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
+ goto opthelp;
+ break;
case OPT_BATCH:
batch = 1;
break;
@@ -343,7 +379,8 @@ int req_main(int argc, char **argv)
verify = 1;
break;
case OPT_NODES:
- nodes = 1;
+ case OPT_NOENC:
+ noenc = 1;
break;
case OPT_NOOUT:
noout = 1;
@@ -366,10 +403,22 @@ int req_main(int argc, char **argv)
text = 1;
break;
case OPT_X509:
- x509 = 1;
+ gen_x509 = 1;
+ break;
+ case OPT_CA:
+ CAfile = opt_arg();
+ gen_x509 = 1;
+ break;
+ case OPT_CAKEY:
+ CAkeyfile = opt_arg();
break;
case OPT_DAYS:
days = atoi(opt_arg());
+ if (days < -1) {
+ BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
+ prog);
+ goto end;
+ }
break;
case OPT_SET_SERIAL:
if (serial != NULL) {
@@ -387,7 +436,14 @@ int req_main(int argc, char **argv)
subj = opt_arg();
break;
case OPT_MULTIVALUE_RDN:
- multirdn = 1;
+ /* obsolete */
+ break;
+ case OPT_COPY_EXTENSIONS:
+ if (!set_ext_copy(&ext_copy, opt_arg())) {
+ BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n",
+ opt_arg());
+ goto end;
+ }
break;
case OPT_ADDEXT:
p = opt_arg();
@@ -398,9 +454,11 @@ int req_main(int argc, char **argv)
goto end;
}
i = duplicated(addexts, p);
- if (i == 1)
+ if (i == 1) {
+ BIO_printf(bio_err, "Duplicate extension: %s\n", p);
goto opthelp;
- if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0)
+ }
+ if (i < 0 || BIO_printf(addext_bio, "%s\n", p) < 0)
goto end;
break;
case OPT_EXTENSIONS:
@@ -413,37 +471,39 @@ int req_main(int argc, char **argv)
newreq = precert = 1;
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &md_alg))
- goto opthelp;
- digest = md_alg;
+ digest = opt_unknown();
break;
}
}
+
+ /* No extra arguments. */
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;
+ if (!app_RAND_load())
+ goto end;
- /* TODO: simplify this as pkey is still always NULL here */
- private = newreq && (pkey == NULL) ? 1 : 0;
+ if (!gen_x509) {
+ if (days != UNSET_DAYS)
+ BIO_printf(bio_err, "Ignoring -days without -x509; not generating a certificate\n");
+ if (ext_copy == EXT_COPY_NONE)
+ BIO_printf(bio_err, "Ignoring -copy_extensions 'none' when -x509 is not given\n");
+ }
+ if (gen_x509 && infile == NULL)
+ newreq = 1;
if (!app_passwd(passargin, passargout, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
goto end;
}
- if (verbose)
- BIO_printf(bio_err, "Using configuration from %s\n", template);
- if ((req_conf = app_load_config(template)) == NULL)
+ if ((req_conf = app_load_config_verbose(template, verbose)) == NULL)
goto end;
- if (addext_bio) {
+ if (addext_bio != NULL) {
if (verbose)
BIO_printf(bio_err,
- "Using additional configuration from command line\n");
+ "Using additional configuration from -addext options\n");
if ((addext_conf = app_load_config_bio(addext_bio, NULL)) == NULL)
goto end;
}
@@ -455,14 +515,12 @@ int req_main(int argc, char **argv)
if (p == NULL)
ERR_clear_error();
if (p != NULL) {
- BIO *oid_bio;
+ 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);
- */
+ if (verbose)
+ BIO_printf(bio_err,
+ "Problems opening '%s' for extra OIDs\n", p);
} else {
OBJ_create_objects(oid_bio);
BIO_free(oid_bio);
@@ -472,59 +530,67 @@ int req_main(int argc, char **argv)
if (!add_oid_section(req_conf))
goto end;
- if (md_alg == NULL) {
- p = NCONF_get_string(req_conf, SECTION, "default_md");
- if (p == NULL) {
+ /* Check that any specified digest is fetchable */
+ if (digest != NULL) {
+ if (!opt_md(digest, &md)) {
ERR_clear_error();
- } else {
- if (!opt_md(p, &md_alg))
- goto opthelp;
- digest = md_alg;
+ goto opthelp;
}
+ EVP_MD_free(md);
+ } else {
+ /* No digest specified, default to configuration */
+ p = NCONF_get_string(req_conf, section, "default_md");
+ if (p == NULL)
+ ERR_clear_error();
+ else
+ digest = p;
}
if (extensions == NULL) {
- extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
+ extensions = NCONF_get_string(req_conf, section, V3_EXTENSIONS);
if (extensions == NULL)
ERR_clear_error();
}
if (extensions != NULL) {
/* Check syntax of file */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, req_conf);
if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
BIO_printf(bio_err,
- "Error Loading extension section %s\n", extensions);
+ "Error checking x509 extension section %s\n",
+ extensions);
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");
+ BIO_printf(bio_err, "Error checking extensions defined using -addext\n");
goto end;
}
}
if (passin == NULL) {
passin = nofree_passin =
- NCONF_get_string(req_conf, SECTION, "input_password");
+ NCONF_get_string(req_conf, section, "input_password");
if (passin == NULL)
ERR_clear_error();
}
if (passout == NULL) {
passout = nofree_passout =
- NCONF_get_string(req_conf, SECTION, "output_password");
+ NCONF_get_string(req_conf, section, "output_password");
if (passout == NULL)
ERR_clear_error();
}
- p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
+ p = NCONF_get_string(req_conf, section, STRING_MASK);
if (p == NULL)
ERR_clear_error();
@@ -534,7 +600,7 @@ int req_main(int argc, char **argv)
}
if (chtype != MBSTRING_UTF8) {
- p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
+ p = NCONF_get_string(req_conf, section, UTF8_IN);
if (p == NULL)
ERR_clear_error();
else if (strcmp(p, "yes") == 0)
@@ -542,134 +608,117 @@ int req_main(int argc, char **argv)
}
if (req_exts == NULL) {
- req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
+ req_exts = NCONF_get_string(req_conf, section, REQ_EXTENSIONS);
if (req_exts == NULL)
ERR_clear_error();
}
if (req_exts != NULL) {
/* Check syntax of file */
X509V3_CTX ctx;
+
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, req_conf);
if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
BIO_printf(bio_err,
- "Error Loading request extension section %s\n",
+ "Error checking request extension section %s\n",
req_exts);
goto end;
}
}
if (keyfile != NULL) {
- pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key");
- if (pkey == NULL) {
- /* load_key() has already printed an appropriate message */
+ pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
+ if (pkey == NULL)
goto end;
- } else {
- app_RAND_load_conf(req_conf, SECTION);
- }
+ app_RAND_load_conf(req_conf, section);
}
+ if (newreq && pkey == NULL) {
+ app_RAND_load_conf(req_conf, section);
- if (newreq && (pkey == NULL)) {
- app_RAND_load_conf(req_conf, SECTION);
+ if (!NCONF_get_number(req_conf, section, BITS, &newkey_len))
+ newkey_len = DEFAULT_KEY_LENGTH;
- if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) {
- newkey = DEFAULT_KEY_LENGTH;
- }
-
- if (keyalg != NULL) {
- genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey,
- &keyalgstr, gen_eng);
- if (genctx == NULL)
- goto end;
- }
+ genctx = set_keygen_ctx(keyalg, &keyalgstr, &newkey_len, gen_eng);
+ if (genctx == NULL)
+ goto end;
- if (newkey < MIN_KEY_LENGTH
- && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
- BIO_printf(bio_err, "private key length is too short,\n");
- BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n",
- MIN_KEY_LENGTH, newkey);
+ if (newkey_len < MIN_KEY_LENGTH
+ && (EVP_PKEY_CTX_is_a(genctx, "RSA")
+ || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS")
+ || EVP_PKEY_CTX_is_a(genctx, "DSA"))) {
+ BIO_printf(bio_err, "Private key length too short, needs to be at least %d bits, not %ld.\n",
+ MIN_KEY_LENGTH, newkey_len);
goto end;
}
- if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS)
+ if (newkey_len > OPENSSL_RSA_MAX_MODULUS_BITS
+ && (EVP_PKEY_CTX_is_a(genctx, "RSA")
+ || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS")))
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);
+ OPENSSL_RSA_MAX_MODULUS_BITS, newkey_len);
#ifndef OPENSSL_NO_DSA
- if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS)
+ if (EVP_PKEY_CTX_is_a(genctx, "DSA")
+ && newkey_len > 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);
+ OPENSSL_DSA_MAX_MODULUS_BITS, newkey_len);
#endif
- if (genctx == NULL) {
- genctx = set_keygen_ctx(NULL, &pkey_type, &newkey,
- &keyalgstr, gen_eng);
- if (!genctx)
- goto end;
- }
-
if (pkeyopts != NULL) {
char *genopt;
for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) {
genopt = sk_OPENSSL_STRING_value(pkeyopts, i);
if (pkey_ctrl_string(genctx, genopt) <= 0) {
- BIO_printf(bio_err, "parameter error \"%s\"\n", genopt);
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Key parameter error \"%s\"\n", genopt);
goto end;
}
}
}
- 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);
- if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
- BIO_puts(bio_err, "Error Generating Key\n");
- goto end;
- }
+ pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose);
EVP_PKEY_CTX_free(genctx);
genctx = NULL;
+ }
+ if (keyout == NULL && keyfile == NULL) {
+ keyout = NCONF_get_string(req_conf, section, KEYFILE);
+ if (keyout == NULL)
+ ERR_clear_error();
+ }
- if (keyout == NULL) {
- keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
+ if (pkey != NULL && (keyfile == NULL || keyout != NULL)) {
+ if (verbose) {
+ BIO_printf(bio_err, "Writing private key to ");
if (keyout == NULL)
- ERR_clear_error();
+ BIO_printf(bio_err, "stdout\n");
+ else
+ BIO_printf(bio_err, "'%s'\n", keyout);
}
-
- if (keyout == NULL)
- BIO_printf(bio_err, "writing new private key to stdout\n");
- else
- BIO_printf(bio_err, "writing new private key to '%s'\n", keyout);
- out = bio_open_owner(keyout, outformat, private);
+ out = bio_open_owner(keyout, outformat, newreq);
if (out == NULL)
goto end;
- p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
+ p = NCONF_get_string(req_conf, section, "encrypt_rsa_key");
if (p == NULL) {
ERR_clear_error();
- p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
+ p = NCONF_get_string(req_conf, section, "encrypt_key");
if (p == NULL)
ERR_clear_error();
}
if ((p != NULL) && (strcmp(p, "no") == 0))
cipher = NULL;
- if (nodes)
+ if (noenc)
cipher = NULL;
i = 0;
loop:
- assert(private);
if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
NULL, 0, NULL, passout)) {
if ((ERR_GET_REASON(ERR_peek_error()) ==
@@ -685,112 +734,151 @@ int req_main(int argc, char **argv)
BIO_printf(bio_err, "-----\n");
}
+ /*
+ * subj is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where characters may be escaped by \
+ */
+ if (subj != NULL
+ && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
+ goto end;
+
if (!newreq) {
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
+ req = load_csr(infile /* if NULL, reads from stdin */,
+ informat, "X509 request");
+ if (req == NULL)
goto end;
+ }
- if (informat == FORMAT_ASN1)
- req = d2i_X509_REQ_bio(in, NULL);
- else
- req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
- if (req == NULL) {
- BIO_printf(bio_err, "unable to load X509 request\n");
+ if (CAkeyfile == NULL)
+ CAkeyfile = CAfile;
+ if (CAkeyfile != NULL) {
+ if (CAfile == NULL) {
+ BIO_printf(bio_err,
+ "Warning: Ignoring -CAkey option since no -CA option is given\n");
+ } else {
+ if ((CAkey = load_key(CAkeyfile, FORMAT_UNDEF,
+ 0, passin, e,
+ CAkeyfile != CAfile
+ ? "issuer private key from -CAkey arg"
+ : "issuer private key from -CA arg")) == NULL)
+ goto end;
+ }
+ }
+ if (CAfile != NULL) {
+ if ((CAcert = load_cert_pass(CAfile, FORMAT_UNDEF, 1, passin,
+ "issuer cert from -CA arg")) == NULL)
+ goto end;
+ if (!X509_check_private_key(CAcert, CAkey)) {
+ BIO_printf(bio_err,
+ "Issuer CA certificate and key do not match\n");
goto end;
}
}
-
- if (newreq || x509) {
- if (pkey == NULL) {
- BIO_printf(bio_err, "you need to specify a private key\n");
+ if (newreq || gen_x509) {
+ if (CAcert == NULL && pkey == NULL) {
+ BIO_printf(bio_err, "Must provide a signature key using -key or"
+ " provide -CA / -CAkey\n");
goto end;
}
if (req == NULL) {
- req = X509_REQ_new();
+ req = X509_REQ_new_ex(app_get0_libctx(), app_get0_propq());
if (req == NULL) {
goto end;
}
- i = make_REQ(req, pkey, subj, multirdn, !x509, chtype);
- subj = NULL; /* done processing '-subj' option */
- if (!i) {
- BIO_printf(bio_err, "problems making Certificate Request\n");
+ if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)){
+ BIO_printf(bio_err, "Error making certificate request\n");
goto end;
}
+ /* Note that -x509 can take over -key and -subj option values. */
}
- if (x509) {
- EVP_PKEY *tmppkey;
+ if (gen_x509) {
+ EVP_PKEY *pub_key = X509_REQ_get0_pubkey(req);
+ EVP_PKEY *issuer_key = CAcert != NULL ? CAkey : pkey;
X509V3_CTX ext_ctx;
- if ((x509ss = X509_new()) == NULL)
- goto end;
+ X509_NAME *issuer = CAcert != NULL ? X509_get_subject_name(CAcert) :
+ X509_REQ_get_subject_name(req);
+ X509_NAME *n_subj = fsubj != NULL ? fsubj :
+ X509_REQ_get_subject_name(req);
- /* Set version to V3 */
- if ((extensions != NULL || addext_conf != NULL)
- && !X509_set_version(x509ss, 2))
+ if ((new_x509 = X509_new_ex(app_get0_libctx(),
+ app_get0_propq())) == NULL)
goto end;
+
if (serial != NULL) {
- if (!X509_set_serialNumber(x509ss, serial))
+ if (!X509_set_serialNumber(new_x509, serial))
goto end;
} else {
- if (!rand_serial(NULL, X509_get_serialNumber(x509ss)))
+ if (!rand_serial(NULL, X509_get_serialNumber(new_x509)))
goto end;
}
- if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
+ if (!X509_set_issuer_name(new_x509, issuer))
goto end;
- if (days == 0) {
- /* set default days if it's not specified */
- days = 30;
+ if (days == UNSET_DAYS) {
+ days = DEFAULT_DAYS;
}
- if (!set_cert_times(x509ss, NULL, NULL, days))
+ if (!set_cert_times(new_x509, NULL, NULL, days))
+ goto end;
+ if (!X509_set_subject_name(new_x509, n_subj))
goto end;
- if (!X509_set_subject_name
- (x509ss, X509_REQ_get_subject_name(req)))
+ if (!pub_key || !X509_set_pubkey(new_x509, pub_key))
goto end;
- tmppkey = X509_REQ_get0_pubkey(req);
- if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey))
+ if (ext_copy == EXT_COPY_UNSET) {
+ if (infile != NULL)
+ BIO_printf(bio_err, "Warning: No -copy_extensions given; ignoring any extensions in the request\n");
+ } else if (!copy_extensions(new_x509, req, ext_copy)) {
+ BIO_printf(bio_err, "Error copying extensions from request\n");
goto end;
+ }
/* Set up V3 context struct */
-
- X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
+ X509V3_set_ctx(&ext_ctx, CAcert != NULL ? CAcert : new_x509,
+ new_x509, NULL, NULL, X509V3_CTX_REPLACE);
+ /* prepare fallback for AKID, but only if issuer cert == new_x509 */
+ if (CAcert == NULL) {
+ if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key))
+ goto end;
+ ERR_set_mark();
+ if (!X509_check_private_key(new_x509, issuer_key))
+ BIO_printf(bio_err,
+ "Warning: Signature key and public key of cert do not match\n");
+ ERR_pop_to_mark();
+ }
X509V3_set_nconf(&ext_ctx, req_conf);
/* Add extensions */
- if (extensions != NULL && !X509V3_EXT_add_nconf(req_conf,
- &ext_ctx, extensions,
- x509ss)) {
- BIO_printf(bio_err, "Error Loading extension section %s\n",
+ if (extensions != NULL
+ && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extensions,
+ new_x509)) {
+ BIO_printf(bio_err, "Error adding x509 extensions from 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");
+ new_x509)) {
+ BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
goto end;
}
/* 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) {
+ if (X509_add1_ext_i2d(new_x509, 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);
+ i = do_X509_sign(new_x509, issuer_key, digest, sigopts, &ext_ctx);
+ if (!i)
goto end;
- }
} else {
X509V3_CTX ext_ctx;
/* Set up V3 context struct */
-
X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
X509V3_set_nconf(&ext_ctx, req_conf);
@@ -798,49 +886,39 @@ int req_main(int argc, char **argv)
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",
+ BIO_printf(bio_err, "Error adding request extensions from section %s\n",
req_exts);
goto end;
}
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");
+ BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
goto end;
}
i = do_X509_REQ_sign(req, pkey, digest, sigopts);
- if (!i) {
- ERR_print_errors(bio_err);
+ if (!i)
goto end;
- }
}
}
- if (subj && x509) {
- BIO_printf(bio_err, "Cannot modify certificate subject\n");
- goto end;
- }
-
- if (subj && !x509) {
+ if (subj != NULL && !newreq && !gen_x509) {
if (verbose) {
- BIO_printf(bio_err, "Modifying Request's Subject\n");
- print_name(bio_err, "old subject=",
- X509_REQ_get_subject_name(req), get_nameopt());
+ BIO_printf(out, "Modifying subject of certificate request\n");
+ print_name(out, "Old subject=", X509_REQ_get_subject_name(req));
}
- if (build_subject(req, subj, chtype, multirdn) == 0) {
- BIO_printf(bio_err, "ERROR: cannot modify subject\n");
- ret = 1;
+ if (!X509_REQ_set_subject_name(req, fsubj)) {
+ BIO_printf(bio_err, "Error modifying subject of certificate request\n");
goto end;
}
if (verbose) {
- print_name(bio_err, "new subject=",
- X509_REQ_get_subject_name(req), get_nameopt());
+ print_name(out, "New subject=", X509_REQ_get_subject_name(req));
}
}
- if (verify && !x509) {
+ if (verify) {
EVP_PKEY *tpubkey = pkey;
if (tpubkey == NULL) {
@@ -849,16 +927,14 @@ int req_main(int argc, char **argv)
goto end;
}
- i = X509_REQ_verify(req, tpubkey);
+ i = do_X509_REQ_verify(req, tpubkey, vfyopts);
- if (i < 0) {
+ 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) */
- BIO_printf(bio_err, "verify OK\n");
- }
+ if (i == 0)
+ BIO_printf(bio_err, "Certificate request self-signature verify failure\n");
+ else /* i > 0 */
+ BIO_printf(bio_err, "Certificate request self-signature verify OK\n");
}
if (noout && !text && !modulus && !subject && !pubkey) {
@@ -878,62 +954,58 @@ int req_main(int argc, char **argv)
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);
}
if (text) {
- if (x509)
- ret = X509_print_ex(out, x509ss, get_nameopt(), reqflag);
+ if (gen_x509)
+ ret = X509_print_ex(out, new_x509, get_nameopt(), reqflag);
else
ret = X509_REQ_print_ex(out, req, get_nameopt(), reqflag);
if (ret == 0) {
- if (x509)
- BIO_printf(bio_err, "Error printing certificate\n");
+ if (gen_x509)
+ BIO_printf(bio_err, "Error printing certificate\n");
else
- BIO_printf(bio_err, "Error printing certificate request\n");
-
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error printing certificate request\n");
goto end;
}
}
if (subject) {
- if (x509)
- print_name(out, "subject=", X509_get_subject_name(x509ss),
- get_nameopt());
- else
- print_name(out, "subject=", X509_REQ_get_subject_name(req),
- get_nameopt());
+ print_name(out, "subject=", gen_x509
+ ? X509_get_subject_name(new_x509)
+ : X509_REQ_get_subject_name(req));
}
if (modulus) {
EVP_PKEY *tpubkey;
- if (x509)
- tpubkey = X509_get0_pubkey(x509ss);
+ if (gen_x509)
+ tpubkey = X509_get0_pubkey(new_x509);
else
tpubkey = X509_REQ_get0_pubkey(req);
if (tpubkey == NULL) {
- fprintf(stdout, "Modulus=unavailable\n");
+ fprintf(stdout, "Modulus is unavailable\n");
goto end;
}
fprintf(stdout, "Modulus=");
-#ifndef OPENSSL_NO_RSA
- if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) {
- const BIGNUM *n;
- RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL);
+ if (EVP_PKEY_is_a(tpubkey, "RSA") || EVP_PKEY_is_a(tpubkey, "RSA-PSS")) {
+ BIGNUM *n = NULL;
+
+ if (!EVP_PKEY_get_bn_param(tpubkey, "n", &n))
+ goto end;
BN_print(out, n);
- } else
-#endif
+ BN_free(n);
+ } else {
fprintf(stdout, "Wrong Algorithm type");
+ }
fprintf(stdout, "\n");
}
- if (!noout && !x509) {
+ if (!noout && !gen_x509) {
if (outformat == FORMAT_ASN1)
i = i2d_X509_REQ_bio(out, req);
else if (newhdr)
@@ -941,17 +1013,17 @@ int req_main(int argc, char **argv)
else
i = PEM_write_bio_X509_REQ(out, req);
if (!i) {
- BIO_printf(bio_err, "unable to write X509 request\n");
+ BIO_printf(bio_err, "Unable to write certificate request\n");
goto end;
}
}
- if (!noout && x509 && (x509ss != NULL)) {
+ if (!noout && gen_x509 && new_x509 != NULL) {
if (outformat == FORMAT_ASN1)
- i = i2d_X509_bio(out, x509ss);
+ i = i2d_X509_bio(out, new_x509);
else
- i = PEM_write_bio_X509(out, x509ss);
+ i = PEM_write_bio_X509(out, new_x509);
if (!i) {
- BIO_printf(bio_err, "unable to write X509 certificate\n");
+ BIO_printf(bio_err, "Unable to write X509 certificate\n");
goto end;
}
}
@@ -963,20 +1035,23 @@ int req_main(int argc, char **argv)
NCONF_free(req_conf);
NCONF_free(addext_conf);
BIO_free(addext_bio);
- BIO_free(in);
BIO_free_all(out);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(genctx);
sk_OPENSSL_STRING_free(pkeyopts);
sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(vfyopts);
lh_OPENSSL_STRING_doall(addexts, exts_cleanup);
lh_OPENSSL_STRING_free(addexts);
#ifndef OPENSSL_NO_ENGINE
- ENGINE_free(gen_eng);
+ release_engine(gen_eng);
#endif
OPENSSL_free(keyalgstr);
X509_REQ_free(req);
- X509_free(x509ss);
+ X509_NAME_free(fsubj);
+ X509_free(new_x509);
+ X509_free(CAcert);
+ EVP_PKEY_free(CAkey);
ASN1_INTEGER_free(serial);
release_engine(e);
if (passin != nofree_passin)
@@ -986,50 +1061,48 @@ int req_main(int argc, char **argv)
return ret;
}
-static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
- int attribs, unsigned long chtype)
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj,
+ int multirdn, int attribs, unsigned long chtype)
{
int ret = 0, i;
char no_prompt = 0;
- STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
+ STACK_OF(CONF_VALUE) *dn_sk = NULL, *attr_sk = NULL;
char *tmp, *dn_sect, *attr_sect;
- tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
+ tmp = NCONF_get_string(req_conf, section, PROMPT);
if (tmp == NULL)
ERR_clear_error();
if ((tmp != NULL) && strcmp(tmp, "no") == 0)
no_prompt = 1;
- dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
+ dn_sect = NCONF_get_string(req_conf, section, DISTINGUISHED_NAME);
if (dn_sect == NULL) {
- BIO_printf(bio_err, "unable to find '%s' in config\n",
- DISTINGUISHED_NAME);
- goto err;
- }
- dn_sk = NCONF_get_section(req_conf, dn_sect);
- if (dn_sk == NULL) {
- BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
- goto err;
+ ERR_clear_error();
+ } else {
+ dn_sk = NCONF_get_section(req_conf, dn_sect);
+ if (dn_sk == NULL) {
+ BIO_printf(bio_err, "Unable to get '%s' section\n", dn_sect);
+ goto err;
+ }
}
- attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
+ attr_sect = NCONF_get_string(req_conf, section, ATTRIBUTES);
if (attr_sect == NULL) {
ERR_clear_error();
- attr_sk = NULL;
} else {
attr_sk = NCONF_get_section(req_conf, attr_sect);
if (attr_sk == NULL) {
- BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
+ BIO_printf(bio_err, "Unable to get '%s' section\n", attr_sect);
goto err;
}
}
- /* setup version number */
- if (!X509_REQ_set_version(req, 0L))
- goto err; /* version 1 */
+ /* so far there is only version 1 */
+ if (!X509_REQ_set_version(req, X509_REQ_VERSION_1))
+ goto err;
- if (subj)
- i = build_subject(req, subj, chtype, multirdn);
+ if (fsubj != NULL)
+ i = X509_REQ_set_subject_name(req, fsubj);
else if (no_prompt)
i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
else
@@ -1046,26 +1119,6 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
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, const char *subject, unsigned long chtype,
- int multirdn)
-{
- X509_NAME *n;
-
- if ((n = parse_name(subject, chtype, multirdn)) == NULL)
- return 0;
-
- if (!X509_REQ_set_subject_name(req, n)) {
- X509_NAME_free(n);
- return 0;
- }
- X509_NAME_free(n);
- return 1;
-}
-
static int prompt_info(X509_REQ *req,
STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
@@ -1079,8 +1132,7 @@ static int prompt_info(X509_REQ *req,
char *type, *value;
const char *def;
CONF_VALUE *v;
- X509_NAME *subj;
- subj = X509_REQ_get_subject_name(req);
+ X509_NAME *subj = X509_REQ_get_subject_name(req);
if (!batch) {
BIO_printf(bio_err,
@@ -1100,7 +1152,7 @@ static int prompt_info(X509_REQ *req,
if (sk_CONF_VALUE_num(dn_sk)) {
i = -1;
start:
- for ( ; ; ) {
+ for (;;) {
i++;
if (sk_CONF_VALUE_num(dn_sk) <= i)
break;
@@ -1152,7 +1204,6 @@ static int prompt_info(X509_REQ *req,
n_min = -1;
}
-
if (!join(buf, sizeof(buf), v->name, "_max", "Name"))
return 0;
if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
@@ -1165,8 +1216,7 @@ static int prompt_info(X509_REQ *req,
return 0;
}
if (X509_NAME_entry_count(subj) == 0) {
- BIO_printf(bio_err,
- "error, no objects specified in config file\n");
+ BIO_printf(bio_err, "Error: No objects specified in config file\n");
return 0;
}
@@ -1181,7 +1231,7 @@ static int prompt_info(X509_REQ *req,
i = -1;
start2:
- for ( ; ; ) {
+ for (;;) {
i++;
if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i))
break;
@@ -1207,7 +1257,7 @@ static int prompt_info(X509_REQ *req,
value = NULL;
}
- if (!join(buf, sizeof(buf), type,"_min", "Name"))
+ if (!join(buf, sizeof(buf), type, "_min", "Name"))
return 0;
if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
ERR_clear_error();
@@ -1258,10 +1308,10 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
*/
for (p = v->name; *p; p++) {
#ifndef CHARSET_EBCDIC
- spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
+ spec_char = (*p == ':' || *p == ',' || *p == '.');
#else
- spec_char = ((*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++;
@@ -1289,7 +1339,7 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
}
if (!X509_NAME_entry_count(subj)) {
- BIO_printf(bio_err, "error, no objects specified in config file\n");
+ BIO_printf(bio_err, "Error: No objects specified in config file\n");
return 0;
}
if (attribs) {
@@ -1339,19 +1389,15 @@ static int add_attribute_object(X509_REQ *req, char *text, const char *def,
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
- )
+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:
@@ -1386,7 +1432,7 @@ static int build_data(char *text, const char *def,
i = strlen(buf);
if (buf[i - 1] != '\n') {
- BIO_printf(bio_err, "weird input :-(\n");
+ BIO_printf(bio_err, "Missing newline at end of input\n");
return 0;
}
buf[--i] = '\0';
@@ -1403,16 +1449,14 @@ static int build_data(char *text, const char *def,
static int req_check_len(int len, int n_min, int n_max)
{
- if ((n_min > 0) && (len < n_min)) {
+ if (n_min > 0 && len < n_min) {
BIO_printf(bio_err,
- "string is too short, it needs to be at least %d bytes long\n",
- n_min);
+ "String too short, must be at least %d bytes long\n", n_min);
return 0;
}
- if ((n_max >= 0) && (len > n_max)) {
+ if (n_max >= 0 && len > n_max) {
BIO_printf(bio_err,
- "string is too long, it needs to be no more than %d bytes long\n",
- n_max);
+ "String too long, must be at most %d bytes long\n", n_max);
return 0;
}
return 1;
@@ -1451,66 +1495,71 @@ static int join(char buf[], size_t buf_size, const char *name,
}
static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
- int *pkey_type, long *pkeylen,
- char **palgnam, ENGINE *keygen_engine)
+ char **pkeytype, long *pkeylen,
+ ENGINE *keygen_engine)
{
EVP_PKEY_CTX *gctx = NULL;
EVP_PKEY *param = NULL;
long keylen = -1;
BIO *pbio = NULL;
+ const char *keytype = NULL;
+ size_t keytypelen = 0;
+ int expect_paramfile = 0;
const char *paramfile = NULL;
+ /* Treat the first part of gstr, and only that */
if (gstr == NULL) {
- *pkey_type = EVP_PKEY_RSA;
+ /*
+ * Special case: when no string given, default to RSA and the
+ * key length given by |*pkeylen|.
+ */
+ keytype = "RSA";
keylen = *pkeylen;
} else if (gstr[0] >= '0' && gstr[0] <= '9') {
- *pkey_type = EVP_PKEY_RSA;
- keylen = atol(gstr);
- *pkeylen = keylen;
- } else if (strncmp(gstr, "param:", 6) == 0) {
- paramfile = gstr + 6;
+ /* Special case: only keylength given from string, so default to RSA */
+ keytype = "RSA";
+ /* The second part treatment will do the rest */
} else {
const char *p = strchr(gstr, ':');
int len;
- ENGINE *tmpeng;
- const EVP_PKEY_ASN1_METHOD *ameth;
if (p != NULL)
len = p - gstr;
else
len = strlen(gstr);
- /*
- * The lookup of a the string will cover all engines so keep a note
- * of the implementation.
- */
- ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len);
-
- 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
- ENGINE_finish(tmpeng);
-#endif
- if (*pkey_type == EVP_PKEY_RSA) {
- if (p != NULL) {
- keylen = atol(p + 1);
- *pkeylen = keylen;
- } else {
- keylen = *pkeylen;
+ if (strncmp(gstr, "param", len) == 0) {
+ expect_paramfile = 1;
+ if (p == NULL) {
+ BIO_printf(bio_err,
+ "Parameter file requested but no path given: %s\n",
+ gstr);
+ return NULL;
}
- } else if (p != NULL) {
- paramfile = p + 1;
+ } else {
+ keytype = gstr;
+ keytypelen = len;
}
+
+ if (p != NULL)
+ gstr = gstr + len + 1;
+ else
+ gstr = NULL;
+ }
+
+ /* Treat the second part of gstr, if there is one */
+ if (gstr != NULL) {
+ /* If the second part starts with a digit, we assume it's a size */
+ if (!expect_paramfile && gstr[0] >= '0' && gstr[0] <= '9')
+ keylen = atol(gstr);
+ else
+ paramfile = gstr;
}
if (paramfile != NULL) {
pbio = BIO_new_file(paramfile, "r");
if (pbio == NULL) {
- BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile);
+ BIO_printf(bio_err, "Cannot open parameter file %s\n", paramfile);
return NULL;
}
param = PEM_read_bio_Parameters(pbio, NULL);
@@ -1532,62 +1581,83 @@ static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile);
return NULL;
}
- if (*pkey_type == -1) {
- *pkey_type = EVP_PKEY_id(param);
- } 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 (keytype == NULL) {
+ keytype = EVP_PKEY_get0_type_name(param);
+ if (keytype == NULL) {
+ EVP_PKEY_free(param);
+ BIO_puts(bio_err, "Unable to determine key type\n");
+ return NULL;
+ }
}
}
- if (palgnam != NULL) {
- const EVP_PKEY_ASN1_METHOD *ameth;
- ENGINE *tmpeng;
- const char *anam;
+ if (keytypelen > 0)
+ *pkeytype = OPENSSL_strndup(keytype, keytypelen);
+ else
+ *pkeytype = OPENSSL_strdup(keytype);
- ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type);
- 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 = OPENSSL_strdup(anam);
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(tmpeng);
-#endif
+ if (*pkeytype == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ EVP_PKEY_free(param);
+ return NULL;
}
+ if (keylen >= 0)
+ *pkeylen = keylen;
+
if (param != NULL) {
- gctx = EVP_PKEY_CTX_new(param, keygen_engine);
- *pkeylen = EVP_PKEY_bits(param);
+ if (!EVP_PKEY_is_a(param, *pkeytype)) {
+ BIO_printf(bio_err, "Key type does not match parameters\n");
+ EVP_PKEY_free(param);
+ return NULL;
+ }
+
+ if (keygen_engine != NULL)
+ gctx = EVP_PKEY_CTX_new(param, keygen_engine);
+ else
+ gctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
+ param, app_get0_propq());
+ *pkeylen = EVP_PKEY_get_bits(param);
EVP_PKEY_free(param);
} else {
- gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine);
+ if (keygen_engine != NULL) {
+ int pkey_id = get_legacy_pkey_id(app_get0_libctx(), *pkeytype,
+ keygen_engine);
+
+ if (pkey_id != NID_undef)
+ gctx = EVP_PKEY_CTX_new_id(pkey_id, keygen_engine);
+ } else {
+ gctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(),
+ *pkeytype, app_get0_propq());
+ }
}
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(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(bio_err, "Error setting RSA keysize\n");
- ERR_print_errors(bio_err);
+ if (keylen == -1 && (EVP_PKEY_CTX_is_a(gctx, "RSA")
+ || EVP_PKEY_CTX_is_a(gctx, "RSA-PSS")))
+ keylen = *pkeylen;
+
+ if (keylen != -1) {
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ size_t bits = keylen;
+
+ params[0] =
+ OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_BITS, &bits);
+ if (EVP_PKEY_CTX_set_params(gctx, params) <= 0) {
+ BIO_puts(bio_err, "Error setting keysize\n");
EVP_PKEY_CTX_free(gctx);
return NULL;
}
}
-#endif
return gctx;
}
@@ -1610,70 +1680,3 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx)
(void)BIO_flush(b);
return 1;
}
-
-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, 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(bio_err, "parameter error \"%s\"\n", sigopt);
- ERR_print_errors(bio_err);
- return 0;
- }
- }
- return 1;
-}
-
-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_new();
-
- rv = do_sign_init(mctx, pkey, md, sigopts);
- if (rv > 0)
- rv = X509_sign_ctx(x, mctx);
- EVP_MD_CTX_free(mctx);
- return rv > 0 ? 1 : 0;
-}
-
-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_new();
- rv = do_sign_init(mctx, pkey, md, sigopts);
- if (rv > 0)
- rv = X509_REQ_sign_ctx(x, mctx);
- EVP_MD_CTX_free(mctx);
- return rv > 0 ? 1 : 0;
-}
-
-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_new();
- rv = do_sign_init(mctx, pkey, md, sigopts);
- if (rv > 0)
- 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 aeda917cc768..0da342c38f2c 100644
--- a/apps/rsa.c
+++ b/apps/rsa.c
@@ -1,13 +1,17 @@
/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
*/
+/* Necessary for legacy RSA public key export */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -21,60 +25,119 @@
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
+#include <openssl/encoder.h>
+
+/*
+ * This include is to get OSSL_KEYMGMT_SELECT_*, which feels a bit
+ * much just for those macros... they might serve better as EVP macros.
+ */
+#include <openssl/core_dispatch.h>
+
+#ifndef OPENSSL_NO_RC4
+# define DEFAULT_PVK_ENCR_STRENGTH 2
+#else
+# define DEFAULT_PVK_ENCR_STRENGTH 0
+#endif
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER,
+ OPT_PROV_ENUM, OPT_TRADITIONAL
} OPTION_CHOICE;
const OPTIONS rsa_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
- {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"},
- {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"},
+ {"check", OPT_CHECK, '-', "Verify key consistency"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input file"},
- {"out", OPT_OUT, '>', "Output file"},
+ {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"},
{"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"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"},
+ {"pubout", OPT_PUBOUT, '-', "Output a public key"},
{"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
{"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)
+ {"traditional", OPT_TRADITIONAL, '-',
+ "Use traditional format for private keys"},
+
+#ifndef OPENSSL_NO_RC4
+ OPT_SECTION("PVK"),
{"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
+
+ OPT_PROV_OPTIONS,
{NULL}
};
+static int try_legacy_encoding(EVP_PKEY *pkey, int outformat, int pubout,
+ BIO *out)
+{
+ int ret = 0;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ const RSA *rsa = EVP_PKEY_get0_RSA(pkey);
+
+ if (rsa == NULL)
+ return 0;
+
+ if (outformat == FORMAT_ASN1) {
+ if (pubout == 2)
+ ret = i2d_RSAPublicKey_bio(out, rsa) > 0;
+ else
+ ret = i2d_RSA_PUBKEY_bio(out, rsa) > 0;
+ } else if (outformat == FORMAT_PEM) {
+ if (pubout == 2)
+ ret = PEM_write_bio_RSAPublicKey(out, rsa) > 0;
+ else
+ ret = PEM_write_bio_RSA_PUBKEY(out, rsa) > 0;
+# ifndef OPENSSL_NO_DSA
+ } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
+ ret = i2b_PublicKey_bio(out, pkey) > 0;
+# endif
+ }
+#endif
+
+ return ret;
+}
+
int rsa_main(int argc, char **argv)
{
ENGINE *e = NULL;
BIO *out = NULL;
- RSA *rsa = NULL;
- const EVP_CIPHER *enc = NULL;
- char *infile = NULL, *outfile = NULL, *prog;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *pctx;
+ EVP_CIPHER *enc = NULL;
+ char *infile = NULL, *outfile = NULL, *ciphername = 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 private = 0;
+ int informat = FORMAT_UNDEF, 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;
-#endif
+ int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH;
OPTION_CHOICE o;
+ int traditional = 0;
+ const char *output_type = NULL;
+ const char *output_structure = NULL;
+ int selection = 0;
+ OSSL_ENCODER_CTX *ectx = NULL;
prog = opt_init(argc, argv, rsa_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -126,9 +189,7 @@ int rsa_main(int argc, char **argv)
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;
@@ -143,15 +204,27 @@ int rsa_main(int argc, char **argv)
check = 1;
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &enc))
- goto opthelp;
+ ciphername = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
+ case OPT_TRADITIONAL:
+ traditional = 1;
break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (ciphername != NULL) {
+ if (!opt_cipher(ciphername, &enc))
+ goto opthelp;
+ }
private = (text && !pubin) || (!pubout && !noout) ? 1 : 0;
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
@@ -163,34 +236,31 @@ int rsa_main(int argc, char **argv)
goto end;
}
- {
- EVP_PKEY *pkey;
+ if (pubin) {
+ int tmpformat = FORMAT_UNDEF;
- if (pubin) {
- int tmpformat = -1;
- if (pubin == 2) {
- if (informat == FORMAT_PEM)
- tmpformat = FORMAT_PEMRSA;
- else if (informat == FORMAT_ASN1)
- tmpformat = FORMAT_ASN1RSA;
- } else {
- tmpformat = informat;
- }
-
- pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key");
+ if (pubin == 2) {
+ if (informat == FORMAT_PEM)
+ tmpformat = FORMAT_PEMRSA;
+ else if (informat == FORMAT_ASN1)
+ tmpformat = FORMAT_ASN1RSA;
} else {
- pkey = load_key(infile, informat, 1, passin, e, "Private Key");
+ tmpformat = informat;
}
- if (pkey != NULL)
- rsa = EVP_PKEY_get1_RSA(pkey);
- EVP_PKEY_free(pkey);
+ pkey = load_pubkey(infile, tmpformat, 1, passin, e, "public key");
+ } else {
+ pkey = load_key(infile, informat, 1, passin, e, "private key");
}
- if (rsa == NULL) {
+ if (pkey == NULL) {
ERR_print_errors(bio_err);
goto end;
}
+ if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+ BIO_printf(bio_err, "Not an RSA key\n");
+ goto end;
+ }
out = bio_open_owner(outfile, outformat, private);
if (out == NULL)
@@ -198,7 +268,8 @@ int rsa_main(int argc, char **argv)
if (text) {
assert(pubin || private);
- if (!RSA_print(out, rsa, 0)) {
+ if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
+ || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) {
perror(outfile);
ERR_print_errors(bio_err);
goto end;
@@ -206,30 +277,34 @@ int rsa_main(int argc, char **argv)
}
if (modulus) {
- const BIGNUM *n;
- RSA_get0_key(rsa, &n, NULL, NULL);
+ BIGNUM *n = NULL;
+
+ /* Every RSA key has an 'n' */
+ EVP_PKEY_get_bn_param(pkey, "n", &n);
BIO_printf(out, "Modulus=");
BN_print(out, n);
BIO_printf(out, "\n");
+ BN_free(n);
}
if (check) {
- int r = RSA_check_key_ex(rsa, NULL);
+ int r;
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+ if (pctx == NULL) {
+ BIO_printf(bio_err, "RSA unable to create PKEY context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ r = EVP_PKEY_check(pctx);
+ EVP_PKEY_CTX_free(pctx);
if (r == 1) {
BIO_printf(out, "RSA key ok\n");
} 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_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 err from error stack */
- }
- } else if (r == -1) {
+ BIO_printf(bio_err, "RSA key not ok\n");
+ ERR_print_errors(bio_err);
+ } else if (r < 0) {
ERR_print_errors(bio_err);
goto end;
}
@@ -240,71 +315,100 @@ int rsa_main(int argc, char **argv)
goto end;
}
BIO_printf(bio_err, "writing RSA key\n");
+
+ /* Choose output type for the format */
if (outformat == FORMAT_ASN1) {
- if (pubout || pubin) {
- if (pubout == 2)
- i = i2d_RSAPublicKey_bio(out, rsa);
- else
- i = i2d_RSA_PUBKEY_bio(out, rsa);
- } else {
- assert(private);
- i = i2d_RSAPrivateKey_bio(out, rsa);
- }
+ output_type = "DER";
} else if (outformat == FORMAT_PEM) {
+ output_type = "PEM";
+ } else if (outformat == FORMAT_MSBLOB) {
+ output_type = "MSBLOB";
+ } else if (outformat == FORMAT_PVK) {
+ if (pubin) {
+ BIO_printf(bio_err, "PVK form impossible with public key input\n");
+ goto end;
+ }
+ output_type = "PVK";
+ } else {
+ BIO_printf(bio_err, "bad output format specified for outfile\n");
+ goto end;
+ }
+
+ /* Select what you want in the output */
+ if (pubout || pubin) {
+ selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+ } else {
+ assert(private);
+ selection = (OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
+ }
+
+ /* For DER based output, select the desired output structure */
+ if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) {
if (pubout || pubin) {
if (pubout == 2)
- i = PEM_write_bio_RSAPublicKey(out, rsa);
+ output_structure = "pkcs1"; /* "type-specific" would work too */
else
- i = PEM_write_bio_RSA_PUBKEY(out, rsa);
+ output_structure = "SubjectPublicKeyInfo";
} else {
assert(private);
- i = PEM_write_bio_RSAPrivateKey(out, rsa,
- enc, NULL, 0, NULL, passout);
+ if (traditional)
+ output_structure = "pkcs1"; /* "type-specific" would work too */
+ else
+ output_structure = "PrivateKeyInfo";
}
-#ifndef OPENSSL_NO_DSA
- } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
- EVP_PKEY *pk;
- pk = EVP_PKEY_new();
- if (pk == NULL)
- goto end;
+ }
- EVP_PKEY_set1_RSA(pk, rsa);
- 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);
+ /* Now, perform the encoding */
+ ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection,
+ output_type, output_structure,
+ NULL);
+ if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) {
+ if ((!pubout && !pubin)
+ || !try_legacy_encoding(pkey, outformat, pubout, out))
+ BIO_printf(bio_err, "%s format not supported\n", output_type);
+ else
+ ret = 0;
+ goto end;
+ }
+
+ /* Passphrase setup */
+ if (enc != NULL)
+ OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL);
+
+ /* Default passphrase prompter */
+ if (enc != NULL || outformat == FORMAT_PVK) {
+ OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL);
+ if (passout != NULL)
+ /* When passout given, override the passphrase prompter */
+ OSSL_ENCODER_CTX_set_passphrase(ectx,
+ (const unsigned char *)passout,
+ strlen(passout));
+ }
+
+ /* PVK is a bit special... */
+ if (outformat == FORMAT_PVK) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr);
+ if (!OSSL_ENCODER_CTX_set_params(ectx, params)) {
+ BIO_printf(bio_err, "invalid PVK encryption level\n");
goto end;
-# else
- i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
-# endif
- } else if (pubin || pubout) {
- i = i2b_PublicKey_bio(out, pk);
- } else {
- assert(private);
- i = i2b_PrivateKey_bio(out, pk);
}
- EVP_PKEY_free(pk);
-#endif
- } else {
- BIO_printf(bio_err, "bad output format specified for outfile\n");
- goto end;
}
- if (i <= 0) {
+
+ if (!OSSL_ENCODER_to_bio(ectx, out)) {
BIO_printf(bio_err, "unable to write key\n");
ERR_print_errors(bio_err);
- } else {
- ret = 0;
+ goto end;
}
+ ret = 0;
end:
+ OSSL_ENCODER_CTX_free(ectx);
release_engine(e);
BIO_free_all(out);
- RSA_free(rsa);
+ EVP_PKEY_free(pkey);
+ EVP_CIPHER_free(enc);
OPENSSL_free(passin);
OPENSSL_free(passout);
return ret;
diff --git a/apps/rsautl.c b/apps/rsautl.c
index 0c0fa8eba30a..df29069bc1f4 100644
--- a/apps/rsautl.c
+++ b/apps/rsautl.c
@@ -1,13 +1,14 @@
/*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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 <string.h>
@@ -25,40 +26,46 @@
#define KEY_CERT 3
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP,
- OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
+ OPT_RSA_RAW, OPT_OAEP, 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
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS rsautl_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"sign", OPT_SIGN, '-', "Sign with private key"},
+ {"verify", OPT_VERIFY, '-', "Verify with public key"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Input"),
{"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"},
+ {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
{"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"},
+ {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file"},
+ {"raw", OPT_RSA_RAW, '-', "Use no padding"},
{"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"},
+ {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"},
{"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
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -67,14 +74,15 @@ int rsautl_main(int argc, char **argv)
BIO *in = NULL, *out = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
- RSA *rsa = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
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;
+ size_t rsa_inlen, rsa_outlen = 0;
+ int keyformat = FORMAT_UNDEF, keysize, ret = 1, rv;
+ int hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0;
OPTION_CHOICE o;
prog = opt_init(argc, argv, rsautl_options);
@@ -90,7 +98,7 @@ int rsautl_main(int argc, char **argv)
ret = 0;
goto end;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_IN:
@@ -108,15 +116,12 @@ int rsautl_main(int argc, char **argv)
case OPT_HEXDUMP:
hexdump = 1;
break;
- case OPT_RAW:
+ case OPT_RSA_RAW:
pad = RSA_NO_PADDING;
break;
case OPT_OAEP:
pad = RSA_PKCS1_OAEP_PADDING;
break;
- case OPT_SSL:
- pad = RSA_SSLV23_PADDING;
- break;
case OPT_PKCS:
pad = RSA_PKCS1_PADDING;
break;
@@ -156,12 +161,21 @@ int rsautl_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
if (need_priv && (key_type != KEY_PRIVKEY)) {
BIO_printf(bio_err, "A private key is needed for this operation\n");
goto end;
@@ -174,15 +188,15 @@ int rsautl_main(int argc, char **argv)
switch (key_type) {
case KEY_PRIVKEY:
- pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key");
+ pkey = load_key(keyfile, keyformat, 0, passin, e, "private key");
break;
case KEY_PUBKEY:
- pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key");
+ pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "public key");
break;
case KEY_CERT:
- x = load_cert(keyfile, keyformat, "Certificate");
+ x = load_cert(keyfile, FORMAT_UNDEF, "Certificate");
if (x) {
pkey = X509_get_pubkey(x);
X509_free(x);
@@ -193,15 +207,6 @@ int rsautl_main(int argc, char **argv)
if (pkey == NULL)
return 1;
- rsa = EVP_PKEY_get1_RSA(pkey);
- EVP_PKEY_free(pkey);
-
- if (rsa == NULL) {
- BIO_printf(bio_err, "Error getting RSA key\n");
- ERR_print_errors(bio_err);
- goto end;
- }
-
in = bio_open_default(infile, 'r', FORMAT_BINARY);
if (in == NULL)
goto end;
@@ -209,48 +214,58 @@ int rsautl_main(int argc, char **argv)
if (out == NULL)
goto end;
- keysize = RSA_size(rsa);
+ keysize = EVP_PKEY_get_size(pkey);
rsa_in = app_malloc(keysize * 2, "hold rsa key");
rsa_out = app_malloc(keysize, "output rsa key");
+ rsa_outlen = keysize;
/* Read the input data */
- rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
- if (rsa_inlen < 0) {
+ rv = BIO_read(in, rsa_in, keysize * 2);
+ if (rv < 0) {
BIO_printf(bio_err, "Error reading input Data\n");
goto end;
}
+ rsa_inlen = rv;
if (rev) {
- int i;
+ size_t i;
unsigned char ctmp;
+
for (i = 0; i < rsa_inlen / 2; i++) {
ctmp = rsa_in[i];
rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
rsa_in[rsa_inlen - 1 - i] = ctmp;
}
}
- switch (rsa_mode) {
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL)
+ goto end;
+
+ switch (rsa_mode) {
case RSA_VERIFY:
- rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_verify_recover_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_verify_recover(ctx, rsa_out, &rsa_outlen,
+ rsa_in, rsa_inlen) > 0;
break;
-
case RSA_SIGN:
- rsa_outlen =
- RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_sign_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_sign(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
break;
-
case RSA_ENCRYPT:
- rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_encrypt_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_encrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
break;
-
case RSA_DECRYPT:
- rsa_outlen =
- RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ rv = EVP_PKEY_decrypt_init(ctx) > 0
+ && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
+ && EVP_PKEY_decrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
break;
}
- if (rsa_outlen < 0) {
+ if (!rv) {
BIO_printf(bio_err, "RSA operation error\n");
ERR_print_errors(bio_err);
goto end;
@@ -266,7 +281,8 @@ int rsautl_main(int argc, char **argv)
BIO_write(out, rsa_out, rsa_outlen);
}
end:
- RSA_free(rsa);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
release_engine(e);
BIO_free(in);
BIO_free_all(out);
diff --git a/apps/s_client.c b/apps/s_client.c
index 00effc80375a..a9142386428d 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -1,8 +1,8 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -38,10 +38,8 @@ typedef unsigned int u_int;
#include <openssl/rand.h>
#include <openssl/ocsp.h>
#include <openssl/bn.h>
+#include <openssl/trace.h>
#include <openssl/async.h>
-#ifndef OPENSSL_NO_SRP
-# include <openssl/srp.h>
-#endif
#ifndef OPENSSL_NO_CT
# include <openssl/ct.h>
#endif
@@ -91,27 +89,6 @@ static int restore_errno(void)
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);
-}
-
/* Default PSK identity and key */
static char *psk_identity = "Client_identity";
@@ -258,117 +235,6 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
return SSL_TLSEXT_ERR_OK;
}
-#ifndef OPENSSL_NO_SRP
-
-/* This is a context that we pass to all callbacks */
-typedef struct srp_arg_st {
- char *srppassin;
- char *srplogin;
- int msg; /* copy from c_msg */
- int debug; /* copy from c_debug */
- int amp; /* allow more groups */
- int strength; /* minimal size for N */
-} SRP_ARG;
-
-# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64
-
-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) == 1 &&
- p != NULL && BN_rshift1(p, N) &&
- /* p = (N-1)/2 */
- 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;
-
- BN_free(r);
- BN_free(p);
- BN_CTX_free(bn_ctx);
- return ret;
-}
-
-/*-
- * This callback is used here for two purposes:
- * - extended debugging
- * - making some primality tests for unknown groups
- * The callback is only called for a non default group.
- *
- * An application does not need the call back at all if
- * 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
- * is not one of those defined in RFC 5054, it is more appropriate
- * to add the group to a static list and then compare since
- * primality tests are rather cpu consuming.
- */
-
-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)) == 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");
- BIO_printf(bio_err, "\tN=");
- BN_print(bio_err, N);
- BIO_printf(bio_err, "\n\tg=");
- BN_print(bio_err, g);
- BIO_printf(bio_err, "\n");
- }
-
- if (SRP_check_known_gN_param(g, N))
- return 1;
-
- if (srp_arg->amp == 1) {
- if (srp_arg->debug)
- BIO_printf(bio_err,
- "SRP param N and g are not known params, going to check deeper.\n");
-
- /*
- * The srp_moregroups is a real debugging feature. Implementors
- * should rather add the value to the known ones. The minimal size
- * has already been tested.
- */
- if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g))
- return 1;
- }
- BIO_printf(bio_err, "SRP param N and g rejected.\n");
- return 0;
-}
-
-# define PWD_STRLEN 1024
-
-static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
-{
- SRP_ARG *srp_arg = (SRP_ARG *)arg;
- char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer");
- PW_CB_DATA cb_tmp;
- int l;
-
- cb_tmp.password = (char *)srp_arg->srppassin;
- cb_tmp.prompt_info = "SRP user";
- if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) {
- BIO_printf(bio_err, "Can't read Password\n");
- OPENSSL_free(pass);
- return NULL;
- }
- *(pass + l) = '\0';
-
- return pass;
-}
-
-#endif
-
#ifndef OPENSSL_NO_NEXTPROTONEG
/* This the context that we pass to next_proto_cb */
typedef struct tlsextnextprotoctx_st {
@@ -563,7 +429,7 @@ static int tlsa_import_rrset(SSL *con, STACK_OF(OPENSSL_STRING) *rrset)
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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,
@@ -581,35 +447,56 @@ typedef enum OPTION_choice {
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_CERT_CHAIN, OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN,
+ OPT_NEXTPROTONEG, OPT_ALPN,
+ OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH,
+ OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, OPT_VERIFYCAFILE,
+ OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE,
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,
+ OPT_S_ENUM, OPT_IGNORE_UNEXPECTED_EOF,
+ OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS,
+ 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_SCTP_LABEL_BUG,
- OPT_R_ENUM
+ OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS s_client_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [host:port]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#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
+ {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified section for SSL_CTX configuration"},
+#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
+
+ OPT_SECTION("Network"),
{"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 ")"},
+ "TCP/IP where to connect; default: " PORT ")"},
{"bind", OPT_BIND, 's', "bind local address for connection"},
{"proxy", OPT_PROXY, 's',
"Connect to via specified proxy to the real server"},
+ {"proxy_user", OPT_PROXY_USER, 's', "UserID for proxy authentication"},
+ {"proxy_pass", OPT_PROXY_PASS, 's', "Proxy authentication password source"},
#ifdef AF_UNIX
{"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"},
#endif
@@ -617,20 +504,38 @@ const OPTIONS s_client_options[] = {
#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"},
+ {"maxfraglen", OPT_MAXFRAGLEN, 'p',
+ "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"},
+ {"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"},
+ {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"},
+
+ OPT_SECTION("Identity"),
+ {"cert", OPT_CERT, '<', "Client certificate file to use"},
{"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"},
+ "Client certificate file format (PEM/DER/P12); has no effect"},
+ {"cert_chain", OPT_CERT_CHAIN, '<',
+ "Client certificate chain file (in PEM format)"},
+ {"build_chain", OPT_BUILD_CHAIN, '-', "Build client certificate chain"},
+ {"key", OPT_KEY, 's', "Private key file to use; default: -cert file"},
+ {"keyform", OPT_KEYFORM, 'E', "Key format (ENGINE, other values ignored)"},
+ {"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"},
+ {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
{"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store 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"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
{"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"},
@@ -638,16 +543,19 @@ const OPTIONS s_client_options[] = {
"DANE TLSA rrdata presentation form"},
{"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-',
"Disable name checks when matching DANE-EE(3) TLSA records"},
+ {"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"},
+ {"name", OPT_PROTOHOST, 's',
+ "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""},
+
+ OPT_SECTION("Session"),
{"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"},
+ {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"},
+ {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"},
+
+ OPT_SECTION("Input/Output"),
{"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)"},
@@ -656,47 +564,35 @@ const OPTIONS s_client_options[] = {
"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"},
+
+ OPT_SECTION("Debug"),
+ {"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"},
+ {"keymatexport", OPT_KEYMATEXPORT, 's',
+ "Export keying material using label"},
+ {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
+ "Export len bytes of keying material; default 20"},
{"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)"},
+#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
+ {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
{"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"},
{"servername", OPT_SERVERNAME, 's',
"Set TLS extension servername (SNI) in ClientHello (default)"},
@@ -704,6 +600,8 @@ const OPTIONS s_client_options[] = {
"Do not send the server name (SNI) extension in the ClientHello"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
+ {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
+ "Do not treat lack of close_notify from a peer as an error"},
#ifndef OPENSSL_NO_OCSP
{"status", OPT_STATUS, '-', "Request certificate status from server"},
#endif
@@ -712,17 +610,9 @@ const OPTIONS s_client_options[] = {
{"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,
+ {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
+
+ OPT_SECTION("Protocol and version"),
#ifndef OPENSSL_NO_SSL3
{"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
#endif
@@ -754,43 +644,54 @@ const OPTIONS s_client_options[] = {
{"sctp", OPT_SCTP, '-', "Use SCTP"},
{"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
#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}
+#ifndef OPENSSL_NO_SRTP
+ {"use_srtp", OPT_USE_SRTP, 's',
+ "Offer SRTP key management with a colon-separated profile list"},
+#endif
+#ifndef OPENSSL_NO_SRP
+ {"srpuser", OPT_SRPUSER, 's', "(deprecated) SRP authentication for 'user'"},
+ {"srppass", OPT_SRPPASS, 's', "(deprecated) Password for 'user'"},
+ {"srp_lateuser", OPT_SRP_LATEUSER, '-',
+ "(deprecated) SRP username into second ClientHello message"},
+ {"srp_moregroups", OPT_SRP_MOREGROUPS, '-',
+ "(deprecated) Tolerate other than the known g N values."},
+ {"srp_strength", OPT_SRP_STRENGTH, 'p',
+ "(deprecated) Minimal length in bits for N"},
+#endif
+
+ OPT_R_OPTIONS,
+ OPT_S_OPTIONS,
+ OPT_V_OPTIONS,
+ {"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); default PEM"},
+ {"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
+ "Close connection on verification error"},
+ {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"},
+ {"chainCAfile", OPT_CHAINCAFILE, '<',
+ "CA file for certificate chain (PEM format)"},
+ {"chainCApath", OPT_CHAINCAPATH, '/',
+ "Use dir as certificate store path to build CA certificate chain"},
+ {"chainCAstore", OPT_CHAINCASTORE, ':',
+ "CA store URI for certificate chain"},
+ {"verifyCAfile", OPT_VERIFYCAFILE, '<',
+ "CA file for certificate verification (PEM format)"},
+ {"verifyCApath", OPT_VERIFYCAPATH, '/',
+ "Use dir as certificate store path to verify CA certificate"},
+ {"verifyCAstore", OPT_VERIFYCASTORE, ':',
+ "CA store URI for certificate verification"},
+ OPT_X_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"host:port", 0, 0, "Where to connect; same as -connect option"},
+ {NULL}
};
typedef enum PROTOCOL_choice {
@@ -802,7 +703,6 @@ typedef enum PROTOCOL_choice {
PROTO_TELNET,
PROTO_XMPP,
PROTO_XMPP_SERVER,
- PROTO_CONNECT,
PROTO_IRC,
PROTO_MYSQL,
PROTO_POSTGRES,
@@ -896,29 +796,33 @@ int s_client_main(int argc, char **argv)
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;
+ const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL;
+ char *proxystr = NULL, *proxyuser = NULL;
+ char *proxypassarg = NULL, *proxypass = NULL;
+ char *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 *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL, *host = NULL;
+ char *thost = NULL, *tport = NULL;
+ char *port = NULL;
char *bindhost = NULL, *bindport = NULL;
- char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
+ char *passarg = NULL, *pass = NULL;
+ char *vfyCApath = NULL, *vfyCAfile = NULL, *vfyCAstore = NULL;
char *ReqCAfile = NULL;
char *sess_in = NULL, *crl_file = NULL, *p;
const char *protohost = NULL;
struct timeval timeout, *timeoutp;
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 noCApath = 0, noCAfile = 0, noCAstore = 0;
+ int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_UNDEF;
+ int key_format = FORMAT_UNDEF, 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 ret = 1, in_init = 1, i, nbio_test = 0, sock = -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 starttls_proto = PROTO_OFF, crl_format = FORMAT_UNDEF, 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;
@@ -983,6 +887,7 @@ int s_client_main(int argc, char **argv)
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
+ int ignore_unexpected_eof = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
@@ -994,16 +899,16 @@ int s_client_main(int argc, char **argv)
# endif
#endif
- prog = opt_progname(argv[0]);
c_quiet = 0;
c_debug = 0;
c_showcerts = 0;
c_nbio = 0;
+ port = OPENSSL_strdup(PORT);
vpm = X509_VERIFY_PARAM_new();
cctx = SSL_CONF_CTX_new();
- if (vpm == NULL || cctx == NULL) {
- BIO_printf(bio_err, "%s: out of memory\n", prog);
+ if (port == NULL || vpm == NULL || cctx == NULL) {
+ BIO_printf(bio_err, "%s: out of memory\n", opt_getprog());
goto end;
}
@@ -1080,7 +985,12 @@ int s_client_main(int argc, char **argv)
break;
case OPT_PROXY:
proxystr = opt_arg();
- starttls_proto = PROTO_CONNECT;
+ break;
+ case OPT_PROXY_USER:
+ proxyuser = opt_arg();
+ break;
+ case OPT_PROXY_PASS:
+ proxypassarg = opt_arg();
break;
#ifdef AF_UNIX
case OPT_UNIX:
@@ -1120,7 +1030,7 @@ int s_client_main(int argc, char **argv)
sess_in = opt_arg();
break;
case OPT_CERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &cert_format))
goto opthelp;
break;
case OPT_CRLFORM:
@@ -1156,6 +1066,9 @@ int s_client_main(int argc, char **argv)
if (!args_excert(o, &exc))
goto end;
break;
+ case OPT_IGNORE_UNEXPECTED_EOF:
+ ignore_unexpected_eof = 1;
+ break;
case OPT_PREXIT:
prexit = 1;
break;
@@ -1176,7 +1089,7 @@ int s_client_main(int argc, char **argv)
break;
case OPT_SSL_CLIENT_ENGINE:
#ifndef OPENSSL_NO_ENGINE
- ssl_client_engine = ENGINE_by_id(opt_arg());
+ ssl_client_engine = setup_engine(opt_arg(), 0);
if (ssl_client_engine == NULL) {
BIO_printf(bio_err, "Error getting client auth engine\n");
goto opthelp;
@@ -1187,6 +1100,10 @@ int s_client_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_IGN_EOF:
c_ign_eof = 1;
break;
@@ -1214,6 +1131,10 @@ int s_client_main(int argc, char **argv)
break;
case OPT_MSGFILE:
bio_c_msg = BIO_new_file(opt_arg(), "w");
+ if (bio_c_msg == NULL) {
+ BIO_printf(bio_err, "Error writing file %s\n", opt_arg());
+ goto end;
+ }
break;
case OPT_TRACE:
#ifndef OPENSSL_NO_SSL_TRACE
@@ -1370,7 +1291,7 @@ int s_client_main(int argc, char **argv)
fallback_scsv = 1;
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &key_format))
goto opthelp;
break;
case OPT_PASS:
@@ -1426,6 +1347,18 @@ int s_client_main(int argc, char **argv)
case OPT_VERIFYCAFILE:
vfyCAfile = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
+ case OPT_CHAINCASTORE:
+ chCAstore = opt_arg();
+ break;
+ case OPT_VERIFYCASTORE:
+ vfyCAstore = opt_arg();
+ break;
case OPT_DANE_TLSA_DOMAIN:
dane_tlsa_domain = opt_arg();
break;
@@ -1530,6 +1463,25 @@ int s_client_main(int argc, char **argv)
break;
}
}
+
+ /* Optional argument is connect string if -connect not used. */
+ argc = opt_num_rest();
+ if (argc == 1) {
+ /* Don't allow -connect and a separate argument. */
+ if (connectstr != NULL) {
+ BIO_printf(bio_err,
+ "%s: cannot 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;
+ }
+ if (!app_RAND_load())
+ goto end;
+
if (count4or6 >= 2) {
BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog);
goto opthelp;
@@ -1548,23 +1500,6 @@ int s_client_main(int argc, char **argv)
goto opthelp;
}
}
- 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) {
@@ -1572,46 +1507,57 @@ int s_client_main(int argc, char **argv)
goto opthelp;
}
#endif
- if (proxystr != NULL) {
+
+ if (connectstr != 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;
- }
- res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST);
+
+ 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: -proxy argument malformed or ambiguous\n", prog);
+ "%s: -connect argument or target parameter malformed or ambiguous\n",
+ prog);
goto end;
}
+ }
+
+ if (proxystr != NULL) {
+ int res;
+ char *tmp_host = host, *tmp_port = port;
+
+ if (host == NULL || port == NULL) {
+ BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog);
+ goto opthelp;
+ }
+
if (servername == NULL && !noservername) {
- res = BIO_parse_hostserv(connectstr, &sname_alloc, NULL, BIO_PARSE_PRIO_HOST);
- if (!res) {
- BIO_printf(bio_err,
- "%s: -connect argument malformed or ambiguous\n", prog);
+ servername = sname_alloc = OPENSSL_strdup(host);
+ if (sname_alloc == NULL) {
+ BIO_printf(bio_err, "%s: out of memory\n", prog);
goto end;
}
- servername = sname_alloc;
}
- } 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);
+
+ /* Retain the original target host:port for use in the HTTP proxy connect string */
+ thost = OPENSSL_strdup(host);
+ tport = OPENSSL_strdup(port);
+ if (thost == NULL || tport == NULL) {
+ BIO_printf(bio_err, "%s: out of memory\n", prog);
+ goto end;
+ }
+
+ 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: -connect argument or target parameter malformed or ambiguous\n",
- prog);
+ "%s: -proxy argument malformed or ambiguous\n", prog);
goto end;
}
}
@@ -1661,7 +1607,17 @@ int s_client_main(int argc, char **argv)
#endif
if (!app_passwd(passarg, NULL, &pass, NULL)) {
- BIO_printf(bio_err, "Error getting password\n");
+ BIO_printf(bio_err, "Error getting private key password\n");
+ goto end;
+ }
+
+ if (!app_passwd(proxypassarg, NULL, &proxypass, NULL)) {
+ BIO_printf(bio_err, "Error getting proxy password\n");
+ goto end;
+ }
+
+ if (proxypass != NULL && proxyuser == NULL) {
+ BIO_printf(bio_err, "Error: Must specify proxy_user with proxy_pass\n");
goto end;
}
@@ -1670,35 +1626,28 @@ int s_client_main(int argc, char **argv)
if (key_file != NULL) {
key = load_key(key_file, key_format, 0, pass, e,
- "client certificate private key file");
- if (key == NULL) {
- ERR_print_errors(bio_err);
+ "client certificate private key");
+ if (key == NULL)
goto end;
- }
}
if (cert_file != NULL) {
- cert = load_cert(cert_file, cert_format, "client certificate file");
- if (cert == NULL) {
- ERR_print_errors(bio_err);
+ cert = load_cert_pass(cert_file, cert_format, 1, pass,
+ "client certificate");
+ if (cert == NULL)
goto end;
- }
}
if (chain_file != NULL) {
- if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL,
- "client certificate chain"))
+ if (!load_certs(chain_file, 0, &chain, pass, "client certificate chain"))
goto end;
}
if (crl_file != NULL) {
X509_CRL *crl;
- crl = load_crl(crl_file, crl_format);
- if (crl == NULL) {
- BIO_puts(bio_err, "Error loading CRL\n");
- ERR_print_errors(bio_err);
+ crl = load_crl(crl_file, crl_format, 0, "CRL");
+ if (crl == NULL)
goto end;
- }
crls = sk_X509_CRL_new_null();
if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
BIO_puts(bio_err, "Error adding CRL\n");
@@ -1714,10 +1663,21 @@ int s_client_main(int argc, char **argv)
if (bio_c_out == NULL) {
if (c_quiet && !c_debug) {
bio_c_out = BIO_new(BIO_s_null());
- if (c_msg && bio_c_msg == NULL)
+ if (c_msg && bio_c_msg == NULL) {
bio_c_msg = dup_bio_out(FORMAT_TEXT);
- } else if (bio_c_out == NULL)
+ if (bio_c_msg == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ goto end;
+ }
+ }
+ } else {
bio_c_out = dup_bio_out(FORMAT_TEXT);
+ }
+
+ if (bio_c_out == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
}
#ifndef OPENSSL_NO_SRP
if (!app_passwd(srppass, NULL, &srp_arg.srppassin, NULL)) {
@@ -1726,7 +1686,7 @@ int s_client_main(int argc, char **argv)
}
#endif
- ctx = SSL_CTX_new(meth);
+ ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -1761,6 +1721,9 @@ int s_client_main(int argc, char **argv)
&& SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
goto end;
+ if (ignore_unexpected_eof)
+ SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
+
if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
BIO_printf(bio_err, "Error setting verify params\n");
ERR_print_errors(bio_err);
@@ -1804,7 +1767,9 @@ int s_client_main(int argc, char **argv)
goto end;
}
- if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+ if (!ssl_load_stores(ctx,
+ vfyCApath, vfyCAfile, vfyCAstore,
+ chCApath, chCAfile, chCAstore,
crls, crl_download)) {
BIO_printf(bio_err, "Error loading store locations\n");
ERR_print_errors(bio_err);
@@ -1826,10 +1791,10 @@ int s_client_main(int argc, char **argv)
if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) {
BIO_puts(bio_err, "Error setting client auth engine\n");
ERR_print_errors(bio_err);
- ENGINE_free(ssl_client_engine);
+ release_engine(ssl_client_engine);
goto end;
}
- ENGINE_free(ssl_client_engine);
+ release_engine(ssl_client_engine);
}
#endif
@@ -1933,7 +1898,8 @@ int s_client_main(int argc, char **argv)
SSL_CTX_set_verify(ctx, verify, verify_callback);
- if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -1948,21 +1914,10 @@ int s_client_main(int argc, char **argv)
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
}
-# ifndef OPENSSL_NO_SRP
- if (srp_arg.srplogin) {
- if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) {
- BIO_printf(bio_err, "Unable to set SRP username\n");
- goto end;
- }
- srp_arg.msg = c_msg;
- srp_arg.debug = c_debug;
- SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
- SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
- SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
- if (c_msg || c_debug || srp_arg.amp == 0)
- SSL_CTX_set_srp_verify_param_callback(ctx,
- ssl_srp_verify_param_cb);
- }
+#ifndef OPENSSL_NO_SRP
+ if (srp_arg.srplogin != NULL
+ && !set_up_srp_arg(ctx, &srp_arg, srp_lateuser, c_msg, c_debug))
+ goto end;
# endif
if (dane_tlsa_domain != NULL) {
@@ -2023,7 +1978,7 @@ int s_client_main(int argc, char **argv)
if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) {
if (servername == NULL) {
- if(host == NULL || is_dNS_name(host))
+ if(host == NULL || is_dNS_name(host))
servername = (host == NULL) ? "localhost" : host;
}
if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) {
@@ -2059,16 +2014,16 @@ int s_client_main(int argc, char **argv)
}
re_start:
- if (init_client(&s, host, port, bindhost, bindport, socket_family,
+ if (init_client(&sock, host, port, bindhost, bindport, socket_family,
socket_type, protocol) == 0) {
BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
- BIO_closesocket(s);
+ BIO_closesocket(sock);
goto end;
}
- BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);
+ BIO_printf(bio_c_out, "CONNECTED(%08X)\n", sock);
if (c_nbio) {
- if (!BIO_socket_nbio(s, 1)) {
+ if (!BIO_socket_nbio(sock, 1)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -2080,21 +2035,23 @@ int s_client_main(int argc, char **argv)
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP)
- sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
+ sbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
else
#endif
- sbio = BIO_new_dgram(s, BIO_NOCLOSE);
+ sbio = BIO_new_dgram(sock, BIO_NOCLOSE);
- if ((peer_info.addr = BIO_ADDR_new()) == NULL) {
+ if (sbio == NULL || (peer_info.addr = BIO_ADDR_new()) == NULL) {
BIO_printf(bio_err, "memory allocation failure\n");
- BIO_closesocket(s);
+ BIO_free(sbio);
+ BIO_closesocket(sock);
goto end;
}
- if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
+ if (!BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
BIO_printf(bio_err, "getsockname:errno=%d\n",
get_last_socket_error());
+ BIO_free(sbio);
BIO_ADDR_free(peer_info.addr);
- BIO_closesocket(s);
+ BIO_closesocket(sock);
goto end;
}
@@ -2131,17 +2088,29 @@ int s_client_main(int argc, char **argv)
}
} else
#endif /* OPENSSL_NO_DTLS */
- sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ sbio = BIO_new_socket(sock, BIO_NOCLOSE);
+
+ if (sbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ ERR_print_errors(bio_err);
+ BIO_closesocket(sock);
+ goto end;
+ }
if (nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
+ if (test == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ BIO_free(sbio);
+ goto shut;
+ }
sbio = BIO_push(test, sbio);
}
if (c_debug) {
- BIO_set_callback(sbio, bio_dump_callback);
+ BIO_set_callback_ex(sbio, bio_dump_callback);
BIO_set_callback_arg(sbio, (char *)bio_c_out);
}
if (c_msg) {
@@ -2186,6 +2155,13 @@ int s_client_main(int argc, char **argv)
sbuf_len = 0;
sbuf_off = 0;
+ if (proxystr != NULL) {
+ /* Here we must use the connect string target host & port */
+ if (!OSSL_HTTP_proxy_connect(sbio, thost, tport, proxyuser, proxypass,
+ 0 /* no timeout */, bio_err, prog))
+ goto shut;
+ }
+
switch ((PROTOCOL_CHOICE) starttls_proto) {
case PROTO_OFF:
break;
@@ -2203,6 +2179,10 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto shut;
+ }
BIO_push(fbio, sbio);
/* Wait for multi-line response to end from LMTP or SMTP */
do {
@@ -2251,6 +2231,10 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto shut;
+ }
BIO_push(fbio, sbio);
BIO_gets(fbio, mbuf, BUFSIZZ);
/* STARTTLS command requires CAPABILITY... */
@@ -2278,6 +2262,10 @@ int s_client_main(int argc, char **argv)
{
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto shut;
+ }
BIO_push(fbio, sbio);
/* wait for multi-line response to end from FTP */
do {
@@ -2361,64 +2349,15 @@ int s_client_main(int argc, char **argv)
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 formatted 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;
- }
- }
- break;
case PROTO_IRC:
{
int numeric;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
BIO_push(fbio, sbio);
BIO_printf(fbio, "STARTTLS\r\n");
(void)BIO_flush(fbio);
@@ -2579,17 +2518,25 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
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] != '.');
+ BIO_gets(fbio, mbuf, BUFSIZZ);
+ /* no point in trying to parse the CAPABILITIES response if there is none */
+ if (strstr(mbuf, "101") != NULL) {
+ /* 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);
@@ -2615,6 +2562,10 @@ int s_client_main(int argc, char **argv)
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
+ if (fbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ goto end;
+ }
BIO_push(fbio, sbio);
/* wait for multi-line response to end from Sieve */
do {
@@ -2674,8 +2625,9 @@ int s_client_main(int argc, char **argv)
BIO *ldapbio = BIO_new(BIO_s_mem());
CONF *cnf = NCONF_new(NULL);
- if (cnf == NULL) {
+ if (ldapbio == NULL || cnf == NULL) {
BIO_free(ldapbio);
+ NCONF_free(cnf);
goto end;
}
BIO_puts(ldapbio, ldap_tls_genconf);
@@ -2784,7 +2736,6 @@ int s_client_main(int argc, char **argv)
tty_on = 1;
if (in_init) {
in_init = 0;
-
if (c_brief) {
BIO_puts(bio_err, "CONNECTION ESTABLISHED\n");
print_ssl_summary(con);
@@ -3080,22 +3031,14 @@ int s_client_main(int argc, char **argv)
BIO_printf(bio_err, "RENEGOTIATING\n");
SSL_renegotiate(con);
cbuf_len = 0;
- } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' )
+ } else 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' && cmdletters)) {
- BIO_printf(bio_err, "HEARTBEATING\n");
- SSL_heartbeat(con);
- cbuf_len = 0;
- }
-#endif
- else {
+ } else {
cbuf_len = i;
cbuf_off = 0;
#ifdef CHARSET_EBCDIC
@@ -3108,7 +3051,6 @@ int s_client_main(int argc, char **argv)
}
}
- ret = 0;
shut:
if (in_init)
print_stuff(bio_c_out, con, full_log);
@@ -3134,8 +3076,8 @@ int s_client_main(int argc, char **argv)
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
+ openssl_fdset(sock, &readfds);
+ } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
&& BIO_read(sbio, sbuf, BUFSIZZ) > 0);
BIO_closesocket(SSL_get_fd(con));
@@ -3166,6 +3108,8 @@ int s_client_main(int argc, char **argv)
OPENSSL_free(bindport);
OPENSSL_free(host);
OPENSSL_free(port);
+ OPENSSL_free(thost);
+ OPENSSL_free(tport);
X509_VERIFY_PARAM_free(vpm);
ssl_excert_free(exc);
sk_OPENSSL_STRING_free(ssl_args);
@@ -3174,6 +3118,7 @@ int s_client_main(int argc, char **argv)
OPENSSL_clear_free(cbuf, BUFSIZZ);
OPENSSL_clear_free(sbuf, BUFSIZZ);
OPENSSL_clear_free(mbuf, BUFSIZZ);
+ clear_free(proxypass);
release_engine(e);
BIO_free(bio_c_out);
bio_c_out = NULL;
@@ -3187,6 +3132,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
X509 *peer = NULL;
STACK_OF(X509) *sk;
const SSL_CIPHER *c;
+ EVP_PKEY *public_key;
int i, istls13 = (SSL_version(s) == TLS1_3_VERSION);
long verify_result;
#ifndef OPENSSL_NO_COMP
@@ -3212,13 +3158,26 @@ static void print_stuff(BIO *bio, SSL *s, int full)
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");
+ public_key = X509_get_pubkey(sk_X509_value(sk, i));
+ if (public_key != NULL) {
+ BIO_printf(bio, " a:PKEY: %s, %d (bit); sigalg: %s\n",
+ OBJ_nid2sn(EVP_PKEY_get_base_id(public_key)),
+ EVP_PKEY_get_bits(public_key),
+ OBJ_nid2sn(X509_get_signature_nid(sk_X509_value(sk, i))));
+ EVP_PKEY_free(public_key);
+ }
+ BIO_printf(bio, " v:NotBefore: ");
+ ASN1_TIME_print(bio, X509_get0_notBefore(sk_X509_value(sk, i)));
+ BIO_printf(bio, "; NotAfter: ");
+ ASN1_TIME_print(bio, X509_get0_notAfter(sk_X509_value(sk, i)));
+ BIO_puts(bio, "\n");
if (c_showcerts)
PEM_write_bio_X509(bio, sk_X509_value(sk, i));
}
}
BIO_printf(bio, "---\n");
- peer = SSL_get_peer_certificate(s);
+ peer = SSL_get0_peer_certificate(s);
if (peer != NULL) {
BIO_printf(bio, "Server certificate\n");
@@ -3283,7 +3242,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
pktmp = X509_get0_pubkey(peer);
BIO_printf(bio, "Server public key is %d bit\n",
- EVP_PKEY_bits(pktmp));
+ EVP_PKEY_get_bits(pktmp));
}
BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(s) ? "" : " NOT");
@@ -3295,9 +3254,14 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_printf(bio, "Expansion: %s\n",
expansion ? SSL_COMP_get_name(expansion) : "NONE");
#endif
+#ifndef OPENSSL_NO_KTLS
+ if (BIO_get_ktls_send(SSL_get_wbio(s)))
+ BIO_printf(bio_err, "Using Kernel TLS for sending\n");
+ if (BIO_get_ktls_recv(SSL_get_rbio(s)))
+ BIO_printf(bio_err, "Using Kernel TLS for receiving\n");
+#endif
-#ifdef SSL_DEBUG
- {
+ if (OSSL_TRACE_ENABLED(TLS)) {
/* Print out local port of connection: useful for debugging */
int sock;
union BIO_sock_info_u info;
@@ -3310,7 +3274,6 @@ static void print_stuff(BIO *bio, SSL *s, int full)
}
BIO_ADDR_free(info.addr);
}
-#endif
#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (next_proto.status != -1) {
@@ -3379,11 +3342,11 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_printf(bio, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = app_malloc(keymatexportlen, "export key");
- if (!SSL_export_keying_material(s, exportedkeymat,
+ if (SSL_export_keying_material(s, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
- NULL, 0, 0)) {
+ NULL, 0, 0) <= 0) {
BIO_printf(bio, " Error\n");
} else {
BIO_printf(bio, " Keying material: ");
@@ -3394,7 +3357,6 @@ static void print_stuff(BIO *bio, SSL *s, int full)
OPENSSL_free(exportedkeymat);
}
BIO_printf(bio, "---\n");
- X509_free(peer);
/* flush, or debugging output gets mixed with http response */
(void)BIO_flush(bio);
}
@@ -3510,7 +3472,7 @@ static int ldap_ExtendedResponse_parse(const char *buf, long rem)
}
/*
- * Host dNS Name verifier: used for checking that the hostname is in dNS format
+ * Host dNS Name verifier: used for checking that the hostname is in dNS format
* before setting it as SNI
*/
static int is_dNS_name(const char *host)
diff --git a/apps/s_server.c b/apps/s_server.c
index 1a42bf89c7a0..2b0b6ba381fb 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -3,7 +3,7 @@
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -21,6 +21,7 @@
#include <openssl/e_os2.h>
#include <openssl/async.h>
#include <openssl/ssl.h>
+#include <openssl/decoder.h>
#ifndef OPENSSL_NO_SOCK
@@ -47,12 +48,7 @@ typedef unsigned int u_int;
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
-#ifndef OPENSSL_NO_SRP
-# include <openssl/srp.h>
-#endif
+#include <openssl/rsa.h>
#include "s_apps.h"
#include "timeouts.h"
#ifdef CHARSET_EBCDIC
@@ -71,9 +67,6 @@ 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);
-#endif
static void print_connection_info(SSL *con);
static const int bufsize = 16 * 1024;
@@ -103,6 +96,8 @@ static int keymatexportlen = 20;
static int async = 0;
+static int use_sendfile = 0;
+
static const char *session_id_prefix = NULL;
#ifndef OPENSSL_NO_DTLS
@@ -123,6 +118,8 @@ static SSL_SESSION *psksess = NULL;
static char *psk_identity = "Client_identity";
char *psk_key = NULL; /* by default PSK is not used */
+static char http_server_binmode = 0; /* for now: 0/1 = default/binary */
+
#ifndef OPENSSL_NO_PSK
static unsigned int psk_server_cb(SSL *ssl, const char *identity,
unsigned char *psk,
@@ -241,56 +238,7 @@ static int psk_find_session_cb(SSL *ssl, const unsigned char *identity,
}
#ifndef OPENSSL_NO_SRP
-/* This is a context that we pass to callbacks */
-typedef struct srpsrvparm_st {
- char *login;
- SRP_VBASE *vb;
- SRP_user_pwd *user;
-} srpsrvparm;
static srpsrvparm srp_callback_parm;
-
-/*
- * This callback pretends to require some asynchronous logic in order to
- * obtain a verifier. When the callback is called for a new connection we
- * return with a negative value. This will provoke the accept etc to return
- * with an LOOKUP_X509. The main logic of the reinvokes the suspended call
- * (which would normally occur after a worker has finished) and we set the
- * user parameters.
- */
-static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
-{
- srpsrvparm *p = (srpsrvparm *) arg;
- int ret = SSL3_AL_FATAL;
-
- 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;
- }
-
- if (p->user == NULL) {
- BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
- goto err;
- }
-
- if (SSL_set_srp_server_param
- (s, p->user->N, p->user->g, p->user->s, p->user->v,
- p->user->info) < 0) {
- *ad = SSL_AD_INTERNAL_ERROR;
- goto err;
- }
- BIO_printf(bio_err,
- "SRP parameters set: username = \"%s\" info=\"%s\" \n",
- p->login, p->user->info);
- ret = SSL_ERROR_NONE;
-
- err:
- SRP_user_pwd_free(p->user);
- p->user = NULL;
- p->login = NULL;
- return ret;
-}
-
#endif
static int local_argc = 0;
@@ -476,7 +424,7 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
BIO_printf(p->biodebug, "Hostname in TLS extension: \"");
while ((uc = *cp++) != 0)
BIO_printf(p->biodebug,
- isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc);
+ (((uc) & ~127) == 0) && isprint(uc) ? "%c" : "\\x%02x", uc);
BIO_printf(p->biodebug, "\"\n");
}
@@ -484,7 +432,7 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
return SSL_TLSEXT_ERR_NOACK;
if (servername != NULL) {
- if (strcasecmp(servername, p->servername))
+ if (OPENSSL_strcasecmp(servername, p->servername))
return p->extension_error;
if (ctx2 != NULL) {
BIO_printf(p->biodebug, "Switching server context.\n");
@@ -501,6 +449,7 @@ typedef struct tlsextstatusctx_st {
char *respin;
/* Default responder to use */
char *host, *path, *port;
+ char *proxy, *no_proxy;
int use_ssl;
int verbose;
} tlsextstatusctx;
@@ -520,6 +469,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
OCSP_RESPONSE **resp)
{
char *host = NULL, *port = NULL, *path = NULL;
+ char *proxy = NULL, *no_proxy = NULL;
int use_ssl;
STACK_OF(OPENSSL_STRING) *aia = NULL;
X509 *x = NULL;
@@ -535,8 +485,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
x = SSL_get_certificate(s);
aia = X509_get1_ocsp(x);
if (aia != NULL) {
- if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
- &host, &port, &path, &use_ssl)) {
+ if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &use_ssl,
+ NULL, &host, &port, NULL, &path, NULL, NULL)) {
BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
goto err;
}
@@ -554,6 +504,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
port = srctx->port;
use_ssl = srctx->use_ssl;
}
+ proxy = srctx->proxy;
+ no_proxy = srctx->no_proxy;
inctx = X509_STORE_CTX_new();
if (inctx == NULL)
@@ -585,8 +537,8 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
if (!OCSP_REQUEST_add_ext(req, ext, -1))
goto err;
}
- *resp = process_responder(req, host, path, port, use_ssl, NULL,
- srctx->timeout);
+ *resp = process_responder(req, host, port, path, proxy, no_proxy,
+ use_ssl, NULL /* headers */, srctx->timeout);
if (*resp == NULL) {
BIO_puts(bio_err, "cert_status: error querying responder\n");
goto done;
@@ -716,7 +668,7 @@ static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
if (SSL_select_next_proto
((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in,
inlen) != OPENSSL_NPN_NEGOTIATED) {
- return SSL_TLSEXT_ERR_NOACK;
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
}
if (!s_quiet) {
@@ -735,7 +687,8 @@ static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE,
+ OPT_COMMON,
+ 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,
@@ -744,9 +697,12 @@ typedef enum OPTION_choice {
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_VERIFYCAFILE,
+ OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE,
+ 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_STATUS_TIMEOUT, OPT_PROXY, OPT_NO_PROXY, 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,
@@ -756,132 +712,154 @@ typedef enum OPTION_choice {
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_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_SENDFILE,
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_SCTP_LABEL_BUG,
+ OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF,
OPT_R_ENUM,
OPT_S_ENUM,
OPT_V_ENUM,
- OPT_X_ENUM
+ OPT_X_ENUM,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS s_server_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"ssl_config", OPT_SSL_CONFIG, 's',
+ "Configure SSL_CTX using the given configuration value"},
+#ifndef OPENSSL_NO_SSL_TRACE
+ {"trace", OPT_TRACE, '-', "trace protocol messages"},
+#endif
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Network"),
{"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"},
+ {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"},
#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
+
+ OPT_SECTION("Identity"),
{"context", OPT_CONTEXT, 's', "Set session ID context"},
+ {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store 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"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store URI"},
+ {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
{"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"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
+ {"cert", OPT_CERT, '<', "Server certificate file to use; default " TEST_CERT},
+ {"cert2", OPT_CERT2, '<',
+ "Certificate file to use for servername; default " TEST_CERT2},
+ {"certform", OPT_CERTFORM, 'F',
+ "Server certificate file format (PEM/DER/P12); has no effect"},
+ {"cert_chain", OPT_CERT_CHAIN, '<',
+ "Server certificate chain file in PEM format"},
+ {"build_chain", OPT_BUILD_CHAIN, '-', "Build server certificate chain"},
{"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"},
+ "Private key file to use; default is -cert file or else" TEST_CERT},
+ {"key2", OPT_KEY2, '<',
+ "-Private Key file to use for servername if not in -cert2"},
+ {"keyform", OPT_KEYFORM, 'f', "Key format (ENGINE, other values ignored)"},
+ {"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"},
{"dcert", OPT_DCERT, '<',
- "Second certificate file to use (usually for DSA)"},
- {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
+ "Second server certificate file to use (usually for DSA)"},
{"dcertform", OPT_DCERTFORM, 'F',
- "Second certificate format (PEM or DER) PEM default"},
+ "Second server certificate file format (PEM/DER/P12); has no effect"},
+ {"dcert_chain", OPT_DCERT_CHAIN, '<',
+ "second server certificate chain file in PEM format"},
{"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"},
+ "Second key file format (ENGINE, other values ignored)"},
+ {"dpass", OPT_DPASS, 's',
+ "Second private key and cert file pass phrase source"},
+ {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
+ {"servername", OPT_SERVERNAME, 's',
+ "Servername for HostName TLS extension"},
+ {"servername_fatal", OPT_SERVERNAME_FATAL, '-',
+ "On servername mismatch send fatal alert (default warning alert)"},
{"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"},
+ {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
+ "Do not treat lack of close_notify from a peer as an error"},
{"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)"},
+ "Export len bytes of keying material; default 20"},
{"CRL", OPT_CRL, '<', "CRL file to use"},
+ {"CRLform", OPT_CRLFORM, 'F', "CRL file format (PEM or DER); default PEM"},
{"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"},
+ "Download CRLs from distribution points in certificate CDP entries"},
+ {"chainCAfile", OPT_CHAINCAFILE, '<',
+ "CA file for certificate chain (PEM format)"},
{"chainCApath", OPT_CHAINCAPATH, '/',
"use dir as certificate store path to build CA certificate chain"},
+ {"chainCAstore", OPT_CHAINCASTORE, ':',
+ "use URI as certificate store to build CA certificate chain"},
+ {"verifyCAfile", OPT_VERIFYCAFILE, '<',
+ "CA file for certificate verification (PEM format)"},
{"verifyCApath", OPT_VERIFYCAPATH, '/',
"use dir as certificate store path to verify CA certificate"},
+ {"verifyCAstore", OPT_VERIFYCASTORE, ':',
+ "use URI as certificate store 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"},
+ "Disable internal cache, set up and use external cache"},
{"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"},
+ {"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
+ OPT_SECTION("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"},
+ {"proxy", OPT_PROXY, 's',
+ "[http[s]://]host[:port][/path] of HTTP(S) proxy to use; path is ignored"},
+ {"no_proxy", OPT_NO_PROXY, 's',
+ "List of addresses of servers not to use HTTP(S) proxy for"},
+ {OPT_MORE_STR, 0, 0,
+ "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
{"status_file", OPT_STATUS_FILE, '<',
"File containing DER encoded OCSP Response"},
#endif
-#ifndef OPENSSL_NO_SSL_TRACE
- {"trace", OPT_TRACE, '-', "trace protocol messages"},
-#endif
+
+ OPT_SECTION("Debug"),
{"security_debug", OPT_SECURITY_DEBUG, '-',
"Print output from SSL/TLS security framework"},
{"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
@@ -889,21 +867,29 @@ const OPTIONS s_server_options[] = {
{"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"},
+ "act as an echo server that sends back received text reversed"},
+ {"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"},
{"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"},
+ {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"},
+ {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
+
+ OPT_SECTION("Network"),
+ {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
+ {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
+ {"mtu", OPT_MTU, 'p', "Set link-layer MTU"},
{"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"},
+ {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
+ "Size used to split data for encrypt pipelines"},
+ {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
+
+ OPT_SECTION("Server identity"),
{"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"},
@@ -911,10 +897,25 @@ const OPTIONS s_server_options[] = {
{"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
- {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"},
+ {"srpvfile", OPT_SRPVFILE, '<', "(deprecated) The verifier file for SRP"},
{"srpuserseed", OPT_SRPUSERSEED, 's',
- "A seed string for a default user salt"},
+ "(deprecated) A seed string for a default user salt"},
#endif
+
+ OPT_SECTION("Protocol and version"),
+ {"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"},
+ {"http_server_binmode", OPT_HTTP_SERVER_BINMODE, '-', "opening files in binary mode when acting as http server (-WWW and -HTTP)"},
+ {"no_ca_names", OPT_NOCANAMES, '-',
+ "Disable TLS Extension CA Names"},
+ {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"},
#ifndef OPENSSL_NO_SSL3
{"ssl3", OPT_SSL3, '-', "Just talk SSLv3"},
#endif
@@ -932,12 +933,9 @@ const OPTIONS s_server_options[] = {
#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
@@ -948,33 +946,27 @@ const OPTIONS s_server_options[] = {
{"sctp", OPT_SCTP, '-', "Use SCTP"},
{"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
#endif
-#ifndef OPENSSL_NO_DH
- {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
+#ifndef OPENSSL_NO_SRTP
+ {"use_srtp", OPT_SRTP_PROFILES, 's',
+ "Offer SRTP key management with a colon-separated profile list"},
#endif
+ {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
#ifndef OPENSSL_NO_NEXTPROTONEG
{"nextprotoneg", OPT_NEXTPROTONEG, 's',
"Set the advertised protocols for the NPN extension (comma-separated list)"},
#endif
-#ifndef OPENSSL_NO_SRTP
- {"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"},
+#ifndef OPENSSL_NO_KTLS
+ {"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"},
#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}
+
+ OPT_R_OPTIONS,
+ OPT_S_OPTIONS,
+ OPT_V_OPTIONS,
+ OPT_X_OPTIONS,
+ OPT_PROV_OPTIONS,
+ {NULL}
};
#define IS_PROT_FLAG(o) \
@@ -993,28 +985,28 @@ int s_server_main(int argc, char *argv[])
STACK_OF(X509_CRL) *crls = NULL;
X509 *s_cert = NULL, *s_dcert = NULL;
X509_VERIFY_PARAM *vpm = NULL;
- const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL;
+ const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ const char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL;
char *dpassarg = NULL, *dpass = NULL;
- char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
+ char *passarg = NULL, *pass = NULL;
+ char *vfyCApath = NULL, *vfyCAfile = NULL, *vfyCAstore = 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 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;
- int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
+ int s_cert_format = FORMAT_UNDEF, s_key_format = FORMAT_UNDEF;
+ int s_dcert_format = FORMAT_UNDEF, s_dkey_format = FORMAT_UNDEF;
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;
+ int state = 0, crl_format = FORMAT_UNDEF, crl_download = 0;
char *host = NULL;
- char *port = BUF_strdup(PORT);
+ char *port = NULL;
unsigned char *context = NULL;
OPTION_CHOICE o;
EVP_PKEY *s_key2 = NULL;
@@ -1056,9 +1048,11 @@ int s_server_main(int argc, char *argv[])
const char *keylog_file = NULL;
int max_early_data = -1, recv_max_early_data = -1;
char *psksessf = NULL;
+ int no_ca_names = 0;
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
+ int ignore_unexpected_eof = 0;
/* Init of few remaining global variables */
local_argc = argc;
@@ -1073,10 +1067,12 @@ int s_server_main(int argc, char *argv[])
s_quiet = 0;
s_brief = 0;
async = 0;
+ use_sendfile = 0;
+ port = OPENSSL_strdup(PORT);
cctx = SSL_CONF_CTX_new();
vpm = X509_VERIFY_PARAM_new();
- if (cctx == NULL || vpm == NULL)
+ if (port == NULL || cctx == NULL || vpm == NULL)
goto end;
SSL_CONF_CTX_set_flags(cctx,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE);
@@ -1163,7 +1159,9 @@ int s_server_main(int argc, char *argv[])
#ifdef AF_UNIX
case OPT_UNIX:
socket_family = AF_UNIX;
- OPENSSL_free(host); host = BUF_strdup(opt_arg());
+ OPENSSL_free(host); host = OPENSSL_strdup(opt_arg());
+ if (host == NULL)
+ goto end;
OPENSSL_free(port); port = NULL;
break;
case OPT_UNLINK:
@@ -1209,7 +1207,7 @@ int s_server_main(int argc, char *argv[])
s_serverinfo_file = opt_arg();
break;
case OPT_CERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_cert_format))
goto opthelp;
break;
case OPT_KEY:
@@ -1226,19 +1224,17 @@ int s_server_main(int argc, char *argv[])
s_chain_file = opt_arg();
break;
case OPT_DHPARAM:
-#ifndef OPENSSL_NO_DH
dhfile = opt_arg();
-#endif
break;
case OPT_DCERTFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &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))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dkey_format))
goto opthelp;
break;
case OPT_DPASS:
@@ -1265,6 +1261,18 @@ int s_server_main(int argc, char *argv[])
case OPT_VERIFYCAPATH:
vfyCApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
+ case OPT_CHAINCASTORE:
+ chCAstore = opt_arg();
+ break;
+ case OPT_VERIFYCASTORE:
+ vfyCAstore = opt_arg();
+ break;
case OPT_NO_CACHE:
no_cache = 1;
break;
@@ -1352,14 +1360,23 @@ int s_server_main(int argc, char *argv[])
tlscstatp.timeout = atoi(opt_arg());
#endif
break;
+ case OPT_PROXY:
+#ifndef OPENSSL_NO_OCSP
+ tlscstatp.proxy = opt_arg();
+#endif
+ break;
+ case OPT_NO_PROXY:
+#ifndef OPENSSL_NO_OCSP
+ tlscstatp.no_proxy = opt_arg();
+#endif
+ break;
case OPT_STATUS_URL:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
- if (!OCSP_parse_url(opt_arg(),
- &tlscstatp.host,
- &tlscstatp.port,
- &tlscstatp.path, &tlscstatp.use_ssl)) {
- BIO_printf(bio_err, "Error parsing URL\n");
+ if (!OSSL_HTTP_parse_url(opt_arg(), &tlscstatp.use_ssl, NULL,
+ &tlscstatp.host, &tlscstatp.port, NULL,
+ &tlscstatp.path, NULL, NULL)) {
+ BIO_printf(bio_err, "Error parsing -status_url argument\n");
goto end;
}
#endif
@@ -1375,6 +1392,10 @@ int s_server_main(int argc, char *argv[])
break;
case OPT_MSGFILE:
bio_s_msg = BIO_new_file(opt_arg(), "w");
+ if (bio_s_msg == NULL) {
+ BIO_printf(bio_err, "Error writing file %s\n", opt_arg());
+ goto end;
+ }
break;
case OPT_TRACE:
#ifndef OPENSSL_NO_SSL_TRACE
@@ -1400,9 +1421,7 @@ int s_server_main(int argc, char *argv[])
s_quiet = s_brief = verify_args.quiet = 1;
break;
case OPT_NO_DHE:
-#ifndef OPENSSL_NO_DH
no_dhe = 1;
-#endif
break;
case OPT_NO_RESUME_EPHEMERAL:
no_resume_ephemeral = 1;
@@ -1529,12 +1548,18 @@ int s_server_main(int argc, char *argv[])
session_id_prefix = opt_arg();
break;
case OPT_ENGINE:
- engine = setup_engine(opt_arg(), 1);
+#ifndef OPENSSL_NO_ENGINE
+ engine = setup_engine(opt_arg(), s_debug);
+#endif
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_SERVERNAME:
tlsextcbp.servername = opt_arg();
break;
@@ -1603,10 +1628,30 @@ int s_server_main(int argc, char *argv[])
if (max_early_data == -1)
max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
break;
+ case OPT_HTTP_SERVER_BINMODE:
+ http_server_binmode = 1;
+ break;
+ case OPT_NOCANAMES:
+ no_ca_names = 1;
+ break;
+ case OPT_SENDFILE:
+#ifndef OPENSSL_NO_KTLS
+ use_sendfile = 1;
+#endif
+ break;
+ case OPT_IGNORE_UNEXPECTED_EOF:
+ ignore_unexpected_eof = 1;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
- argv = opt_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (!app_RAND_load())
+ goto end;
#ifndef OPENSSL_NO_NEXTPROTONEG
if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) {
@@ -1655,6 +1700,13 @@ int s_server_main(int argc, char *argv[])
}
#endif
+#ifndef OPENSSL_NO_KTLS
+ if (use_sendfile && www <= 1) {
+ BIO_printf(bio_err, "Can't use -sendfile without -WWW or -HTTP\n");
+ goto end;
+ }
+#endif
+
if (!app_passwd(passarg, dpassarg, &pass, &dpass)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
@@ -1671,40 +1723,32 @@ int s_server_main(int argc, char *argv[])
if (nocert == 0) {
s_key = load_key(s_key_file, s_key_format, 0, pass, engine,
- "server certificate private key file");
- if (s_key == NULL) {
- ERR_print_errors(bio_err);
+ "server certificate private key");
+ if (s_key == NULL)
goto end;
- }
- s_cert = load_cert(s_cert_file, s_cert_format,
- "server certificate file");
+ s_cert = load_cert_pass(s_cert_file, s_cert_format, 1, pass,
+ "server certificate");
- if (s_cert == NULL) {
- ERR_print_errors(bio_err);
+ if (s_cert == NULL)
goto end;
- }
if (s_chain_file != NULL) {
- if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL,
+ if (!load_certs(s_chain_file, 0, &s_chain, NULL,
"server certificate chain"))
goto end;
}
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 == NULL) {
- ERR_print_errors(bio_err);
+ "second server certificate private key");
+ if (s_key2 == NULL)
goto end;
- }
- s_cert2 = load_cert(s_cert_file2, s_cert_format,
- "second server certificate file");
+ s_cert2 = load_cert_pass(s_cert_file2, s_cert_format, 1, pass,
+ "second server certificate");
- if (s_cert2 == NULL) {
- ERR_print_errors(bio_err);
+ if (s_cert2 == NULL)
goto end;
- }
}
}
#if !defined(OPENSSL_NO_NEXTPROTONEG)
@@ -1723,12 +1767,9 @@ int s_server_main(int argc, char *argv[])
if (crl_file != NULL) {
X509_CRL *crl;
- crl = load_crl(crl_file, crl_format);
- if (crl == NULL) {
- BIO_puts(bio_err, "Error loading CRL\n");
- ERR_print_errors(bio_err);
+ crl = load_crl(crl_file, crl_format, 0, "CRL");
+ if (crl == NULL)
goto end;
- }
crls = sk_X509_CRL_new_null();
if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
BIO_puts(bio_err, "Error adding CRL\n");
@@ -1744,21 +1785,19 @@ int s_server_main(int argc, char *argv[])
s_dkey_file = s_dcert_file;
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);
+ 0, dpass, engine, "second certificate private key");
+ if (s_dkey == NULL)
goto end;
- }
- s_dcert = load_cert(s_dcert_file, s_dcert_format,
- "second server certificate file");
+ s_dcert = load_cert_pass(s_dcert_file, s_dcert_format, 1, dpass,
+ "second server certificate");
if (s_dcert == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (s_dchain_file != NULL) {
- if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL,
+ if (!load_certs(s_dchain_file, 0, &s_dchain, NULL,
"second server certificate chain"))
goto end;
}
@@ -1768,17 +1807,22 @@ int s_server_main(int argc, char *argv[])
if (bio_s_out == NULL) {
if (s_quiet && !s_debug) {
bio_s_out = BIO_new(BIO_s_null());
- if (s_msg && bio_s_msg == NULL)
+ if (s_msg && bio_s_msg == NULL) {
bio_s_msg = dup_bio_out(FORMAT_TEXT);
+ if (bio_s_msg == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ goto end;
+ }
+ }
} else {
- if (bio_s_out == NULL)
- bio_s_out = dup_bio_out(FORMAT_TEXT);
+ bio_s_out = dup_bio_out(FORMAT_TEXT);
}
}
-#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
- if (nocert)
-#endif
- {
+
+ if (bio_s_out == NULL)
+ goto end;
+
+ if (nocert) {
s_cert_file = NULL;
s_key_file = NULL;
s_dcert_file = NULL;
@@ -1787,7 +1831,7 @@ int s_server_main(int argc, char *argv[])
s_key_file2 = NULL;
}
- ctx = SSL_CTX_new(meth);
+ ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -1809,7 +1853,6 @@ int s_server_main(int argc, char *argv[])
goto end;
}
}
-
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
@@ -1833,7 +1876,6 @@ int s_server_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 (exc != NULL)
ssl_ctx_set_excert(ctx, exc);
@@ -1850,6 +1892,13 @@ int s_server_main(int argc, char *argv[])
SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
}
+ if (no_ca_names) {
+ SSL_CTX_set_options(ctx, SSL_OP_DISABLE_TLSEXT_CA_NAMES);
+ }
+
+ if (ignore_unexpected_eof)
+ SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
+
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",
@@ -1884,7 +1933,8 @@ int s_server_main(int argc, char *argv[])
}
#endif
- if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -1896,7 +1946,9 @@ int s_server_main(int argc, char *argv[])
ssl_ctx_add_crls(ctx, crls, 0);
- if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+ if (!ssl_load_stores(ctx,
+ vfyCApath, vfyCAfile, vfyCAstore,
+ chCApath, chCAfile, chCAstore,
crls, crl_download)) {
BIO_printf(bio_err, "Error loading store locations\n");
ERR_print_errors(bio_err);
@@ -1904,7 +1956,7 @@ int s_server_main(int argc, char *argv[])
}
if (s_cert2) {
- ctx2 = SSL_CTX_new(meth);
+ ctx2 = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx2 == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -1928,7 +1980,6 @@ int s_server_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 (exc != NULL)
ssl_ctx_set_excert(ctx2, exc);
@@ -1945,8 +1996,8 @@ int s_server_main(int argc, char *argv[])
if (async)
SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
- if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile,
- noCApath)) {
+ if (!ctx_set_verify_locations(ctx2, CAfile, noCAfile, CApath,
+ noCApath, CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -1968,54 +2019,70 @@ int s_server_main(int argc, char *argv[])
if (alpn_ctx.data)
SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
-#ifndef OPENSSL_NO_DH
if (!no_dhe) {
- DH *dh = NULL;
+ EVP_PKEY *dhpkey = NULL;
if (dhfile != NULL)
- dh = load_dh_param(dhfile);
+ dhpkey = load_keyparams(dhfile, FORMAT_UNDEF, 0, "DH", "DH parameters");
else if (s_cert_file != NULL)
- dh = load_dh_param(s_cert_file);
+ dhpkey = load_keyparams_suppress(s_cert_file, FORMAT_UNDEF, 0, "DH",
+ "DH parameters", 1);
- if (dh != NULL) {
+ if (dhpkey != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
} else {
BIO_printf(bio_s_out, "Using default temp DH parameters\n");
}
(void)BIO_flush(bio_s_out);
- if (dh == NULL) {
+ if (dhpkey == 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;
+ } else {
+ /*
+ * We need 2 references: one for use by ctx and one for use by
+ * ctx2
+ */
+ if (!EVP_PKEY_up_ref(dhpkey)) {
+ EVP_PKEY_free(dhpkey);
+ goto end;
+ }
+ if (!SSL_CTX_set0_tmp_dh_pkey(ctx, dhpkey)) {
+ BIO_puts(bio_err, "Error setting temp DH parameters\n");
+ ERR_print_errors(bio_err);
+ /* Free 2 references */
+ EVP_PKEY_free(dhpkey);
+ EVP_PKEY_free(dhpkey);
+ goto end;
+ }
}
if (ctx2 != NULL) {
- if (!dhfile) {
- DH *dh2 = load_dh_param(s_cert_file2);
- if (dh2 != NULL) {
+ if (dhfile != NULL) {
+ EVP_PKEY *dhpkey2 = load_keyparams_suppress(s_cert_file2,
+ FORMAT_UNDEF,
+ 0, "DH",
+ "DH parameters", 1);
+
+ if (dhpkey2 != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
(void)BIO_flush(bio_s_out);
- DH_free(dh);
- dh = dh2;
+ EVP_PKEY_free(dhpkey);
+ dhpkey = dhpkey2;
}
}
- if (dh == NULL) {
+ if (dhpkey == NULL) {
SSL_CTX_set_dh_auto(ctx2, 1);
- } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) {
+ } else if (!SSL_CTX_set0_tmp_dh_pkey(ctx2, dhpkey)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
- DH_free(dh);
+ EVP_PKEY_free(dhpkey);
goto end;
}
+ dhpkey = NULL;
}
- DH_free(dh);
+ EVP_PKEY_free(dhpkey);
}
-#endif
if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
goto end;
@@ -2050,10 +2117,16 @@ int s_server_main(int argc, char *argv[])
SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
}
- if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) {
- BIO_printf(bio_err, "error setting PSK identity hint to context\n");
- ERR_print_errors(bio_err);
- goto end;
+ if (psk_identity_hint != NULL) {
+ if (min_version == TLS1_3_VERSION) {
+ BIO_printf(bio_s_out, "PSK warning: there is NO identity hint in TLSv1.3\n");
+ } else {
+ if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) {
+ BIO_printf(bio_err, "error setting PSK identity hint to context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
}
#endif
if (psksessf != NULL) {
@@ -2112,20 +2185,9 @@ int s_server_main(int argc, char *argv[])
#ifndef OPENSSL_NO_SRP
if (srp_verifier_file != NULL) {
- srp_callback_parm.vb = SRP_VBASE_new(srpuserseed);
- srp_callback_parm.user = NULL;
- srp_callback_parm.login = NULL;
- if ((ret =
- SRP_VBASE_init(srp_callback_parm.vb,
- srp_verifier_file)) != SRP_NO_ERROR) {
- BIO_printf(bio_err,
- "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
- srp_verifier_file, ret);
+ if (!set_up_srp_verifier_file(ctx, &srp_callback_parm, srpuserseed,
+ srp_verifier_file))
goto end;
- }
- SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
- SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);
- SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
} else
#endif
if (CAfile != NULL) {
@@ -2236,8 +2298,8 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
SSL_CTX_sess_get_cache_size(ssl_ctx));
}
-static long int count_reads_callback(BIO *bio, int cmd, const char *argp,
- int argi, long int argl, long int ret)
+static long int count_reads_callback(BIO *bio, int cmd, const char *argp, size_t len,
+ int argi, long argl, int ret, size_t *processed)
{
unsigned int *p_counter = (unsigned int *)BIO_get_callback_arg(bio);
@@ -2253,7 +2315,7 @@ static long int count_reads_callback(BIO *bio, int cmd, const char *argp,
if (s_debug) {
BIO_set_callback_arg(bio, (char *)bio_s_out);
- ret = bio_dump_callback(bio, cmd, argp, argi, argl, ret);
+ ret = (int)bio_dump_callback(bio, cmd, argp, len, argi, argl, ret, processed);
BIO_set_callback_arg(bio, (char *)p_counter);
}
@@ -2321,6 +2383,11 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
else
# endif
sbio = BIO_new_dgram(s, BIO_NOCLOSE);
+ if (sbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ ERR_print_errors(bio_err);
+ goto err;
+ }
if (enable_timeouts) {
timeout.tv_sec = 0;
@@ -2370,6 +2437,13 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
BIO *test;
test = BIO_new(BIO_f_nbio_test());
+ if (test == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ ret = -1;
+ BIO_free(sbio);
+ goto err;
+ }
+
sbio = BIO_push(test, sbio);
}
@@ -2377,7 +2451,7 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
SSL_set_accept_state(con);
/* SSL_set_fd(con,s); */
- BIO_set_callback(SSL_get_rbio(con), count_reads_callback);
+ BIO_set_callback_ex(SSL_get_rbio(con), count_reads_callback);
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_msg == 2)
@@ -2536,14 +2610,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
*/
goto err;
}
-#ifndef OPENSSL_NO_HEARTBEATS
- if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
- BIO_printf(bio_err, "HEARTBEATING\n");
- SSL_heartbeat(con);
- i = 0;
- continue;
- }
-#endif
if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_renegotiate(con);
i = SSL_do_handshake(con);
@@ -2585,8 +2651,8 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
continue;
}
if (buf[0] == 'P') {
- static const char *str = "Lets print some clear text\n";
- BIO_write(SSL_get_wbio(con), str, strlen(str));
+ static const char str[] = "Lets print some clear text\n";
+ BIO_write(SSL_get_wbio(con), str, sizeof(str) -1);
}
if (buf[0] == 'S') {
print_stats(bio_s_out, SSL_get_SSL_CTX(con));
@@ -2609,15 +2675,9 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during write\n");
- 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");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
k = SSL_write(con, &(buf[l]), (unsigned int)i);
}
#endif
@@ -2688,7 +2748,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
ret = -1;
goto err;
}
-
if (i < 0) {
ret = 0;
goto err;
@@ -2702,15 +2761,9 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
- 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");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
i = SSL_read(con, (char *)buf, bufsize);
}
#endif
@@ -2757,7 +2810,7 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
err:
if (con != NULL) {
BIO_printf(bio_s_out, "shutting down SSL\n");
- SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ do_ssl_shutdown(con);
SSL_free(con);
}
BIO_printf(bio_s_out, "CONNECTION CLOSED\n");
@@ -2852,15 +2905,9 @@ static int init_ssl_connection(SSL *con)
&& 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");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
@@ -2909,12 +2956,11 @@ static void print_connection_info(SSL *con)
PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con));
- peer = SSL_get_peer_certificate(con);
+ peer = SSL_get0_peer_certificate(con);
if (peer != NULL) {
BIO_printf(bio_s_out, "Client certificate\n");
PEM_write_bio_X509(bio_s_out, peer);
dump_cert_text(bio_s_out, peer);
- X509_free(peer);
peer = NULL;
}
@@ -2959,11 +3005,11 @@ static void print_connection_info(SSL *con)
BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = app_malloc(keymatexportlen, "export key");
- if (!SSL_export_keying_material(con, exportedkeymat,
+ if (SSL_export_keying_material(con, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
- NULL, 0, 0)) {
+ NULL, 0, 0) <= 0) {
BIO_printf(bio_s_out, " Error\n");
} else {
BIO_printf(bio_s_out, " Keying material: ");
@@ -2973,25 +3019,16 @@ static void print_connection_info(SSL *con)
}
OPENSSL_free(exportedkeymat);
}
+#ifndef OPENSSL_NO_KTLS
+ if (BIO_get_ktls_send(SSL_get_wbio(con)))
+ BIO_printf(bio_err, "Using Kernel TLS for sending\n");
+ if (BIO_get_ktls_recv(SSL_get_rbio(con)))
+ BIO_printf(bio_err, "Using Kernel TLS for receiving\n");
+#endif
(void)BIO_flush(bio_s_out);
}
-#ifndef OPENSSL_NO_DH
-static DH *load_dh_param(const char *dhfile)
-{
- DH *ret = NULL;
- BIO *bio;
-
- if ((bio = BIO_new_file(dhfile, "r")) == NULL)
- goto err;
- ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- err:
- BIO_free(bio);
- return ret;
-}
-#endif
-
static int www_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
@@ -3004,12 +3041,21 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
int total_bytes = 0;
#endif
int width;
+#ifndef OPENSSL_NO_KTLS
+ int use_sendfile_for_req = use_sendfile;
+#endif
fd_set readfds;
+ const char *opmode;
+#ifdef CHARSET_EBCDIC
+ BIO *filter;
+#endif
/* Set width for a select call if needed */
width = s + 1;
- buf = app_malloc(bufsize, "server www buffer");
+ /* as we use BIO_gets(), and it always null terminates data, we need
+ * to allocate 1 byte longer buffer to fit the full 2^14 byte record */
+ buf = app_malloc(bufsize + 1, "server www buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
@@ -3023,7 +3069,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
/* lets make the output buffer a reasonable size */
- if (!BIO_set_write_buffer_size(io, bufsize))
+ if (BIO_set_write_buffer_size(io, bufsize) <= 0)
goto err;
if ((con = SSL_new(ctx)) == NULL)
@@ -3042,10 +3088,21 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ if (sbio == NULL) {
+ SSL_free(con);
+ goto err;
+ }
+
if (s_nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
+ if (test == NULL) {
+ SSL_free(con);
+ BIO_free(sbio);
+ goto err;
+ }
+
sbio = BIO_push(test, sbio);
}
SSL_set_bio(con, sbio, sbio);
@@ -3054,12 +3111,17 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
/* 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);
+ ssl_bio = NULL;
#ifdef CHARSET_EBCDIC
- io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
+ filter = BIO_new(BIO_f_ebcdic_filter());
+ if (filter == NULL)
+ goto err;
+
+ io = BIO_push(filter, io);
#endif
if (s_debug) {
- BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+ BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
@@ -3073,7 +3135,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
for (;;) {
- i = BIO_gets(io, buf, bufsize - 1);
+ i = BIO_gets(io, buf, bufsize + 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) {
if (!s_quiet)
@@ -3085,21 +3147,13 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
- 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");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
continue;
}
#endif
-#if !defined(OPENSSL_SYS_MSDOS)
- sleep(1);
-#endif
+ ossl_sleep(1000);
continue;
}
} else if (i == 0) { /* end of input */
@@ -3146,7 +3200,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
* 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_gets(io, buf, bufsize + 1);
}
BIO_puts(io,
@@ -3228,12 +3282,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
BIO_printf(io, "---\n");
print_stats(io, SSL_get_SSL_CTX(con));
BIO_printf(io, "---\n");
- peer = SSL_get_peer_certificate(con);
+ peer = SSL_get0_peer_certificate(con);
if (peer != NULL) {
BIO_printf(io, "Client certificate\n");
X509_print(io, peer);
PEM_write_bio_X509(io, peer);
- X509_free(peer);
peer = NULL;
} else {
BIO_puts(io, "no client certificate available\n");
@@ -3304,9 +3357,10 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
break;
}
- if ((file = BIO_new_file(p, "r")) == NULL) {
+ opmode = (http_server_binmode == 1) ? "rb" : "r";
+ if ((file = BIO_new_file(p, opmode)) == NULL) {
BIO_puts(io, text);
- BIO_printf(io, "Error opening '%s'\r\n", p);
+ BIO_printf(io, "Error opening '%s' mode='%s'\r\n", p, opmode);
ERR_print_errors(io);
break;
}
@@ -3326,38 +3380,83 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
}
/* send the file */
- for (;;) {
- i = BIO_read(file, buf, bufsize);
- if (i <= 0)
- break;
+#ifndef OPENSSL_NO_KTLS
+ if (use_sendfile_for_req && !BIO_get_ktls_send(SSL_get_wbio(con))) {
+ BIO_printf(bio_err, "Warning: sendfile requested but KTLS is not available\n");
+ use_sendfile_for_req = 0;
+ }
+ if (use_sendfile_for_req) {
+ FILE *fp = NULL;
+ int fd;
+ struct stat st;
+ off_t offset = 0;
+ size_t filesize;
+
+ BIO_get_fp(file, &fp);
+ fd = fileno(fp);
+ if (fstat(fd, &st) < 0) {
+ BIO_printf(io, "Error fstat '%s'\r\n", p);
+ ERR_print_errors(io);
+ goto write_error;
+ }
-#ifdef RENEG
- total_bytes += i;
- BIO_printf(bio_err, "%d\n", i);
- if (total_bytes > 3 * 1024) {
- total_bytes = 0;
- BIO_printf(bio_err, "RENEGOTIATE\n");
- SSL_renegotiate(con);
+ filesize = st.st_size;
+ if (((int)BIO_flush(io)) < 0)
+ goto write_error;
+
+ for (;;) {
+ i = SSL_sendfile(con, fd, offset, filesize, 0);
+ if (i < 0) {
+ BIO_printf(io, "Error SSL_sendfile '%s'\r\n", p);
+ ERR_print_errors(io);
+ break;
+ } else {
+ offset += i;
+ filesize -= i;
+ }
+
+ if (filesize <= 0) {
+ if (!s_quiet)
+ BIO_printf(bio_err, "KTLS SENDFILE '%s' OK\n", p);
+
+ break;
+ }
}
+ } else
#endif
+ {
+ for (;;) {
+ i = BIO_read(file, buf, bufsize);
+ if (i <= 0)
+ break;
- for (j = 0; j < i;) {
#ifdef RENEG
- static count = 0;
- if (++count == 13) {
+ total_bytes += i;
+ BIO_printf(bio_err, "%d\n", i);
+ if (total_bytes > 3 * 1024) {
+ total_bytes = 0;
+ BIO_printf(bio_err, "RENEGOTIATE\n");
SSL_renegotiate(con);
}
#endif
- k = BIO_write(io, &(buf[j]), i - j);
- if (k <= 0) {
- if (!BIO_should_retry(io)
- && !SSL_waiting_for_async(con))
- goto write_error;
- else {
- BIO_printf(bio_s_out, "rwrite W BLOCK\n");
+
+ for (j = 0; j < i;) {
+#ifdef RENEG
+ 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)
+ && !SSL_waiting_for_async(con)) {
+ goto write_error;
+ } else {
+ BIO_printf(bio_s_out, "rwrite W BLOCK\n");
+ }
+ } else {
+ j += k;
}
- } else {
- j += k;
}
}
}
@@ -3377,10 +3476,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
}
end:
/* make sure we re-use sessions */
- SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ do_ssl_shutdown(con);
err:
OPENSSL_free(buf);
+ BIO_free(ssl_bio);
BIO_free_all(io);
return ret;
}
@@ -3392,15 +3492,20 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
int ret = 1;
SSL *con;
BIO *io, *ssl_bio, *sbio;
+#ifdef CHARSET_EBCDIC
+ BIO *filter;
+#endif
- buf = app_malloc(bufsize, "server rev buffer");
+ /* as we use BIO_gets(), and it always null terminates data, we need
+ * to allocate 1 byte longer buffer to fit the full 2^14 byte record */
+ buf = app_malloc(bufsize + 1, "server rev buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
goto err;
/* lets make the output buffer a reasonable size */
- if (!BIO_set_write_buffer_size(io, bufsize))
+ if (BIO_set_write_buffer_size(io, bufsize) <= 0)
goto err;
if ((con = SSL_new(ctx)) == NULL)
@@ -3419,18 +3524,29 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ if (sbio == NULL) {
+ SSL_free(con);
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+
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);
+ ssl_bio = NULL;
#ifdef CHARSET_EBCDIC
- io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
+ filter = BIO_new(BIO_f_ebcdic_filter());
+ if (filter == NULL)
+ goto err;
+
+ io = BIO_push(filter, io);
#endif
if (s_debug) {
- BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+ BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
@@ -3456,15 +3572,9 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during accept\n");
- 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");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
continue;
}
#endif
@@ -3473,7 +3583,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
print_ssl_summary(con);
for (;;) {
- i = BIO_gets(io, buf, bufsize - 1);
+ i = BIO_gets(io, buf, bufsize + 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io)) {
if (!s_quiet)
@@ -3485,21 +3595,13 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
- 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");
+
+ lookup_srp_user(&srp_callback_parm, bio_s_out);
+
continue;
}
#endif
-#if !defined(OPENSSL_SYS_MSDOS)
- sleep(1);
-#endif
+ ossl_sleep(1000);
continue;
}
} else if (i == 0) { /* end of input */
@@ -3531,11 +3633,12 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
}
end:
/* make sure we re-use sessions */
- SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ do_ssl_shutdown(con);
err:
OPENSSL_free(buf);
+ BIO_free(ssl_bio);
BIO_free_all(io);
return ret;
}
@@ -3545,6 +3648,8 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len)
{
unsigned int count = 0;
+ unsigned int session_id_prefix_len = strlen(session_id_prefix);
+
do {
if (RAND_bytes(id, *id_len) <= 0)
return 0;
@@ -3556,8 +3661,8 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
* conflicts.
*/
memcpy(id, session_id_prefix,
- (strlen(session_id_prefix) < *id_len) ?
- strlen(session_id_prefix) : *id_len);
+ (session_id_prefix_len < *id_len) ?
+ session_id_prefix_len : *id_len);
}
while (SSL_has_matching_session_id(ssl, id, *id_len) &&
(++count < MAX_SESSION_ID_ATTEMPTS));
@@ -3568,7 +3673,7 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
/*
* By default s_server uses an in-memory cache which caches SSL_SESSION
- * structures without any serialisation. This hides some bugs which only
+ * structures without any serialization. This hides some bugs which only
* become apparent in deployed servers. By implementing a basic external
* session cache some issues can be debugged using s_server.
*/
diff --git a/apps/s_time.c b/apps/s_time.c
index 1235e545c20a..1a58e19de53f 100644
--- a/apps/s_time.c
+++ b/apps/s_time.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -22,9 +22,9 @@
#include <openssl/pem.h>
#include "s_apps.h"
#include <openssl/err.h>
-#include <internal/sockets.h>
+#include "internal/sockets.h"
#if !defined(OPENSSL_SYS_MSDOS)
-# include OPENSSL_UNISTD
+# include <unistd.h>
#endif
#define SSL_CONNECT_NAME "localhost:4433"
@@ -43,40 +43,64 @@ 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;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
+ OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
+ OPT_NEW, OPT_REUSE, OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3,
+ OPT_WWW, OPT_TLS1, OPT_TLS1_1, OPT_TLS1_2, OPT_TLS1_3,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS s_time_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Connection"),
{"connect", OPT_CONNECT, 's',
"Where to connect as post:port (default is " SSL_CONNECT_NAME ")"},
+ {"new", OPT_NEW, '-', "Just time new connections"},
+ {"reuse", OPT_REUSE, '-', "Just time connection reuse"},
+ {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"},
{"cipher", OPT_CIPHER, 's', "TLSv1.2 and below cipher list to be used"},
{"ciphersuites", OPT_CIPHERSUITES, 's',
"Specify TLSv1.3 ciphersuites to be used"},
+#ifndef OPENSSL_NO_SSL3
+ {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
+#endif
+#ifndef OPENSSL_NO_TLS1
+ {"tls1", OPT_TLS1, '-', "Just use TLSv1.0"},
+#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
+ {"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"},
+
+ OPT_SECTION("Certificate"),
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"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"},
{"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+ {"CAstore", OPT_CASTORE, ':', "URI to store 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
- {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
-#endif
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store URI"},
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -94,15 +118,16 @@ int s_time_main(int argc, char **argv)
SSL *scon = NULL;
SSL_CTX *ctx = NULL;
const SSL_METHOD *meth = NULL;
- char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *ciphersuites = NULL;
+ char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ char *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 noCApath = 0, noCAfile = 0, noCAstore = 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;
+ int min_version = 0, max_version = 0, ver, buf_len, fd;
size_t buf_size;
meth = TLS_client_method();
@@ -129,8 +154,7 @@ int s_time_main(int argc, char **argv)
perform = 1;
break;
case OPT_VERIFY:
- if (!opt_int(opt_arg(), &verify_args.depth))
- goto opthelp;
+ verify_args.depth = opt_int_arg();
BIO_printf(bio_err, "%s: verify depth is %d\n",
prog, verify_args.depth);
break;
@@ -156,6 +180,12 @@ int s_time_main(int argc, char **argv)
case OPT_NOCAFILE:
noCAfile = 1;
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_CIPHER:
cipher = opt_arg();
break;
@@ -166,8 +196,7 @@ int s_time_main(int argc, char **argv)
st_bugs = 1;
break;
case OPT_TIME:
- if (!opt_int(opt_arg(), &maxtime))
- goto opthelp;
+ maxtime = opt_int_arg();
break;
case OPT_WWW:
www_path = opt_arg();
@@ -178,10 +207,33 @@ int s_time_main(int argc, char **argv)
}
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_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -192,8 +244,9 @@ int s_time_main(int argc, char **argv)
if ((ctx = SSL_CTX_new(meth)) == NULL)
goto end;
- SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_quiet_shutdown(ctx, 1);
+ if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
+ goto end;
if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
goto end;
@@ -206,7 +259,8 @@ int s_time_main(int argc, char **argv)
if (!set_cert_stuff(ctx, certfile, keyfile))
goto end;
- if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
@@ -289,7 +343,8 @@ int s_time_main(int argc, char **argv)
continue;
}
SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
- BIO_closesocket(SSL_get_fd(scon));
+ if ((fd = SSL_get_fd(scon)) >= 0)
+ BIO_closesocket(fd);
nConn = 0;
totalTime = 0.0;
@@ -316,7 +371,8 @@ int s_time_main(int argc, char **argv)
bytes_read += i;
}
SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
- BIO_closesocket(SSL_get_fd(scon));
+ if ((fd = SSL_get_fd(scon)) >= 0)
+ BIO_closesocket(fd);
nConn += 1;
if (SSL_session_reused(scon)) {
@@ -338,10 +394,13 @@ int s_time_main(int argc, char **argv)
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);
-
+ if (nConn > 0)
+ printf
+ ("%d connections in %ld real seconds, %ld bytes read per connection\n",
+ nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
+ else
+ printf("0 connections in %ld real seconds\n",
+ (long)time(NULL) - finishtime + maxtime);
ret = 0;
end:
@@ -362,12 +421,19 @@ static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx)
if ((conn = BIO_new(BIO_s_connect())) == NULL)
return NULL;
- BIO_set_conn_hostname(conn, host);
- BIO_set_conn_mode(conn, BIO_SOCK_NODELAY);
+ if (BIO_set_conn_hostname(conn, host) <= 0
+ || BIO_set_conn_mode(conn, BIO_SOCK_NODELAY) <= 0) {
+ BIO_free(conn);
+ return NULL;
+ }
- if (scon == NULL)
+ if (scon == NULL) {
serverCon = SSL_new(ctx);
- else {
+ if (serverCon == NULL) {
+ BIO_free(conn);
+ return NULL;
+ }
+ } else {
serverCon = scon;
SSL_set_connect_state(serverCon);
}
diff --git a/apps/sess_id.c b/apps/sess_id.c
index 8fd584f3b131..714c0f77877e 100644
--- a/apps/sess_id.c
+++ b/apps/sess_id.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -19,22 +19,27 @@
#include <openssl/ssl.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT,
OPT_TEXT, OPT_CERT, OPT_NOOUT, OPT_CONTEXT
} OPTION_CHOICE;
const OPTIONS sess_id_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"context", OPT_CONTEXT, 's', "Set the session ID context"},
+
+ OPT_SECTION("Input"),
+ {"in", OPT_IN, 's', "Input file - default stdin"},
{"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
{"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}
};
@@ -91,6 +96,8 @@ int sess_id_main(int argc, char **argv)
break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
diff --git a/apps/smime.c b/apps/smime.c
index 6fd473775f45..a2ff0b5be75c 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -33,7 +33,7 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx);
#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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,
@@ -41,76 +41,97 @@ typedef enum OPTION_choice {
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_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE,
+ OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG,
OPT_V_ENUM,
- OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, OPT_IN, OPT_INFORM, OPT_OUT,
+ 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"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'c',
+ "Output 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 (ENGINE, other values ignored)"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"stream", OPT_STREAM, '-', "Enable CMS streaming" },
+ {"indef", OPT_INDEF, '-', "Same as -stream" },
+ {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
+ OPT_CONFIG_OPTION,
+
+ OPT_SECTION("Action"),
{"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
{"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
{"sign", OPT_SIGN, '-', "Sign message"},
+ {"resign", OPT_RESIGN, '-', "Resign a signed message"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
+
+ OPT_SECTION("Signing/Encryption"),
+ {"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"},
{"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"},
+ {"nocerts", OPT_NOCERTS, '-',
+ "Don't include signers certificate when signing"},
+
+ OPT_SECTION("Verification/Decryption"),
+ {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
+
+ {"certfile", OPT_CERTFILE, '<', "Other certificates file"},
+ {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"},
+
+ OPT_SECTION("Email"),
{"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"},
+ {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
+
+ OPT_SECTION("Certificate chain"),
{"CApath", OPT_CAPATH, '/', "Trusted certificates directory"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
+ {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"},
{"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"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load certificates from the default certificates store"},
{"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
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"cert", 0, 0, "Recipient certs, used when encrypting"},
{NULL}
};
int smime_main(int argc, char **argv)
{
+ CONF *conf = NULL;
BIO *in = NULL, *out = NULL, *indata = NULL;
EVP_PKEY *key = NULL;
PKCS7 *p7 = NULL;
@@ -119,20 +140,22 @@ int smime_main(int argc, char **argv)
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;
+ EVP_CIPHER *cipher = NULL;
+ EVP_MD *sign_md = NULL;
+ const char *CAfile = NULL, *CApath = NULL, *CAstore = 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;
+ char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL;
+ char *subject = NULL, *digestname = NULL, *ciphername = NULL;
OPTION_CHOICE o;
- int noCApath = 0, noCAfile = 0;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0;
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
- FORMAT_PEM;
+ FORMAT_UNDEF;
int vpmtouched = 0, rv = 0;
ENGINE *e = NULL;
const char *mime_eol = "\n";
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
return 1;
@@ -226,6 +249,15 @@ int smime_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
+ case OPT_CONFIG:
+ conf = app_load_config_modules(opt_arg());
+ if (conf == NULL)
+ goto end;
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
@@ -262,12 +294,10 @@ int smime_main(int argc, char **argv)
recipfile = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_arg(), &sign_md))
- goto opthelp;
+ digestname = opt_arg();
break;
case OPT_CIPHER:
- if (!opt_cipher(opt_unknown(), &cipher))
- goto opthelp;
+ ciphername = opt_unknown();
break;
case OPT_INKEY:
/* If previous -inkey argument add signer to list */
@@ -302,12 +332,18 @@ int smime_main(int argc, char **argv)
case OPT_CAPATH:
CApath = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_CONTENT:
contfile = opt_arg();
break;
@@ -318,13 +354,31 @@ int smime_main(int argc, char **argv)
break;
}
}
+
+ /* Extra arguments are files with recipient keys. */
argc = opt_num_rest();
argv = opt_rest();
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &sign_md))
+ goto opthelp;
+ }
+ if (ciphername != NULL) {
+ if (!opt_cipher_any(ciphername, &cipher))
+ goto opthelp;
+ }
if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) {
BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
goto opthelp;
}
+ if (!operation) {
+ BIO_puts(bio_err,
+ "No operation (-encrypt|-sign|...) specified\n");
+ goto opthelp;
+ }
if (operation & SMIME_SIGNERS) {
/* Check to see if any final signer needs to be appended */
@@ -360,8 +414,6 @@ int smime_main(int argc, char **argv)
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
goto opthelp;
}
- } else if (!operation) {
- goto opthelp;
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
@@ -387,7 +439,7 @@ int smime_main(int argc, char **argv)
if (operation == SMIME_ENCRYPT) {
if (cipher == NULL) {
#ifndef OPENSSL_NO_DES
- cipher = EVP_des_ede3_cbc();
+ cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
#else
BIO_printf(bio_err, "No cipher selected\n");
goto end;
@@ -397,7 +449,7 @@ int smime_main(int argc, char **argv)
if (encerts == NULL)
goto end;
while (*argv != NULL) {
- cert = load_cert(*argv, FORMAT_PEM,
+ cert = load_cert(*argv, FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
@@ -408,15 +460,14 @@ int smime_main(int argc, char **argv)
}
if (certfile != NULL) {
- if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
- "certificate file")) {
+ if (!load_certs(certfile, 0, &other, NULL, "certificates")) {
ERR_print_errors(bio_err);
goto end;
}
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
- if ((recip = load_cert(recipfile, FORMAT_PEM,
+ if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
@@ -434,7 +485,7 @@ int smime_main(int argc, char **argv)
}
if (keyfile != NULL) {
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
}
@@ -444,18 +495,25 @@ int smime_main(int argc, char **argv)
goto end;
if (operation & SMIME_IP) {
+ PKCS7 *p7_in = NULL;
+
+ p7 = PKCS7_new_ex(libctx, app_get0_propq());
+ if (p7 == NULL) {
+ BIO_printf(bio_err, "Error allocating PKCS7 object\n");
+ goto end;
+ }
if (informat == FORMAT_SMIME) {
- p7 = SMIME_read_PKCS7(in, &indata);
+ p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7);
} else if (informat == FORMAT_PEM) {
- p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
+ p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
- p7 = d2i_PKCS7_bio(in, NULL);
+ p7_in = d2i_PKCS7_bio(in, &p7);
} else {
BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
goto end;
}
- if (p7 == NULL) {
+ if (p7_in == NULL) {
BIO_printf(bio_err, "Error reading S/MIME message\n");
goto end;
}
@@ -473,7 +531,8 @@ int smime_main(int argc, char **argv)
goto end;
if (operation == SMIME_VERIFY) {
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, smime_cb);
if (vpmtouched)
@@ -485,7 +544,7 @@ int smime_main(int argc, char **argv)
if (operation == SMIME_ENCRYPT) {
if (indef)
flags |= PKCS7_STREAM;
- p7 = PKCS7_encrypt(encerts, in, cipher, flags);
+ p7 = PKCS7_encrypt_ex(encerts, in, cipher, flags, libctx, app_get0_propq());
} else if (operation & SMIME_SIGNERS) {
int i;
/*
@@ -500,7 +559,7 @@ int smime_main(int argc, char **argv)
flags |= PKCS7_STREAM;
}
flags |= PKCS7_PARTIAL;
- p7 = PKCS7_sign(NULL, NULL, other, in, flags);
+ p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq());
if (p7 == NULL)
goto end;
if (flags & PKCS7_NOCERTS) {
@@ -515,13 +574,13 @@ int smime_main(int argc, char **argv)
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(signerfile, FORMAT_PEM,
- "signer certificate");
+ signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL)
goto end;
- key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key");
if (key == NULL)
goto end;
+
if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
goto end;
X509_free(signer);
@@ -604,12 +663,15 @@ int smime_main(int argc, char **argv)
X509_free(recip);
X509_free(signer);
EVP_PKEY_free(key);
+ EVP_MD_free(sign_md);
+ EVP_CIPHER_free(cipher);
PKCS7_free(p7);
release_engine(e);
BIO_free(in);
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
+ NCONF_free(conf);
return ret;
}
diff --git a/apps/speed.c b/apps/speed.c
index 89bf18480fa1..addf7e32137f 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -1,20 +1,27 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 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
+ * Licensed under the Apache License 2.0 (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
*/
#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
+#define SECONDS 3
+#define PKEY_SECONDS 10
+
+#define RSA_SECONDS PKEY_SECONDS
+#define DSA_SECONDS PKEY_SECONDS
+#define ECDSA_SECONDS PKEY_SECONDS
+#define ECDH_SECONDS PKEY_SECONDS
+#define EdDSA_SECONDS PKEY_SECONDS
+#define SM2_SECONDS PKEY_SECONDS
+#define FFDH_SECONDS PKEY_SECONDS
+
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <stdlib.h>
@@ -22,14 +29,22 @@
#include <math.h>
#include "apps.h"
#include "progs.h"
+#include "internal/numbers.h"
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
+#include <openssl/core_names.h>
#include <openssl/async.h>
#if !defined(OPENSSL_SYS_MSDOS)
-# include OPENSSL_UNISTD
+# include <unistd.h>
+#endif
+
+#if defined(__TANDEM)
+# if defined(OPENSSL_TANDEM_FLOSS)
+# include <floss.h(floss_fork)>
+# endif
#endif
#if defined(_WIN32)
@@ -37,66 +52,14 @@
#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"
+#include <openssl/rsa.h>
+#include "./testrsa.h"
+#ifndef OPENSSL_NO_DH
+# include <openssl/dh.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/dsa.h>
+#include "./testdsa.h"
#include <openssl/modes.h>
#ifndef HAVE_FORK
@@ -104,6 +67,7 @@
# define HAVE_FORK 0
# else
# define HAVE_FORK 1
+# include <sys/wait.h>
# endif
#endif
@@ -116,6 +80,11 @@
#define MAX_MISALIGNMENT 63
#define MAX_ECDH_SIZE 256
#define MISALIGN 64
+#define MAX_FFDH_SIZE 1024
+
+#ifndef RSA_DEFAULT_PRIME_NUM
+# define RSA_DEFAULT_PRIME_NUM 2
+#endif
typedef struct openssl_speed_sec_st {
int sym;
@@ -124,70 +93,15 @@ typedef struct openssl_speed_sec_st {
int ecdsa;
int ecdh;
int eddsa;
+ int sm2;
+ int ffdh;
} openssl_speed_sec_t;
static volatile int run = 0;
-static int mr = 0;
+static int mr = 0; /* machine-readeable output format to merge fork results */
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, int tm);
static void pkey_print_message(const char *str, const char *str2,
@@ -200,6 +114,7 @@ static int do_multi(int multi, int size_num);
static const int lengths_list[] = {
16, 64, 256, 1024, 8 * 1024, 16 * 1024
};
+#define SIZE_NUM OSSL_NELEM(lengths_list)
static const int *lengths = lengths_list;
static const int aead_lengths_list[] = {
@@ -272,17 +187,12 @@ static double Time_F(int s)
return ret;
}
#else
-static double Time_F(int s)
-{
- return app_tminterval(s, usertime);
-}
+# error "SIGALRM not defined and the platform is not Windows"
#endif
static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
const openssl_speed_sec_t *seconds);
-#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)
{
@@ -295,23 +205,21 @@ static int opt_found(const char *name, unsigned int *result,
}
return 0;
}
+#define opt_found(value, pairs, result)\
+ opt_found(value, result, pairs, OSSL_NELEM(pairs))
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
+ OPT_COMMON,
+ OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
+ OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM,
+ OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC
} OPTION_CHOICE;
const OPTIONS speed_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [algorithm...]\n"},
+
+ OPT_SECTION("General"),
{"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"},
@@ -322,160 +230,114 @@ const OPTIONS speed_options[] = {
{"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
+ {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
+
+ OPT_SECTION("Selection"),
+ {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
+ {"hmac", OPT_HMAC, 's', "HMAC using EVP-named digest"},
+ {"cmac", OPT_CMAC, 's', "CMAC using EVP-named cipher"},
+ {"decrypt", OPT_DECRYPT, '-',
+ "Time decryption instead of encryption (only EVP)"},
+ {"aead", OPT_AEAD, '-',
+ "Benchmark EVP-named AEAD cipher in TLS-like sequence"},
+
+ OPT_SECTION("Timing"),
{"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"},
+
+ OPT_R_OPTIONS,
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"algorithm", 0, 0, "Algorithm(s) to test (optional; otherwise tests all)"},
{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"
+enum {
+ D_MD2, D_MDC2, D_MD4, D_MD5, D_SHA1, D_RMD160,
+ D_SHA256, D_SHA512, D_WHIRLPOOL, D_HMAC,
+ D_CBC_DES, D_EDE3_DES, D_RC4, D_CBC_IDEA, D_CBC_SEED,
+ D_CBC_RC2, D_CBC_RC5, D_CBC_BF, D_CBC_CAST,
+ D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES,
+ D_CBC_128_CML, D_CBC_192_CML, D_CBC_256_CML,
+ D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, ALGOR_NUM
+};
+/* name of algorithms to test. MUST BE KEEP IN SYNC with above enum ! */
+static const char *names[ALGOR_NUM] = {
+ "md2", "mdc2", "md4", "md5", "sha1", "rmd160",
+ "sha256", "sha512", "whirlpool", "hmac(md5)",
+ "des-cbc", "des-ede3", "rc4", "idea-cbc", "seed-cbc",
+ "rc2-cbc", "rc5-cbc", "blowfish", "cast-cbc",
+ "aes-128-cbc", "aes-192-cbc", "aes-256-cbc",
+ "camellia-128-cbc", "camellia-192-cbc", "camellia-256-cbc",
+ "evp", "ghash", "rand", "cmac"
};
-#define ALGOR_NUM OSSL_NELEM(names)
-/* list of configured algorithm (remaining) */
+/* list of configured algorithm (remaining), with some few alias */
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
+ {"camellia-128-cbc", D_CBC_128_CML},
+ {"camellia-192-cbc", D_CBC_192_CML},
+ {"camellia-256-cbc", D_CBC_256_CML},
{"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)];
+static double results[ALGOR_NUM][SIZE_NUM];
-#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[] = {
+enum { R_DSA_512, R_DSA_1024, R_DSA_2048, DSA_NUM };
+static const OPT_PAIR dsa_choices[DSA_NUM] = {
{"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[] = {
+
+enum {
+ R_RSA_512, R_RSA_1024, R_RSA_2048, R_RSA_3072, R_RSA_4096, R_RSA_7680,
+ R_RSA_15360, RSA_NUM
+};
+static const OPT_PAIR rsa_choices[RSA_NUM] = {
{"rsa512", R_RSA_512},
{"rsa1024", R_RSA_1024},
{"rsa2048", R_RSA_2048},
@@ -484,49 +346,43 @@ static const OPT_PAIR rsa_choices[] = {
{"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 */
-enum {
- R_EC_P160,
- R_EC_P192,
- R_EC_P224,
- R_EC_P256,
- R_EC_P384,
- R_EC_P521,
+#ifndef OPENSSL_NO_DH
+enum ff_params_t {
+ R_FFDH_2048, R_FFDH_3072, R_FFDH_4096, R_FFDH_6144, R_FFDH_8192, FFDH_NUM
+};
+
+static const OPT_PAIR ffdh_choices[FFDH_NUM] = {
+ {"ffdh2048", R_FFDH_2048},
+ {"ffdh3072", R_FFDH_3072},
+ {"ffdh4096", R_FFDH_4096},
+ {"ffdh6144", R_FFDH_6144},
+ {"ffdh8192", R_FFDH_8192},
+};
+
+static double ffdh_results[FFDH_NUM][1]; /* 1 op: derivation */
+#endif /* OPENSSL_NO_DH */
+
+enum ec_curves_t {
+ R_EC_P160, R_EC_P192, R_EC_P224, R_EC_P256, R_EC_P384, R_EC_P521,
#ifndef OPENSSL_NO_EC2M
- R_EC_K163,
- R_EC_K233,
- R_EC_K283,
- R_EC_K409,
- R_EC_K571,
- R_EC_B163,
- R_EC_B233,
- R_EC_B283,
- R_EC_B409,
- R_EC_B571,
+ R_EC_K163, R_EC_K233, R_EC_K283, R_EC_K409, R_EC_K571,
+ R_EC_B163, R_EC_B233, R_EC_B283, R_EC_B409, R_EC_B571,
#endif
- R_EC_BRP256R1,
- R_EC_BRP256T1,
- R_EC_BRP384R1,
- R_EC_BRP384T1,
- R_EC_BRP512R1,
- R_EC_BRP512T1,
- R_EC_X25519,
- R_EC_X448
+ R_EC_BRP256R1, R_EC_BRP256T1, R_EC_BRP384R1, R_EC_BRP384T1,
+ R_EC_BRP512R1, R_EC_BRP512T1, ECDSA_NUM
};
-
-#ifndef OPENSSL_NO_EC
-static OPT_PAIR ecdsa_choices[] = {
+/* list of ecdsa curves */
+static const OPT_PAIR ecdsa_choices[ECDSA_NUM] = {
{"ecdsap160", R_EC_P160},
{"ecdsap192", R_EC_P192},
{"ecdsap224", R_EC_P224},
{"ecdsap256", R_EC_P256},
{"ecdsap384", R_EC_P384},
{"ecdsap521", R_EC_P521},
-# ifndef OPENSSL_NO_EC2M
+#ifndef OPENSSL_NO_EC2M
{"ecdsak163", R_EC_K163},
{"ecdsak233", R_EC_K233},
{"ecdsak283", R_EC_K283},
@@ -537,7 +393,7 @@ static OPT_PAIR ecdsa_choices[] = {
{"ecdsab283", R_EC_B283},
{"ecdsab409", R_EC_B409},
{"ecdsab571", R_EC_B571},
-# endif
+#endif
{"ecdsabrp256r1", R_EC_BRP256R1},
{"ecdsabrp256t1", R_EC_BRP256T1},
{"ecdsabrp384r1", R_EC_BRP384R1},
@@ -545,18 +401,16 @@ static OPT_PAIR ecdsa_choices[] = {
{"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[] = {
+enum { R_EC_X25519 = ECDSA_NUM, R_EC_X448, EC_NUM };
+/* list of ecdh curves, extension of |ecdsa_choices| list above */
+static const OPT_PAIR ecdh_choices[EC_NUM] = {
{"ecdhp160", R_EC_P160},
{"ecdhp192", R_EC_P192},
{"ecdhp224", R_EC_P224},
{"ecdhp256", R_EC_P256},
{"ecdhp384", R_EC_P384},
{"ecdhp521", R_EC_P521},
-# ifndef OPENSSL_NO_EC2M
+#ifndef OPENSSL_NO_EC2M
{"ecdhk163", R_EC_K163},
{"ecdhk233", R_EC_K233},
{"ecdhk283", R_EC_K283},
@@ -567,7 +421,7 @@ static const OPT_PAIR ecdh_choices[] = {
{"ecdhb283", R_EC_B283},
{"ecdhb409", R_EC_B409},
{"ecdhb571", R_EC_B571},
-# endif
+#endif
{"ecdhbrp256r1", R_EC_BRP256R1},
{"ecdhbrp256t1", R_EC_BRP256T1},
{"ecdhbrp384r1", R_EC_BRP384R1},
@@ -577,28 +431,30 @@ static const OPT_PAIR ecdh_choices[] = {
{"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 */
+static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */
+static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */
-#define R_EC_Ed25519 0
-#define R_EC_Ed448 1
-static OPT_PAIR eddsa_choices[] = {
+enum { R_EC_Ed25519, R_EC_Ed448, EdDSA_NUM };
+static const OPT_PAIR eddsa_choices[EdDSA_NUM] = {
{"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 */
+#ifndef OPENSSL_NO_SM2
+enum { R_EC_CURVESM2, SM2_NUM };
+static const OPT_PAIR sm2_choices[SM2_NUM] = {
+ {"curveSM2", R_EC_CURVESM2}
+};
+# define SM2_ID "TLSv1.3+GM+Cipher+Suite"
+# define SM2_ID_LEN sizeof("TLSv1.3+GM+Cipher+Suite") - 1
+static double sm2_results[SM2_NUM][2]; /* 2 ops: sign then verify */
+#endif /* OPENSSL_NO_SM2 */
+
+#define COND(unused_cond) (run && count < INT_MAX)
+#define COUNT(d) (count)
typedef struct loopargs_st {
ASYNC_JOB *inprogress_job;
@@ -608,25 +464,32 @@ typedef struct loopargs_st {
unsigned char *buf_malloc;
unsigned char *buf2_malloc;
unsigned char *key;
- unsigned int siglen;
+ size_t buflen;
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 *rsa_sign_ctx[RSA_NUM];
+ EVP_PKEY_CTX *rsa_verify_ctx[RSA_NUM];
+ EVP_PKEY_CTX *dsa_sign_ctx[DSA_NUM];
+ EVP_PKEY_CTX *dsa_verify_ctx[DSA_NUM];
+ EVP_PKEY_CTX *ecdsa_sign_ctx[ECDSA_NUM];
+ EVP_PKEY_CTX *ecdsa_verify_ctx[ECDSA_NUM];
EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
+ EVP_MD_CTX *eddsa_ctx2[EdDSA_NUM];
+#ifndef OPENSSL_NO_SM2
+ EVP_MD_CTX *sm2_ctx[SM2_NUM];
+ EVP_MD_CTX *sm2_vfy_ctx[SM2_NUM];
+ EVP_PKEY *sm2_pkey[SM2_NUM];
+#endif
unsigned char *secret_a;
unsigned char *secret_b;
size_t outlen[EC_NUM];
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY_CTX *ffdh_ctx[FFDH_NUM];
+ unsigned char *secret_ff_a;
+ unsigned char *secret_ff_b;
#endif
EVP_CIPHER_CTX *ctx;
- HMAC_CTX *hctx;
- GCM128_CONTEXT *gcm_ctx;
+ EVP_MAC_CTX *mctx;
} loopargs_t;
static int run_benchmark(int async_jobs, int (*loop_function) (void *),
loopargs_t * loopargs);
@@ -634,273 +497,216 @@ static int run_benchmark(int async_jobs, int (*loop_function) (void *),
static unsigned int testnum;
/* Nb of iterations to do per algorithm and key-size */
-static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)];
+static long c[ALGOR_NUM][SIZE_NUM];
-#ifndef OPENSSL_NO_MD2
-static int EVP_Digest_MD2_loop(void *args)
+static char *evp_mac_mdname = "md5";
+static char *evp_hmac_name = NULL;
+static const char *evp_md_name = NULL;
+static char *evp_mac_ciphername = "aes-128-cbc";
+static char *evp_cmac_name = NULL;
+
+static int have_md(const char *name)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char md2[MD2_DIGEST_LENGTH];
- int count;
+ int ret = 0;
+ EVP_MD *md = NULL;
- for (count = 0; COND(c[D_MD2][testnum]); count++) {
- if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(),
- NULL))
- return -1;
+ if (opt_md_silent(name, &md)) {
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+
+ if (ctx != NULL && EVP_DigestInit(ctx, md) > 0)
+ ret = 1;
+ EVP_MD_CTX_free(ctx);
+ EVP_MD_free(md);
}
- return count;
+ return ret;
}
-#endif
-#ifndef OPENSSL_NO_MDC2
-static int EVP_Digest_MDC2_loop(void *args)
+static int have_cipher(const char *name)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char mdc2[MDC2_DIGEST_LENGTH];
- int count;
+ int ret = 0;
+ EVP_CIPHER *cipher = NULL;
- for (count = 0; COND(c[D_MDC2][testnum]); count++) {
- if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(),
- NULL))
- return -1;
+ if (opt_cipher_silent(name, &cipher)) {
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx != NULL
+ && EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) > 0)
+ ret = 1;
+ EVP_CIPHER_CTX_free(ctx);
+ EVP_CIPHER_free(cipher);
}
- return count;
+ return ret;
}
-#endif
-#ifndef OPENSSL_NO_MD4
-static int EVP_Digest_MD4_loop(void *args)
+static int EVP_Digest_loop(const char *mdname, int algindex, void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- unsigned char md4[MD4_DIGEST_LENGTH];
+ unsigned char digest[EVP_MAX_MD_SIZE];
int count;
+ EVP_MD *md = NULL;
- for (count = 0; COND(c[D_MD4][testnum]); count++) {
- if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(),
- NULL))
- return -1;
+ if (!opt_md_silent(mdname, &md))
+ return -1;
+ for (count = 0; COND(c[algindex][testnum]); count++) {
+ if (!EVP_Digest(buf, (size_t)lengths[testnum], digest, NULL, md,
+ NULL)) {
+ count = -1;
+ break;
+ }
}
+ EVP_MD_free(md);
return count;
}
-#endif
-#ifndef OPENSSL_NO_MD5
-static int MD5_loop(void *args)
+static int EVP_Digest_md_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;
+ return EVP_Digest_loop(evp_md_name, D_EVP, args);
}
-static int HMAC_loop(void *args)
+static int EVP_Digest_MD2_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];
- 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;
+ return EVP_Digest_loop("md2", D_MD2, args);
}
-#endif
-static int SHA1_loop(void *args)
+static int EVP_Digest_MDC2_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char sha[SHA_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_SHA1][testnum]); count++)
- SHA1(buf, lengths[testnum], sha);
- return count;
+ return EVP_Digest_loop("mdc2", D_MDC2, args);
}
-static int SHA256_loop(void *args)
+static int EVP_Digest_MD4_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char sha256[SHA256_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_SHA256][testnum]); count++)
- SHA256(buf, lengths[testnum], sha256);
- return count;
+ return EVP_Digest_loop("md4", D_MD4, args);
}
-static int SHA512_loop(void *args)
+static int MD5_loop(void *args)
{
- loopargs_t *tempargs = *(loopargs_t **) args;
- unsigned char *buf = tempargs->buf;
- unsigned char sha512[SHA512_DIGEST_LENGTH];
- int count;
- for (count = 0; COND(c[D_SHA512][testnum]); count++)
- SHA512(buf, lengths[testnum], sha512);
- return count;
+ return EVP_Digest_loop("md5", D_MD5, args);
}
-#ifndef OPENSSL_NO_WHIRLPOOL
-static int WHIRLPOOL_loop(void *args)
+static int EVP_MAC_loop(int algindex, void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
+ EVP_MAC_CTX *mctx = tempargs->mctx;
+ unsigned char mac[EVP_MAX_MD_SIZE];
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];
- 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))
+ for (count = 0; COND(c[algindex][testnum]); count++) {
+ size_t outl;
+
+ if (!EVP_MAC_init(mctx, NULL, 0, NULL)
+ || !EVP_MAC_update(mctx, buf, lengths[testnum])
+ || !EVP_MAC_final(mctx, mac, &outl, sizeof(mac)))
return -1;
}
return count;
}
-#endif
-#ifndef OPENSSL_NO_RC4
-static RC4_KEY rc4_ks;
-static int RC4_loop(void *args)
+static int HMAC_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;
+ return EVP_MAC_loop(D_HMAC, args);
}
-#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)
+static int CMAC_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;
+ return EVP_MAC_loop(D_EVP_CMAC, args);
}
-static int DES_ede3_cbc_encrypt_loop(void *args)
+static int SHA1_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;
+ return EVP_Digest_loop("sha1", D_SHA1, args);
}
-#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)
+static int SHA256_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;
+ return EVP_Digest_loop("sha256", D_SHA256, args);
}
-static int AES_cbc_192_encrypt_loop(void *args)
+static int SHA512_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;
+ return EVP_Digest_loop("sha512", D_SHA512, args);
}
-static int AES_cbc_256_encrypt_loop(void *args)
+static int WHIRLPOOL_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;
+ return EVP_Digest_loop("whirlpool", D_WHIRLPOOL, args);
}
-static int AES_ige_128_encrypt_loop(void *args)
+static int EVP_Digest_RMD160_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;
+ return EVP_Digest_loop("ripemd160", D_RMD160, args);
}
-static int AES_ige_192_encrypt_loop(void *args)
+static int algindex;
+
+static int EVP_Cipher_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);
+
+ if (tempargs->ctx == NULL)
+ return -1;
+ for (count = 0; COND(c[algindex][testnum]); count++)
+ if (EVP_Cipher(tempargs->ctx, buf, buf, (size_t)lengths[testnum]) <= 0)
+ return -1;
return count;
}
-static int AES_ige_256_encrypt_loop(void *args)
+static int GHASH_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
- unsigned char *buf2 = tempargs->buf2;
+ EVP_MAC_CTX *mctx = tempargs->mctx;
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);
+
+ /* just do the update in the loop to be comparable with 1.1.1 */
+ for (count = 0; COND(c[D_GHASH][testnum]); count++) {
+ if (!EVP_MAC_update(mctx, buf, lengths[testnum]))
+ return -1;
+ }
return count;
}
-static int CRYPTO_gcm128_aad_loop(void *args)
+#define MAX_BLOCK_SIZE 128
+
+static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
+
+static EVP_CIPHER_CTX *init_evp_cipher_ctx(const char *ciphername,
+ const unsigned char *key,
+ int keylen)
{
- 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;
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+
+ if (!opt_cipher_silent(ciphername, &cipher))
+ return NULL;
+
+ if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto end;
+
+ if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1)) {
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
+ goto end;
+ }
+
+ if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
+ goto end;
+ }
+
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1)) {
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
+ goto end;
+ }
+
+end:
+ EVP_CIPHER_free(cipher);
+ return ctx;
}
static int RAND_bytes_loop(void *args)
@@ -914,7 +720,6 @@ static int RAND_bytes_loop(void *args)
return count;
}
-static long save_count = 0;
static int decrypt = 0;
static int EVP_Update_loop(void *args)
{
@@ -922,11 +727,9 @@ static int EVP_Update_loop(void *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++) {
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
if (rc != 1) {
/* reset iv in case of counter overflow */
@@ -934,7 +737,7 @@ static int EVP_Update_loop(void *args)
}
}
} else {
- for (count = 0; COND(nb_iter); count++) {
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
if (rc != 1) {
/* reset iv in case of counter overflow */
@@ -961,29 +764,28 @@ static int EVP_Update_loop_ccm(void *args)
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);
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag),
+ tag);
/* reset iv */
- EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
/* counter is reset on every update */
- EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
}
} else {
- for (count = 0; COND(nb_iter); count++) {
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
/* restore iv length field */
- EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
+ (void)EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
/* counter is reset on every update */
- EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
}
}
if (decrypt)
- EVP_DecryptFinal_ex(ctx, buf, &outl);
+ (void)EVP_DecryptFinal_ex(ctx, buf, &outl);
else
- EVP_EncryptFinal_ex(ctx, buf, &outl);
+ (void)EVP_EncryptFinal_ex(ctx, buf, &outl);
return count;
}
@@ -1000,48 +802,27 @@ static int EVP_Update_loop_aead(void *args)
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);
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ sizeof(faketag), faketag);
+ (void)EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+ (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)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);
+ for (count = 0; COND(c[D_EVP][testnum]); count++) {
+ (void)EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ (void)EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+ (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ (void)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)
@@ -1049,12 +830,14 @@ 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;
+ size_t *rsa_num = &tempargs->sigsize;
+ EVP_PKEY_CTX **rsa_sign_ctx = tempargs->rsa_sign_ctx;
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) {
+ *rsa_num = tempargs->buflen;
+ ret = EVP_PKEY_sign(rsa_sign_ctx[testnum], buf2, rsa_num, buf, 36);
+ if (ret <= 0) {
BIO_printf(bio_err, "RSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1069,12 +852,12 @@ 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;
+ size_t rsa_num = tempargs->sigsize;
+ EVP_PKEY_CTX **rsa_verify_ctx = tempargs->rsa_verify_ctx;
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]);
+ ret = EVP_PKEY_verify(rsa_verify_ctx[testnum], buf2, rsa_num, buf, 36);
if (ret <= 0) {
BIO_printf(bio_err, "RSA verify failure\n");
ERR_print_errors(bio_err);
@@ -1084,21 +867,41 @@ static int RSA_verify_loop(void *args)
}
return count;
}
-#endif
-#ifndef OPENSSL_NO_DSA
+#ifndef OPENSSL_NO_DH
+static long ffdh_c[FFDH_NUM][1];
+
+static int FFDH_derive_key_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ EVP_PKEY_CTX *ffdh_ctx = tempargs->ffdh_ctx[testnum];
+ unsigned char *derived_secret = tempargs->secret_ff_a;
+ int count;
+
+ for (count = 0; COND(ffdh_c[testnum][0]); count++) {
+ /* outlen can be overwritten with a too small value (no padding used) */
+ size_t outlen = MAX_FFDH_SIZE;
+
+ EVP_PKEY_derive(ffdh_ctx, derived_secret, &outlen);
+ }
+ return count;
+}
+#endif /* OPENSSL_NO_DH */
+
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;
+ size_t *dsa_num = &tempargs->sigsize;
+ EVP_PKEY_CTX **dsa_sign_ctx = tempargs->dsa_sign_ctx;
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) {
+ *dsa_num = tempargs->buflen;
+ ret = EVP_PKEY_sign(dsa_sign_ctx[testnum], buf2, dsa_num, buf, 20);
+ if (ret <= 0) {
BIO_printf(bio_err, "DSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1113,11 +916,12 @@ 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;
+ size_t dsa_num = tempargs->sigsize;
+ EVP_PKEY_CTX **dsa_verify_ctx = tempargs->dsa_verify_ctx;
int ret, count;
+
for (count = 0; COND(dsa_c[testnum][1]); count++) {
- ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]);
+ ret = EVP_PKEY_verify(dsa_verify_ctx[testnum], buf2, dsa_num, buf, 20);
if (ret <= 0) {
BIO_printf(bio_err, "DSA verify failure\n");
ERR_print_errors(bio_err);
@@ -1127,21 +931,21 @@ static int DSA_verify_loop(void *args)
}
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;
+ unsigned char *buf2 = tempargs->buf2;
+ size_t *ecdsa_num = &tempargs->sigsize;
+ EVP_PKEY_CTX **ecdsa_sign_ctx = tempargs->ecdsa_sign_ctx;
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) {
+ *ecdsa_num = tempargs->buflen;
+ ret = EVP_PKEY_sign(ecdsa_sign_ctx[testnum], buf2, ecdsa_num, buf, 20);
+ if (ret <= 0) {
BIO_printf(bio_err, "ECDSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1155,13 +959,15 @@ 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;
+ unsigned char *buf2 = tempargs->buf2;
+ size_t ecdsa_num = tempargs->sigsize;
+ EVP_PKEY_CTX **ecdsa_verify_ctx = tempargs->ecdsa_verify_ctx;
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) {
+ ret = EVP_PKEY_verify(ecdsa_verify_ctx[testnum], buf2, ecdsa_num,
+ buf, 20);
+ if (ret <= 0) {
BIO_printf(bio_err, "ECDSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
@@ -1214,7 +1020,7 @@ 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;
+ EVP_MD_CTX **edctx = tempargs->eddsa_ctx2;
unsigned char *eddsasig = tempargs->buf2;
size_t eddsasigsize = tempargs->sigsize;
int ret, count;
@@ -1230,7 +1036,75 @@ static int EdDSA_verify_loop(void *args)
}
return count;
}
-#endif /* OPENSSL_NO_EC */
+
+#ifndef OPENSSL_NO_SM2
+static long sm2_c[SM2_NUM][2];
+static int SM2_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_MD_CTX **sm2ctx = tempargs->sm2_ctx;
+ unsigned char *sm2sig = tempargs->buf2;
+ size_t sm2sigsize;
+ int ret, count;
+ EVP_PKEY **sm2_pkey = tempargs->sm2_pkey;
+ const size_t max_size = EVP_PKEY_get_size(sm2_pkey[testnum]);
+
+ for (count = 0; COND(sm2_c[testnum][0]); count++) {
+ sm2sigsize = max_size;
+
+ if (!EVP_DigestSignInit(sm2ctx[testnum], NULL, EVP_sm3(),
+ NULL, sm2_pkey[testnum])) {
+ BIO_printf(bio_err, "SM2 init sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ ret = EVP_DigestSign(sm2ctx[testnum], sm2sig, &sm2sigsize,
+ buf, 20);
+ if (ret == 0) {
+ BIO_printf(bio_err, "SM2 sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ /* update the latest returned size and always use the fixed buffer size */
+ tempargs->sigsize = sm2sigsize;
+ }
+
+ return count;
+}
+
+static int SM2_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_MD_CTX **sm2ctx = tempargs->sm2_vfy_ctx;
+ unsigned char *sm2sig = tempargs->buf2;
+ size_t sm2sigsize = tempargs->sigsize;
+ int ret, count;
+ EVP_PKEY **sm2_pkey = tempargs->sm2_pkey;
+
+ for (count = 0; COND(sm2_c[testnum][1]); count++) {
+ if (!EVP_DigestVerifyInit(sm2ctx[testnum], NULL, EVP_sm3(),
+ NULL, sm2_pkey[testnum])) {
+ BIO_printf(bio_err, "SM2 verify init failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ ret = EVP_DigestVerify(sm2ctx[testnum], sm2sig, sm2sigsize,
+ buf, 20);
+ if (ret != 1) {
+ BIO_printf(bio_err, "SM2 verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+#endif /* OPENSSL_NO_SM2 */
static int run_benchmark(int async_jobs,
int (*loop_function) (void *), loopargs_t * loopargs)
@@ -1383,124 +1257,170 @@ static int run_benchmark(int async_jobs,
return error ? -1 : total_op_count;
}
+typedef struct ec_curve_st {
+ const char *name;
+ unsigned int nid;
+ unsigned int bits;
+ size_t sigsize; /* only used for EdDSA curves */
+} EC_CURVE;
+
+static EVP_PKEY *get_ecdsa(const EC_CURVE *curve)
+{
+ EVP_PKEY_CTX *kctx = NULL;
+ EVP_PKEY *key = NULL;
+
+ /* 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);
+ }
+
+ /*
+ * 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(curve->nid, NULL);
+ if (kctx == NULL) {
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *params = NULL;
+ /*
+ * 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();
+
+ 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_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM
+ || ERR_GET_REASON(error) == ERR_R_UNSUPPORTED))
+ ERR_get_error(); /* pop error from queue */
+ if (ERR_peek_error()) {
+ BIO_printf(bio_err,
+ "Unhandled error in the error queue during EC key setup.\n");
+ ERR_print_errors(bio_err);
+ return NULL;
+ }
+
+ /* Create the context for parameter generation */
+ if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL
+ || EVP_PKEY_paramgen_init(pctx) <= 0
+ || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
+ curve->nid) <= 0
+ || EVP_PKEY_paramgen(pctx, &params) <= 0) {
+ BIO_printf(bio_err, "EC params init failure.\n");
+ ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(pctx);
+ return NULL;
+ }
+ EVP_PKEY_CTX_free(pctx);
+
+ /* Create the context for the key generation */
+ kctx = EVP_PKEY_CTX_new(params, NULL);
+ EVP_PKEY_free(params);
+ }
+ if (kctx == NULL
+ || EVP_PKEY_keygen_init(kctx) <= 0
+ || EVP_PKEY_keygen(kctx, &key) <= 0) {
+ BIO_printf(bio_err, "EC key generation failure.\n");
+ ERR_print_errors(bio_err);
+ key = NULL;
+ }
+ EVP_PKEY_CTX_free(kctx);
+ return key;
+}
+
+#define stop_it(do_it, test_num)\
+ memset(do_it + test_num, 0, OSSL_NELEM(do_it) - test_num);
+
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;
+ EVP_CIPHER *evp_cipher = NULL;
+ EVP_MAC *mac = NULL;
double d = 0.0;
OPTION_CHOICE o;
int async_init = 0, multiblock = 0, pr_header = 0;
- int doit[ALGOR_NUM] = { 0 };
+ uint8_t 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;
+ unsigned int size_num = SIZE_NUM;
+ unsigned int i, k, loopargs_len = 0, async_jobs = 0;
int keylen;
int buflen;
+ BIGNUM *bn = NULL;
+ EVP_PKEY_CTX *genctx = NULL;
#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
+ long op_count = 1;
openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
ECDSA_SECONDS, ECDH_SECONDS,
- EdDSA_SECONDS };
+ EdDSA_SECONDS, SM2_SECONDS,
+ FFDH_SECONDS };
- /* What follows are the buffers and key material. */
-#ifndef OPENSSL_NO_RC5
- RC5_32_KEY rc5_ks;
-#endif
-#ifndef OPENSSL_NO_RC2
- RC2_KEY rc2_ks;
-#endif
-#ifndef OPENSSL_NO_IDEA
- IDEA_KEY_SCHEDULE idea_ks;
-#endif
-#ifndef OPENSSL_NO_SEED
- SEED_KEY_SCHEDULE seed_ks;
-#endif
-#ifndef OPENSSL_NO_BF
- BF_KEY bf_ks;
-#endif
-#ifndef OPENSSL_NO_CAST
- CAST_KEY cast_ks;
-#endif
- static const unsigned char key16[16] = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
- };
- static const unsigned char key24[24] = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
- 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
- };
static const unsigned char key32[32] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
};
-#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,
- 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
- };
- static const unsigned char ckey32[32] = {
- 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
- 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
- 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
- 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
- };
- CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3;
-#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 const unsigned char *rsa_data[RSA_NUM] = {
- test512, test1024, test2048, test3072, test4096, test7680, test15360
+ static const unsigned char deskey[] = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, /* key1 */
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, /* key2 */
+ 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 /* key3 */
};
- static const int rsa_data_length[RSA_NUM] = {
- sizeof(test512), sizeof(test1024),
- sizeof(test2048), sizeof(test3072),
- sizeof(test4096), sizeof(test7680),
- sizeof(test15360)
+ static const struct {
+ const unsigned char *data;
+ unsigned int length;
+ unsigned int bits;
+ } rsa_keys[] = {
+ { test512, sizeof(test512), 512 },
+ { test1024, sizeof(test1024), 1024 },
+ { test2048, sizeof(test2048), 2048 },
+ { test3072, sizeof(test3072), 3072 },
+ { test4096, sizeof(test4096), 4096 },
+ { test7680, sizeof(test7680), 7680 },
+ { test15360, sizeof(test15360), 15360 }
};
- int rsa_doit[RSA_NUM] = { 0 };
+ uint8_t rsa_doit[RSA_NUM] = { 0 };
int primes = RSA_DEFAULT_PRIME_NUM;
-#endif
-#ifndef OPENSSL_NO_DSA
+#ifndef OPENSSL_NO_DH
+ typedef struct ffdh_params_st {
+ const char *name;
+ unsigned int nid;
+ unsigned int bits;
+ } FFDH_PARAMS;
+
+ static const FFDH_PARAMS ffdh_params[FFDH_NUM] = {
+ {"ffdh2048", NID_ffdhe2048, 2048},
+ {"ffdh3072", NID_ffdhe3072, 3072},
+ {"ffdh4096", NID_ffdhe4096, 4096},
+ {"ffdh6144", NID_ffdhe6144, 6144},
+ {"ffdh8192", NID_ffdhe8192, 8192}
+ };
+ uint8_t ffdh_doit[FFDH_NUM] = { 0 };
+
+#endif /* OPENSSL_NO_DH */
static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
- int dsa_doit[DSA_NUM] = { 0 };
-#endif
-#ifndef OPENSSL_NO_EC
+ uint8_t dsa_doit[DSA_NUM] = { 0 };
/*
* 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 |ecdh_choices| list accordingly.
+ * the following arrays and increase the |ecdh_choices| and |ecdsa_choices|
+ * lists accordingly.
*/
- static const struct {
- const char *name;
- unsigned int nid;
- unsigned int bits;
- } test_curves[] = {
+ static const EC_CURVE ec_curves[EC_NUM] = {
/* Prime Curves */
{"secp160r1", NID_secp160r1, 160},
{"nistp192", NID_X9_62_prime192v1, 192},
@@ -1508,7 +1428,7 @@ int speed_main(int argc, char **argv)
{"nistp256", NID_X9_62_prime256v1, 256},
{"nistp384", NID_secp384r1, 384},
{"nistp521", NID_secp521r1, 521},
-# ifndef OPENSSL_NO_EC2M
+#ifndef OPENSSL_NO_EC2M
/* Binary Curves */
{"nistk163", NID_sect163k1, 163},
{"nistk233", NID_sect233k1, 233},
@@ -1520,7 +1440,7 @@ int speed_main(int argc, char **argv)
{"nistb283", NID_sect283r1, 283},
{"nistb409", NID_sect409r1, 409},
{"nistb571", NID_sect571r1, 571},
-# endif
+#endif
{"brainpoolP256r1", NID_brainpoolP256r1, 256},
{"brainpoolP256t1", NID_brainpoolP256t1, 256},
{"brainpoolP384r1", NID_brainpoolP384r1, 384},
@@ -1531,22 +1451,36 @@ int speed_main(int argc, char **argv)
{"X25519", NID_X25519, 253},
{"X448", NID_X448, 448}
};
- static const struct {
- const char *name;
- unsigned int nid;
- unsigned int bits;
- size_t sigsize;
- } test_ed_curves[] = {
+ static const EC_CURVE ed_curves[EdDSA_NUM] = {
/* 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 */
+#ifndef OPENSSL_NO_SM2
+ static const EC_CURVE sm2_curves[SM2_NUM] = {
+ /* SM2 */
+ {"CurveSM2", NID_sm2, 256}
+ };
+ uint8_t sm2_doit[SM2_NUM] = { 0 };
+#endif
+ uint8_t ecdsa_doit[ECDSA_NUM] = { 0 };
+ uint8_t ecdh_doit[EC_NUM] = { 0 };
+ uint8_t eddsa_doit[EdDSA_NUM] = { 0 };
+
+ /* checks declarated curves against choices list. */
+ OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448);
+ OPENSSL_assert(strcmp(eddsa_choices[EdDSA_NUM - 1].name, "ed448") == 0);
+
+ OPENSSL_assert(ec_curves[EC_NUM - 1].nid == NID_X448);
+ OPENSSL_assert(strcmp(ecdh_choices[EC_NUM - 1].name, "ecdhx448") == 0);
+
+ OPENSSL_assert(ec_curves[ECDSA_NUM - 1].nid == NID_brainpoolP512t1);
+ OPENSSL_assert(strcmp(ecdsa_choices[ECDSA_NUM - 1].name, "ecdsabrp512t1") == 0);
+
+#ifndef OPENSSL_NO_SM2
+ OPENSSL_assert(sm2_curves[SM2_NUM - 1].nid == NID_sm2);
+ OPENSSL_assert(strcmp(sm2_choices[SM2_NUM - 1].name, "curveSM2") == 0);
+#endif
prog = opt_init(argc, argv, speed_options);
while ((o = opt_next()) != OPT_EOF) {
@@ -1564,18 +1498,43 @@ int speed_main(int argc, char **argv)
usertime = 0;
break;
case OPT_EVP:
- evp_md = NULL;
- 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) {
+ if (doit[D_EVP]) {
+ BIO_printf(bio_err, "%s: -evp option cannot be used more than once\n", prog);
+ goto opterr;
+ }
+ ERR_set_mark();
+ if (!opt_cipher_silent(opt_arg(), &evp_cipher)) {
+ if (have_md(opt_arg()))
+ evp_md_name = opt_arg();
+ }
+ if (evp_cipher == NULL && evp_md_name == NULL) {
+ ERR_clear_last_mark();
BIO_printf(bio_err,
"%s: %s is an unknown cipher or digest\n",
prog, opt_arg());
goto end;
}
+ ERR_pop_to_mark();
doit[D_EVP] = 1;
break;
+ case OPT_HMAC:
+ if (!have_md(opt_arg())) {
+ BIO_printf(bio_err, "%s: %s is an unknown digest\n",
+ prog, opt_arg());
+ goto end;
+ }
+ evp_mac_mdname = opt_arg();
+ doit[D_HMAC] = 1;
+ break;
+ case OPT_CMAC:
+ if (!have_cipher(opt_arg())) {
+ BIO_printf(bio_err, "%s: %s is an unknown cipher\n",
+ prog, opt_arg());
+ goto end;
+ }
+ evp_mac_ciphername = opt_arg();
+ doit[D_EVP_CMAC] = 1;
+ break;
case OPT_DECRYPT:
decrypt = 1;
break;
@@ -1590,7 +1549,7 @@ int speed_main(int argc, char **argv)
case OPT_MULTI:
#ifndef NO_FORK
multi = atoi(opt_arg());
- if (multi >= INT_MAX / (int)sizeof(int)) {
+ if ((size_t)multi >= SIZE_MAX / sizeof(int)) {
BIO_printf(bio_err, "%s: multi argument too large\n", prog);
return 0;
}
@@ -1612,8 +1571,7 @@ int speed_main(int argc, char **argv)
#endif
break;
case OPT_MISALIGN:
- if (!opt_int(opt_arg(), &misalign))
- goto end;
+ misalign = opt_int_arg();
if (misalign > MISALIGN) {
BIO_printf(bio_err,
"%s: Maximum offset is %d\n", prog, MISALIGN);
@@ -1636,13 +1594,17 @@ int speed_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
- case OPT_PRIMES:
- if (!opt_int(opt_arg(), &primes))
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
goto end;
break;
+ case OPT_PRIMES:
+ primes = opt_int_arg();
+ break;
case OPT_SECONDS:
seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
- = seconds.ecdh = seconds.eddsa = atoi(opt_arg());
+ = seconds.ecdh = seconds.eddsa
+ = seconds.sm2 = seconds.ffdh = atoi(opt_arg());
break;
case OPT_BYTES:
lengths_single = atoi(opt_arg());
@@ -1654,89 +1616,112 @@ int speed_main(int argc, char **argv)
break;
}
}
+
+ /* Remaining arguments are algorithms. */
argc = opt_num_rest();
argv = opt_rest();
- /* Remaining arguments are algorithms. */
+ if (!app_RAND_load())
+ goto end;
+
for (; *argv; argv++) {
- if (found(*argv, doit_choices, &i)) {
+ const char *algo = *argv;
+
+ if (opt_found(algo, doit_choices, &i)) {
doit[i] = 1;
continue;
}
-#ifndef OPENSSL_NO_DES
- if (strcmp(*argv, "des") == 0) {
+ if (strcmp(algo, "des") == 0) {
doit[D_CBC_DES] = doit[D_EDE3_DES] = 1;
continue;
}
-#endif
- if (strcmp(*argv, "sha") == 0) {
+ if (strcmp(algo, "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) {
- for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++)
- rsa_doit[loop] = 1;
- continue;
- }
- if (found(*argv, rsa_choices, &i)) {
- rsa_doit[i] = 1;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ if (strcmp(algo, "openssl") == 0) /* just for compatibility */
continue;
- }
#endif
-#ifndef OPENSSL_NO_DSA
- if (strcmp(*argv, "dsa") == 0) {
- dsa_doit[R_DSA_512] = dsa_doit[R_DSA_1024] =
- dsa_doit[R_DSA_2048] = 1;
- continue;
+ if (strncmp(algo, "rsa", 3) == 0) {
+ if (algo[3] == '\0') {
+ memset(rsa_doit, 1, sizeof(rsa_doit));
+ continue;
+ }
+ if (opt_found(algo, rsa_choices, &i)) {
+ rsa_doit[i] = 1;
+ continue;
+ }
}
- if (found(*argv, dsa_choices, &i)) {
- dsa_doit[i] = 2;
- continue;
+#ifndef OPENSSL_NO_DH
+ if (strncmp(algo, "ffdh", 4) == 0) {
+ if (algo[4] == '\0') {
+ memset(ffdh_doit, 1, sizeof(ffdh_doit));
+ continue;
+ }
+ if (opt_found(algo, ffdh_choices, &i)) {
+ ffdh_doit[i] = 2;
+ continue;
+ }
}
#endif
- if (strcmp(*argv, "aes") == 0) {
+ if (strncmp(algo, "dsa", 3) == 0) {
+ if (algo[3] == '\0') {
+ memset(dsa_doit, 1, sizeof(dsa_doit));
+ continue;
+ }
+ if (opt_found(algo, dsa_choices, &i)) {
+ dsa_doit[i] = 2;
+ continue;
+ }
+ }
+ if (strcmp(algo, "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) {
+ if (strcmp(algo, "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 (strncmp(algo, "ecdsa", 5) == 0) {
+ if (algo[5] == '\0') {
+ memset(ecdsa_doit, 1, sizeof(ecdsa_doit));
+ continue;
+ }
+ if (opt_found(algo, ecdsa_choices, &i)) {
+ ecdsa_doit[i] = 2;
+ continue;
+ }
}
- if (found(*argv, ecdsa_choices, &i)) {
- ecdsa_doit[i] = 2;
- continue;
+ if (strncmp(algo, "ecdh", 4) == 0) {
+ if (algo[4] == '\0') {
+ memset(ecdh_doit, 1, sizeof(ecdh_doit));
+ continue;
+ }
+ if (opt_found(algo, ecdh_choices, &i)) {
+ ecdh_doit[i] = 2;
+ continue;
+ }
}
- if (strcmp(*argv, "ecdh") == 0) {
- for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
- ecdh_doit[loop] = 1;
+ if (strcmp(algo, "eddsa") == 0) {
+ memset(eddsa_doit, 1, sizeof(eddsa_doit));
continue;
}
- if (found(*argv, ecdh_choices, &i)) {
- ecdh_doit[i] = 2;
+ if (opt_found(algo, eddsa_choices, &i)) {
+ eddsa_doit[i] = 2;
continue;
}
- if (strcmp(*argv, "eddsa") == 0) {
- for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
- eddsa_doit[loop] = 1;
+#ifndef OPENSSL_NO_SM2
+ if (strcmp(algo, "sm2") == 0) {
+ memset(sm2_doit, 1, sizeof(sm2_doit));
continue;
}
- if (found(*argv, eddsa_choices, &i)) {
- eddsa_doit[i] = 2;
+ if (opt_found(algo, sm2_choices, &i)) {
+ sm2_doit[i] = 2;
continue;
}
#endif
- BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv);
+ BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo);
goto end;
}
@@ -1745,22 +1730,22 @@ int speed_main(int argc, char **argv)
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) &
+ } else if (!(EVP_CIPHER_get_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)));
+ EVP_CIPHER_get0_name(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");
+ 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) &
+ } else if (!(EVP_CIPHER_get_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)));
+ EVP_CIPHER_get0_name(evp_cipher));
goto end;
} else if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with -mb");
@@ -1794,6 +1779,10 @@ int speed_main(int argc, char **argv)
buflen = lengths[size_num - 1];
if (buflen < 36) /* size of random vector in RSA benchmark */
buflen = 36;
+ if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) {
+ BIO_printf(bio_err, "Error: buffer size too large\n");
+ goto end;
+ }
buflen += MAX_MISALIGNMENT + 1;
loopargs[i].buf_malloc = app_malloc(buflen, "input buffer");
loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer");
@@ -1803,9 +1792,13 @@ int speed_main(int argc, char **argv)
/* 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].buflen = buflen - misalign;
+ loopargs[i].sigsize = buflen - misalign;
loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a");
loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b");
+#ifndef OPENSSL_NO_DH
+ loopargs[i].secret_ff_a = app_malloc(MAX_FFDH_SIZE, "FFDH secret a");
+ loopargs[i].secret_ff_b = app_malloc(MAX_FFDH_SIZE, "FFDH secret b");
#endif
}
@@ -1818,25 +1811,43 @@ int speed_main(int argc, char **argv)
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;
+ if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) {
+ memset(doit, 1, sizeof(doit));
+ doit[D_EVP] = doit[D_EVP_CMAC] = 0;
+ ERR_set_mark();
+ for (i = D_MD2; i <= D_WHIRLPOOL; i++) {
+ if (!have_md(names[i]))
+ doit[i] = 0;
+ }
+ for (i = D_CBC_DES; i <= D_CBC_256_CML; i++) {
+ if (!have_cipher(names[i]))
+ doit[i] = 0;
+ }
+ if ((mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC",
+ app_get0_propq())) != NULL) {
+ EVP_MAC_free(mac);
+ mac = NULL;
+ } else {
+ doit[D_GHASH] = 0;
+ }
+ if ((mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC",
+ app_get0_propq())) != NULL) {
+ EVP_MAC_free(mac);
+ mac = NULL;
+ } else {
+ doit[D_HMAC] = 0;
+ }
+ ERR_pop_to_mark();
+ memset(rsa_doit, 1, sizeof(rsa_doit));
+#ifndef OPENSSL_NO_DH
+ memset(ffdh_doit, 1, sizeof(ffdh_doit));
#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;
+ memset(dsa_doit, 1, sizeof(dsa_doit));
+ memset(ecdsa_doit, 1, sizeof(ecdsa_doit));
+ memset(ecdh_doit, 1, sizeof(ecdh_doit));
+ memset(eddsa_doit, 1, sizeof(eddsa_doit));
+#ifndef OPENSSL_NO_SM2
+ memset(sm2_doit, 1, sizeof(sm2_doit));
#endif
}
for (i = 0; i < ALGOR_NUM; i++)
@@ -1848,308 +1859,10 @@ int speed_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 < loopargs_len; i++) {
- if (primes > RSA_DEFAULT_PRIME_NUM) {
- /* for multi-prime RSA, skip this */
- break;
- }
- 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
-#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
- AES_set_encrypt_key(key16, 128, &aes_ks1);
- AES_set_encrypt_key(key24, 192, &aes_ks2);
- AES_set_encrypt_key(key32, 256, &aes_ks3);
-#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
- SEED_set_key(key16, &seed_ks);
-#endif
-#ifndef OPENSSL_NO_RC4
- RC4_set_key(&rc4_ks, 16, key16);
-#endif
-#ifndef OPENSSL_NO_RC2
- RC2_set_key(&rc2_ks, 16, key16, 128);
-#endif
-#ifndef OPENSSL_NO_RC5
- RC5_32_set_key(&rc5_ks, 16, key16, 12);
-#endif
-#ifndef OPENSSL_NO_BF
- BF_set_key(&bf_ks, 16, key16);
-#endif
-#ifndef OPENSSL_NO_CAST
- CAST_set_key(&cast_ks, 16, key16);
-#endif
-#ifndef SIGALRM
-# ifndef OPENSSL_NO_DES
- BIO_printf(bio_err, "First we calculate the approximate speed ...\n");
- count = 10;
- do {
- long it;
- count *= 2;
- Time_F(START);
- for (it = count; it; it--)
- 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;
- c[D_MD2][0] = count / 10;
- c[D_MDC2][0] = count / 10;
- c[D_MD4][0] = count;
- c[D_MD5][0] = count;
- c[D_HMAC][0] = count;
- c[D_SHA1][0] = count;
- c[D_RMD160][0] = count;
- c[D_RC4][0] = count * 5;
- c[D_CBC_DES][0] = count;
- c[D_EDE3_DES][0] = count / 3;
- c[D_CBC_IDEA][0] = count;
- c[D_CBC_SEED][0] = count;
- c[D_CBC_RC2][0] = count;
- c[D_CBC_RC5][0] = count;
- c[D_CBC_BF][0] = count;
- c[D_CBC_CAST][0] = count;
- c[D_CBC_128_AES][0] = count;
- c[D_CBC_192_AES][0] = count;
- c[D_CBC_256_AES][0] = count;
- c[D_CBC_128_CML][0] = count;
- c[D_CBC_192_CML][0] = count;
- c[D_CBC_256_CML][0] = count;
- c[D_SHA256][0] = count;
- c[D_SHA512][0] = count;
- c[D_WHIRLPOOL][0] = count;
- c[D_IGE_128_AES][0] = count;
- 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++) {
- long l0, l1;
-
- 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;
- c[D_CBC_IDEA][i] = c[D_CBC_IDEA][i - 1] * l0 / l1;
- c[D_CBC_SEED][i] = c[D_CBC_SEED][i - 1] * l0 / l1;
- c[D_CBC_RC2][i] = c[D_CBC_RC2][i - 1] * l0 / l1;
- c[D_CBC_RC5][i] = c[D_CBC_RC5][i - 1] * l0 / l1;
- c[D_CBC_BF][i] = c[D_CBC_BF][i - 1] * l0 / l1;
- c[D_CBC_CAST][i] = c[D_CBC_CAST][i - 1] * l0 / l1;
- c[D_CBC_128_AES][i] = c[D_CBC_128_AES][i - 1] * l0 / l1;
- c[D_CBC_192_AES][i] = c[D_CBC_192_AES][i - 1] * l0 / l1;
- c[D_CBC_256_AES][i] = c[D_CBC_256_AES][i - 1] * l0 / l1;
- c[D_CBC_128_CML][i] = c[D_CBC_128_CML][i - 1] * l0 / l1;
- c[D_CBC_192_CML][i] = c[D_CBC_192_CML][i - 1] * l0 / l1;
- c[D_CBC_256_CML][i] = c[D_CBC_256_CML][i - 1] * l0 / l1;
- c[D_IGE_128_AES][i] = c[D_IGE_128_AES][i - 1] * l0 / l1;
- 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
- 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)
- rsa_doit[i] = 0;
- else {
- if (rsa_c[i][0] == 0) {
- rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
- rsa_c[i][1] = 20;
- }
- }
- }
-# endif
-
-# 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)
- dsa_doit[i] = 0;
- else {
- if (dsa_c[i][0] == 0) {
- dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
- dsa_c[i][1] = 1;
- }
- }
- }
-# endif
-
-# 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)
- ecdsa_doit[i] = 0;
- else {
- if (ecdsa_c[i][0] == 0) {
- ecdsa_c[i][0] = 1;
- ecdsa_c[i][1] = 1;
- }
- }
- }
-# ifndef OPENSSL_NO_EC2M
- ecdsa_c[R_EC_K163][0] = count / 1000;
- ecdsa_c[R_EC_K163][1] = count / 1000 / 2;
- 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)
- ecdsa_doit[i] = 0;
- else {
- if (ecdsa_c[i][0] == 0) {
- ecdsa_c[i][0] = 1;
- ecdsa_c[i][1] = 1;
- }
- }
- }
- ecdsa_c[R_EC_B163][0] = count / 1000;
- ecdsa_c[R_EC_B163][1] = count / 1000 / 2;
- 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)
- ecdsa_doit[i] = 0;
- else {
- if (ecdsa_c[i][0] == 0) {
- ecdsa_c[i][0] = 1;
- ecdsa_c[i][1] = 1;
- }
- }
- }
-# endif
-
- ecdh_c[R_EC_P160][0] = count / 1000;
- for (i = R_EC_P192; i <= R_EC_P521; i++) {
- ecdh_c[i][0] = ecdh_c[i - 1][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;
- }
- }
- }
-# ifndef OPENSSL_NO_EC2M
- ecdh_c[R_EC_K163][0] = count / 1000;
- for (i = R_EC_K233; i <= R_EC_K571; i++) {
- ecdh_c[i][0] = ecdh_c[i - 1][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;
- }
- }
- }
- ecdh_c[R_EC_B163][0] = count / 1000;
- for (i = R_EC_B233; i <= R_EC_B571; i++) {
- ecdh_c[i][0] = ecdh_c[i - 1][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;
- }
- }
- }
-# endif
- /* 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] == 0) {
- ecdh_c[i][0] = 1;
- }
- }
- }
- 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;
-
- eddsa_c[R_EC_Ed25519][0] = count / 1800;
- eddsa_c[R_EC_Ed448][0] = count / 7200;
-# endif
-
-# else
-/* not worth fixing */
-# error "You cannot disable DES on systems without SIGALRM."
-# endif /* OPENSSL_NO_DES */
-#elif SIGALRM > 0
+#if SIGALRM > 0
signal(SIGALRM, alarmed);
-#endif /* SIGALRM */
+#endif
-#ifndef OPENSSL_NO_MD2
if (doit[D_MD2]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum],
@@ -2158,10 +1871,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD2, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_MDC2
+
if (doit[D_MDC2]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum],
@@ -2170,11 +1884,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs);
d = Time_F(STOP);
print_result(D_MDC2, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_MD4
if (doit[D_MD4]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum],
@@ -2183,11 +1897,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD4, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_MD5
if (doit[D_MD5]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum],
@@ -2196,35 +1910,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, MD5_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD5, testnum, count, d);
+ if (count < 0)
+ break;
}
}
- if (doit[D_HMAC]) {
- static const char hmac_key[] = "This is a key...";
- int len = strlen(hmac_key);
-
- 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);
- }
-
- 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);
- count = run_benchmark(async_jobs, HMAC_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_HMAC, testnum, count, d);
- }
- for (i = 0; i < loopargs_len; i++) {
- HMAC_CTX_free(loopargs[i].hctx);
- }
- }
-#endif
if (doit[D_SHA1]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum],
@@ -2233,8 +1923,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, SHA1_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA1, testnum, count, d);
+ if (count < 0)
+ break;
}
}
+
if (doit[D_SHA256]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA256], c[D_SHA256][testnum],
@@ -2243,8 +1936,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, SHA256_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA256, testnum, count, d);
+ if (count < 0)
+ break;
}
}
+
if (doit[D_SHA512]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA512], c[D_SHA512][testnum],
@@ -2253,9 +1949,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, SHA512_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA512, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#ifndef OPENSSL_NO_WHIRLPOOL
+
if (doit[D_WHIRLPOOL]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum],
@@ -2264,11 +1962,11 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs);
d = Time_F(STOP);
print_result(D_WHIRLPOOL, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_RMD160
if (doit[D_RMD160]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_RMD160], c[D_RMD160][testnum],
@@ -2277,319 +1975,215 @@ int speed_main(int argc, char **argv)
count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs);
d = Time_F(STOP);
print_result(D_RMD160, testnum, count, d);
+ if (count < 0)
+ break;
}
}
-#endif
-#ifndef OPENSSL_NO_RC4
- if (doit[D_RC4]) {
+
+ if (doit[D_HMAC]) {
+ static const char hmac_key[] = "This is a key...";
+ int len = strlen(hmac_key);
+ OSSL_PARAM params[3];
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC", app_get0_propq());
+ if (mac == NULL || evp_mac_mdname == NULL)
+ goto end;
+
+ evp_hmac_name = app_malloc(sizeof("hmac()") + strlen(evp_mac_mdname),
+ "HMAC name");
+ sprintf(evp_hmac_name, "hmac(%s)", evp_mac_mdname);
+ names[D_HMAC] = evp_hmac_name;
+
+ params[0] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ evp_mac_mdname, 0);
+ params[1] =
+ OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (char *)hmac_key, len);
+ params[2] = OSSL_PARAM_construct_end();
+
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].mctx = EVP_MAC_CTX_new(mac);
+ if (loopargs[i].mctx == NULL)
+ goto end;
+
+ if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
+ goto skip_hmac; /* Digest not found */
+ }
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum],
+ print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, RC4_loop, loopargs);
+ count = run_benchmark(async_jobs, HMAC_loop, loopargs);
d = Time_F(STOP);
- print_result(D_RC4, testnum, count, d);
+ print_result(D_HMAC, testnum, count, d);
+ if (count < 0)
+ break;
}
+ for (i = 0; i < loopargs_len; i++)
+ EVP_MAC_CTX_free(loopargs[i].mctx);
+ EVP_MAC_free(mac);
+ mac = NULL;
}
-#endif
-#ifndef OPENSSL_NO_DES
+skip_hmac:
if (doit[D_CBC_DES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
+ int st = 1;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx("des-cbc", deskey,
+ sizeof(deskey) / 3);
+ st = loopargs[i].ctx != NULL;
+ }
+ algindex = D_CBC_DES;
+ for (testnum = 0; st && testnum < size_num; testnum++) {
print_message(names[D_CBC_DES], c[D_CBC_DES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs);
+ count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(D_CBC_DES, testnum, count, d);
}
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
if (doit[D_EDE3_DES]) {
- for (testnum = 0; testnum < size_num; testnum++) {
+ int st = 1;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx("des-ede3-cbc", deskey,
+ sizeof(deskey));
+ st = loopargs[i].ctx != NULL;
+ }
+ algindex = D_EDE3_DES;
+ for (testnum = 0; st && testnum < size_num; testnum++) {
print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
- run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs);
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
d = Time_F(STOP);
print_result(D_EDE3_DES, testnum, count, d);
}
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
-#endif
- if (doit[D_CBC_128_AES]) {
- 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);
- count =
- run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_CBC_128_AES, testnum, count, d);
- }
- }
- if (doit[D_CBC_192_AES]) {
- 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);
- count =
- run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_CBC_192_AES, testnum, count, d);
- }
- }
- if (doit[D_CBC_256_AES]) {
- 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);
- count =
- run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_CBC_256_AES, testnum, count, d);
- }
- }
+ for (k = 0; k < 3; k++) {
+ algindex = D_CBC_128_AES + k;
+ if (doit[algindex]) {
+ int st = 1;
- if (doit[D_IGE_128_AES]) {
- 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);
- count =
- run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_IGE_128_AES, testnum, count, d);
+ keylen = 16 + k * 8;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
+ key32, keylen);
+ st = loopargs[i].ctx != NULL;
+ }
+
+ for (testnum = 0; st && testnum < size_num; testnum++) {
+ print_message(names[algindex], c[algindex][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(algindex, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
- if (doit[D_IGE_192_AES]) {
- 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);
- count =
- run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_IGE_192_AES, testnum, count, d);
+
+ for (k = 0; k < 3; k++) {
+ algindex = D_CBC_128_CML + k;
+ if (doit[algindex]) {
+ int st = 1;
+
+ keylen = 16 + k * 8;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
+ key32, keylen);
+ st = loopargs[i].ctx != NULL;
+ }
+
+ for (testnum = 0; st && testnum < size_num; testnum++) {
+ print_message(names[algindex], c[algindex][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(algindex, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
- if (doit[D_IGE_256_AES]) {
- 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);
- count =
- run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs);
- d = Time_F(STOP);
- print_result(D_IGE_256_AES, testnum, count, d);
+
+ for (algindex = D_RC4; algindex <= D_CBC_CAST; algindex++) {
+ if (doit[algindex]) {
+ int st = 1;
+
+ keylen = 16;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ctx = init_evp_cipher_ctx(names[algindex],
+ key32, keylen);
+ st = loopargs[i].ctx != NULL;
+ }
+
+ for (testnum = 0; st && testnum < size_num; testnum++) {
+ print_message(names[algindex], c[algindex][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, EVP_Cipher_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(algindex, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_CIPHER_CTX_free(loopargs[i].ctx);
}
}
if (doit[D_GHASH]) {
+ static const char gmac_iv[] = "0123456789ab";
+ OSSL_PARAM params[3];
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC", app_get0_propq());
+ if (mac == NULL)
+ goto end;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER,
+ "aes-128-gcm", 0);
+ params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV,
+ (char *)gmac_iv,
+ sizeof(gmac_iv) - 1);
+ params[2] = OSSL_PARAM_construct_end();
+
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);
- }
+ loopargs[i].mctx = EVP_MAC_CTX_new(mac);
+ if (loopargs[i].mctx == NULL)
+ goto end;
+ if (!EVP_MAC_init(loopargs[i].mctx, key32, 16, params))
+ goto end;
+ }
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_GHASH], c[D_GHASH][testnum],
- lengths[testnum], seconds.sym);
+ print_message(names[D_GHASH], c[D_GHASH][testnum], lengths[testnum],
+ seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs);
+ count = run_benchmark(async_jobs, GHASH_loop, loopargs);
d = Time_F(STOP);
print_result(D_GHASH, testnum, count, d);
+ if (count < 0)
+ break;
}
for (i = 0; i < loopargs_len; i++)
- CRYPTO_gcm128_release(loopargs[i].gcm_ctx);
- }
-#ifndef OPENSSL_NO_CAMELLIA
- if (doit[D_CBC_128_CML]) {
- 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; 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, testnum, count, d);
- }
- }
- if (doit[D_CBC_192_CML]) {
- 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; 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, testnum, count, d);
- }
- }
- if (doit[D_CBC_256_CML]) {
- 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; 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, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_IDEA
- if (doit[D_CBC_IDEA]) {
- 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; 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, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_SEED
- if (doit[D_CBC_SEED]) {
- 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; 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, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_RC2
- if (doit[D_CBC_RC2]) {
- 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; 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, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_RC5
- if (doit[D_CBC_RC5]) {
- 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; 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, testnum, count, d);
- }
- }
-#endif
-#ifndef OPENSSL_NO_BF
- if (doit[D_CBC_BF]) {
- 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; 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, testnum, count, d);
- }
+ EVP_MAC_CTX_free(loopargs[i].mctx);
+ EVP_MAC_free(mac);
+ mac = NULL;
}
-#endif
-#ifndef OPENSSL_NO_CAST
- if (doit[D_CBC_CAST]) {
- 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; 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, 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],
@@ -2603,20 +2197,20 @@ int speed_main(int argc, char **argv)
if (doit[D_EVP]) {
if (evp_cipher != NULL) {
- int (*loopfunc)(void *args) = EVP_Update_loop;
+ int (*loopfunc) (void *) = EVP_Update_loop;
- if (multiblock && (EVP_CIPHER_flags(evp_cipher) &
+ if (multiblock && (EVP_CIPHER_get_flags(evp_cipher) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
multiblock_speed(evp_cipher, lengths_single, &seconds);
ret = 0;
goto end;
}
- names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
+ names[D_EVP] = EVP_CIPHER_get0_name(evp_cipher);
- if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
+ if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
loopfunc = EVP_Update_loop_ccm;
- } else if (aead && (EVP_CIPHER_flags(evp_cipher) &
+ } else if (aead && (EVP_CIPHER_get_flags(evp_cipher) &
EVP_CIPH_FLAG_AEAD_CIPHER)) {
loopfunc = EVP_Update_loop_aead;
if (lengths == lengths_list) {
@@ -2626,7 +2220,7 @@ int speed_main(int argc, char **argv)
}
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_EVP], save_count, lengths[testnum],
+ print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum],
seconds.sym);
for (k = 0; k < loopargs_len; k++) {
@@ -2644,7 +2238,7 @@ int speed_main(int argc, char **argv)
EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
- keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx);
+ keylen = EVP_CIPHER_CTX_get_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);
if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
@@ -2654,81 +2248,139 @@ int speed_main(int argc, char **argv)
exit(1);
}
OPENSSL_clear_free(loopargs[k].key, keylen);
+
+ /* SIV mode only allows for a single Update operation */
+ if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_SIV_MODE)
+ (void)EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
+ EVP_CTRL_SET_SPEED, 1, NULL);
}
Time_F(START);
count = run_benchmark(async_jobs, loopfunc, loopargs);
d = Time_F(STOP);
- for (k = 0; k < loopargs_len; k++) {
+ for (k = 0; k < loopargs_len; k++)
EVP_CIPHER_CTX_free(loopargs[k].ctx);
- }
print_result(D_EVP, testnum, count, d);
}
- } else if (evp_md != NULL) {
- names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md));
+ } else if (evp_md_name != NULL) {
+ names[D_EVP] = evp_md_name;
for (testnum = 0; testnum < size_num; testnum++) {
- print_message(names[D_EVP], save_count, lengths[testnum],
+ print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
- count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs);
+ count = run_benchmark(async_jobs, EVP_Digest_md_loop, loopargs);
d = Time_F(STOP);
print_result(D_EVP, testnum, count, d);
+ if (count < 0)
+ break;
}
}
}
+ if (doit[D_EVP_CMAC]) {
+ OSSL_PARAM params[3];
+ EVP_CIPHER *cipher = NULL;
+
+ mac = EVP_MAC_fetch(app_get0_libctx(), "CMAC", app_get0_propq());
+ if (mac == NULL || evp_mac_ciphername == NULL)
+ goto end;
+ if (!opt_cipher(evp_mac_ciphername, &cipher))
+ goto end;
+
+ keylen = EVP_CIPHER_get_key_length(cipher);
+ EVP_CIPHER_free(cipher);
+ if (keylen <= 0 || keylen > (int)sizeof(key32)) {
+ BIO_printf(bio_err, "\nRequested CMAC cipher with unsupported key length.\n");
+ goto end;
+ }
+ evp_cmac_name = app_malloc(sizeof("cmac()")
+ + strlen(evp_mac_ciphername), "CMAC name");
+ sprintf(evp_cmac_name, "cmac(%s)", evp_mac_ciphername);
+ names[D_EVP_CMAC] = evp_cmac_name;
+
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER,
+ evp_mac_ciphername, 0);
+ params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (char *)key32, keylen);
+ params[2] = OSSL_PARAM_construct_end();
+
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].mctx = EVP_MAC_CTX_new(mac);
+ if (loopargs[i].mctx == NULL)
+ goto end;
+
+ if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
+ goto end;
+ }
+
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_EVP_CMAC], c[D_EVP_CMAC][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, CMAC_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_EVP_CMAC, testnum, count, d);
+ if (count < 0)
+ break;
+ }
+ for (i = 0; i < loopargs_len; i++)
+ EVP_MAC_CTX_free(loopargs[i].mctx);
+ EVP_MAC_free(mac);
+ mac = NULL;
+ }
+
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++) {
+ EVP_PKEY *rsa_key = NULL;
int st = 0;
+
if (!rsa_doit[testnum])
continue;
- 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);
+ if (primes > RSA_DEFAULT_PRIME_NUM) {
+ /* we haven't set keys yet, generate multi-prime RSA keys */
+ bn = BN_new();
+ st = bn != NULL
+ && BN_set_word(bn, RSA_F4)
+ && init_gen_str(&genctx, "RSA", NULL, 0, NULL, NULL)
+ && EVP_PKEY_CTX_set_rsa_keygen_bits(genctx, rsa_keys[testnum].bits) > 0
+ && EVP_PKEY_CTX_set1_rsa_keygen_pubexp(genctx, bn) > 0
+ && EVP_PKEY_CTX_set_rsa_keygen_primes(genctx, primes) > 0
+ && EVP_PKEY_keygen(genctx, &rsa_key);
+ BN_free(bn);
+ bn = NULL;
+ EVP_PKEY_CTX_free(genctx);
+ genctx = NULL;
+ } else {
+ const unsigned char *p = rsa_keys[testnum].data;
- loopargs[i].rsa_key[testnum] = RSA_new();
- if (loopargs[i].rsa_key[testnum] == NULL) {
- BN_free(bn);
- goto end;
- }
+ st = (rsa_key = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p,
+ rsa_keys[testnum].length)) != NULL;
+ }
- 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;
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].rsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key, NULL);
+ loopargs[i].sigsize = loopargs[i].buflen;
+ if (loopargs[i].rsa_sign_ctx[testnum] == NULL
+ || EVP_PKEY_sign_init(loopargs[i].rsa_sign_ctx[testnum]) <= 0
+ || EVP_PKEY_sign(loopargs[i].rsa_sign_ctx[testnum],
+ loopargs[i].buf2,
+ &loopargs[i].sigsize,
+ loopargs[i].buf, 36) <= 0)
+ st = 0;
}
- if (st == 0) {
+ if (!st) {
BIO_printf(bio_err,
- "RSA sign failure. No RSA sign will be done.\n");
+ "RSA sign setup failure. No RSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
pkey_print_message("private", "rsa",
- rsa_c[testnum][0], rsa_bits[testnum],
+ rsa_c[testnum][0], rsa_keys[testnum].bits,
seconds.rsa);
/* RSA_blinding_on(rsa_key[testnum],NULL); */
Time_F(START);
@@ -2737,25 +2389,30 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
mr ? "+R1:%ld:%d:%.2f\n"
: "%ld %u bits private RSA's in %.2fs\n",
- count, rsa_bits[testnum], d);
+ count, rsa_keys[testnum].bits, d);
rsa_results[testnum][0] = (double)count / d;
- rsa_count = count;
- }
-
- 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;
+ op_count = count;
+ }
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].rsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key,
+ NULL);
+ if (loopargs[i].rsa_verify_ctx[testnum] == NULL
+ || EVP_PKEY_verify_init(loopargs[i].rsa_verify_ctx[testnum]) <= 0
+ || EVP_PKEY_verify(loopargs[i].rsa_verify_ctx[testnum],
+ loopargs[i].buf2,
+ loopargs[i].sigsize,
+ loopargs[i].buf, 36) <= 0)
+ st = 0;
}
- if (st <= 0) {
+ if (!st) {
BIO_printf(bio_err,
- "RSA verify failure. No RSA verify will be done.\n");
+ "RSA verify setup failure. No RSA verify will be done.\n");
ERR_print_errors(bio_err);
rsa_doit[testnum] = 0;
} else {
pkey_print_message("public", "rsa",
- rsa_c[testnum][1], rsa_bits[testnum],
+ rsa_c[testnum][1], rsa_keys[testnum].bits,
seconds.rsa);
Time_F(START);
count = run_benchmark(async_jobs, RSA_verify_loop, loopargs);
@@ -2763,41 +2420,44 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
mr ? "+R2:%ld:%d:%.2f\n"
: "%ld %u bits public RSA's in %.2fs\n",
- count, rsa_bits[testnum], d);
+ count, rsa_keys[testnum].bits, d);
rsa_results[testnum][1] = (double)count / d;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < RSA_NUM; testnum++)
- rsa_doit[testnum] = 0;
+ stop_it(rsa_doit, testnum);
}
+ EVP_PKEY_free(rsa_key);
}
-#endif /* OPENSSL_NO_RSA */
-
- for (i = 0; i < loopargs_len; i++)
- if (RAND_bytes(loopargs[i].buf, 36) <= 0)
- goto end;
-#ifndef OPENSSL_NO_DSA
for (testnum = 0; testnum < DSA_NUM; testnum++) {
- int st = 0;
+ EVP_PKEY *dsa_key = NULL;
+ int st;
+
if (!dsa_doit[testnum])
continue;
- /* 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;
+ st = (dsa_key = get_dsa(dsa_bits[testnum])) != NULL;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].dsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key,
+ NULL);
+ loopargs[i].sigsize = loopargs[i].buflen;
+ if (loopargs[i].dsa_sign_ctx[testnum] == NULL
+ || EVP_PKEY_sign_init(loopargs[i].dsa_sign_ctx[testnum]) <= 0
+
+ || EVP_PKEY_sign(loopargs[i].dsa_sign_ctx[testnum],
+ loopargs[i].buf2,
+ &loopargs[i].sigsize,
+ loopargs[i].buf, 20) <= 0)
+ st = 0;
}
- if (st == 0) {
+ if (!st) {
BIO_printf(bio_err,
- "DSA sign failure. No DSA sign will be done.\n");
+ "DSA sign setup failure. No DSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
pkey_print_message("sign", "dsa",
dsa_c[testnum][0], dsa_bits[testnum],
@@ -2810,18 +2470,23 @@ int speed_main(int argc, char **argv)
: "%ld %u bits DSA signs in %.2fs\n",
count, dsa_bits[testnum], d);
dsa_results[testnum][0] = (double)count / d;
- rsa_count = count;
- }
-
- 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;
+ op_count = count;
+ }
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].dsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key,
+ NULL);
+ if (loopargs[i].dsa_verify_ctx[testnum] == NULL
+ || EVP_PKEY_verify_init(loopargs[i].dsa_verify_ctx[testnum]) <= 0
+ || EVP_PKEY_verify(loopargs[i].dsa_verify_ctx[testnum],
+ loopargs[i].buf2,
+ loopargs[i].sigsize,
+ loopargs[i].buf, 36) <= 0)
+ st = 0;
}
- if (st <= 0) {
+ if (!st) {
BIO_printf(bio_err,
- "DSA verify failure. No DSA verify will be done.\n");
+ "DSA verify setup failure. No DSA verify will be done.\n");
ERR_print_errors(bio_err);
dsa_doit[testnum] = 0;
} else {
@@ -2838,96 +2503,88 @@ int speed_main(int argc, char **argv)
dsa_results[testnum][1] = (double)count / d;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < DSA_NUM; testnum++)
- dsa_doit[testnum] = 0;
+ stop_it(dsa_doit, testnum);
}
+ EVP_PKEY_free(dsa_key);
}
-#endif /* OPENSSL_NO_DSA */
-#ifndef OPENSSL_NO_EC
for (testnum = 0; testnum < ECDSA_NUM; testnum++) {
- int st = 1;
+ EVP_PKEY *ecdsa_key = NULL;
+ int st;
if (!ecdsa_doit[testnum])
- continue; /* Ignore Curve */
- 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) {
+ continue;
+
+ st = (ecdsa_key = get_ecdsa(&ec_curves[testnum])) != NULL;
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ecdsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key,
+ NULL);
+ loopargs[i].sigsize = loopargs[i].buflen;
+ if (loopargs[i].ecdsa_sign_ctx[testnum] == NULL
+ || EVP_PKEY_sign_init(loopargs[i].ecdsa_sign_ctx[testnum]) <= 0
+
+ || EVP_PKEY_sign(loopargs[i].ecdsa_sign_ctx[testnum],
+ loopargs[i].buf2,
+ &loopargs[i].sigsize,
+ loopargs[i].buf, 20) <= 0)
st = 0;
- break;
- }
}
- if (st == 0) {
- BIO_printf(bio_err, "ECDSA failure.\n");
+ if (!st) {
+ BIO_printf(bio_err,
+ "ECDSA sign setup failure. No ECDSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
- 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[testnum][0],
- test_curves[testnum].bits, seconds.ecdsa);
- Time_F(START);
- count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs);
- d = Time_F(STOP);
-
- BIO_printf(bio_err,
- 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 */
- 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[testnum] = 0;
- } else {
- pkey_print_message("verify", "ecdsa",
- ecdsa_c[testnum][1],
- test_curves[testnum].bits, seconds.ecdsa);
- Time_F(START);
- count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs);
- d = Time_F(STOP);
- BIO_printf(bio_err,
- 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;
- }
+ pkey_print_message("sign", "ecdsa",
+ ecdsa_c[testnum][0], ec_curves[testnum].bits,
+ seconds.ecdsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R5:%ld:%u:%.2f\n"
+ : "%ld %u bits ECDSA signs in %.2fs\n",
+ count, ec_curves[testnum].bits, d);
+ ecdsa_results[testnum][0] = (double)count / d;
+ op_count = count;
+ }
+
+ for (i = 0; st && i < loopargs_len; i++) {
+ loopargs[i].ecdsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key,
+ NULL);
+ if (loopargs[i].ecdsa_verify_ctx[testnum] == NULL
+ || EVP_PKEY_verify_init(loopargs[i].ecdsa_verify_ctx[testnum]) <= 0
+ || EVP_PKEY_verify(loopargs[i].ecdsa_verify_ctx[testnum],
+ loopargs[i].buf2,
+ loopargs[i].sigsize,
+ loopargs[i].buf, 20) <= 0)
+ st = 0;
+ }
+ if (!st) {
+ BIO_printf(bio_err,
+ "ECDSA verify setup failure. No ECDSA verify will be done.\n");
+ ERR_print_errors(bio_err);
+ ecdsa_doit[testnum] = 0;
+ } else {
+ pkey_print_message("verify", "ecdsa",
+ ecdsa_c[testnum][1], ec_curves[testnum].bits,
+ seconds.ecdsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R6:%ld:%u:%.2f\n"
+ : "%ld %u bits ECDSA verify in %.2fs\n",
+ count, ec_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 (testnum++; testnum < ECDSA_NUM; testnum++)
- ecdsa_doit[testnum] = 0;
- }
+ if (op_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ stop_it(ecdsa_doit, testnum);
}
}
@@ -2938,7 +2595,6 @@ int speed_main(int argc, char **argv)
continue;
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;
@@ -2946,106 +2602,38 @@ int speed_main(int argc, char **argv)
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);
- }
-
- /* 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;
-
- /* 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 ( /* 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, &params)) {
- 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) <= 0/* 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) <= 0 || /* generate secret key A */
- EVP_PKEY_keygen(kctx, &key_B) <= 0 || /* generate secret key B */
- !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */
- EVP_PKEY_derive_init(ctx) <= 0 || /* init derivation ctx */
- EVP_PKEY_derive_set_peer(ctx, key_B) <= 0 || /* set peer pubkey in ctx */
- EVP_PKEY_derive(ctx, NULL, &outlen) <= 0 || /* determine max length */
- outlen == 0 || /* ensure outlen is a valid size */
- outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) {
+ if ((key_A = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key A */
+ || (key_B = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key B */
+ || (ctx = EVP_PKEY_CTX_new(key_A, NULL)) == NULL /* derivation ctx from skeyA */
+ || EVP_PKEY_derive_init(ctx) <= 0 /* init derivation ctx */
+ || EVP_PKEY_derive_set_peer(ctx, key_B) <= 0 /* set peer pubkey in ctx */
+ || EVP_PKEY_derive(ctx, NULL, &outlen) <= 0 /* 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;
+ op_count = 1;
break;
}
- /* Here we perform a test run, comparing the output of a*B and b*A;
+ /*
+ * 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 */ ) {
+ * code, for maximum performance.
+ */
+ if ((test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) == NULL /* test ctx from skeyB */
+ || EVP_PKEY_derive_init(test_ctx) <= 0 /* init derivation test_ctx */
+ || EVP_PKEY_derive_set_peer(test_ctx, key_A) <= 0 /* set peer pubkey in test_ctx */
+ || EVP_PKEY_derive(test_ctx, NULL, &test_outlen) <= 0 /* determine max length */
+ || EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) <= 0 /* compute a*B */
+ || EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) <= 0 /* 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;
+ op_count = 1;
break;
}
@@ -3055,7 +2643,7 @@ int speed_main(int argc, char **argv)
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH computations don't match.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
break;
}
@@ -3064,15 +2652,13 @@ int speed_main(int argc, char **argv)
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);
+ ec_curves[testnum].bits, seconds.ecdh);
Time_F(START);
count =
run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs);
@@ -3080,15 +2666,14 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
mr ? "+R7:%ld:%d:%.2f\n" :
"%ld %u-bits ECDH ops in %.2fs\n", count,
- test_curves[testnum].bits, d);
+ ec_curves[testnum].bits, d);
ecdh_results[testnum][0] = (double)count / d;
- rsa_count = count;
+ op_count = count;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++)
- ecdh_doit[testnum] = 0;
+ stop_it(ecdh_doit, testnum);
}
}
@@ -3105,9 +2690,14 @@ int speed_main(int argc, char **argv)
st = 0;
break;
}
+ loopargs[i].eddsa_ctx2[testnum] = EVP_MD_CTX_new();
+ if (loopargs[i].eddsa_ctx2[testnum] == NULL) {
+ st = 0;
+ break;
+ }
- if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL))
- == NULL
+ if ((ed_pctx = EVP_PKEY_CTX_new_id(ed_curves[testnum].nid,
+ NULL)) == NULL
|| EVP_PKEY_keygen_init(ed_pctx) <= 0
|| EVP_PKEY_keygen(ed_pctx, &ed_pkey) <= 0) {
st = 0;
@@ -3122,16 +2712,24 @@ int speed_main(int argc, char **argv)
EVP_PKEY_free(ed_pkey);
break;
}
+ if (!EVP_DigestVerifyInit(loopargs[i].eddsa_ctx2[testnum], NULL,
+ NULL, NULL, ed_pkey)) {
+ st = 0;
+ EVP_PKEY_free(ed_pkey);
+ break;
+ }
+
EVP_PKEY_free(ed_pkey);
+ ed_pkey = NULL;
}
if (st == 0) {
BIO_printf(bio_err, "EdDSA failure.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
for (i = 0; i < loopargs_len; i++) {
/* Perform EdDSA signature test */
- loopargs[i].sigsize = test_ed_curves[testnum].sigsize;
+ loopargs[i].sigsize = ed_curves[testnum].sigsize;
st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum],
loopargs[i].buf2, &loopargs[i].sigsize,
loopargs[i].buf, 20);
@@ -3142,11 +2740,11 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
"EdDSA sign failure. No EdDSA sign will be done.\n");
ERR_print_errors(bio_err);
- rsa_count = 1;
+ op_count = 1;
} else {
- pkey_print_message("sign", test_ed_curves[testnum].name,
+ pkey_print_message("sign", ed_curves[testnum].name,
eddsa_c[testnum][0],
- test_ed_curves[testnum].bits, seconds.eddsa);
+ ed_curves[testnum].bits, seconds.eddsa);
Time_F(START);
count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs);
d = Time_F(STOP);
@@ -3154,15 +2752,14 @@ int speed_main(int argc, char **argv)
BIO_printf(bio_err,
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);
+ count, ed_curves[testnum].bits,
+ ed_curves[testnum].name, d);
eddsa_results[testnum][0] = (double)count / d;
- rsa_count = count;
+ op_count = count;
}
-
/* Perform EdDSA verification test */
for (i = 0; i < loopargs_len; i++) {
- st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum],
+ st = EVP_DigestVerify(loopargs[i].eddsa_ctx2[testnum],
loopargs[i].buf2, loopargs[i].sigsize,
loopargs[i].buf, 20);
if (st != 1)
@@ -3174,62 +2771,360 @@ int speed_main(int argc, char **argv)
ERR_print_errors(bio_err);
eddsa_doit[testnum] = 0;
} else {
- pkey_print_message("verify", test_ed_curves[testnum].name,
+ pkey_print_message("verify", ed_curves[testnum].name,
eddsa_c[testnum][1],
- test_ed_curves[testnum].bits, seconds.eddsa);
+ 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);
+ count, ed_curves[testnum].bits,
+ ed_curves[testnum].name, d);
eddsa_results[testnum][1] = (double)count / d;
}
- if (rsa_count <= 1) {
+ if (op_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ stop_it(eddsa_doit, testnum);
+ }
+ }
+ }
+
+#ifndef OPENSSL_NO_SM2
+ for (testnum = 0; testnum < SM2_NUM; testnum++) {
+ int st = 1;
+ EVP_PKEY *sm2_pkey = NULL;
+
+ if (!sm2_doit[testnum])
+ continue; /* Ignore Curve */
+ /* Init signing and verification */
+ for (i = 0; i < loopargs_len; i++) {
+ EVP_PKEY_CTX *sm2_pctx = NULL;
+ EVP_PKEY_CTX *sm2_vfy_pctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ st = 0;
+
+ loopargs[i].sm2_ctx[testnum] = EVP_MD_CTX_new();
+ loopargs[i].sm2_vfy_ctx[testnum] = EVP_MD_CTX_new();
+ if (loopargs[i].sm2_ctx[testnum] == NULL
+ || loopargs[i].sm2_vfy_ctx[testnum] == NULL)
+ break;
+
+ sm2_pkey = NULL;
+
+ st = !((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL)) == NULL
+ || EVP_PKEY_keygen_init(pctx) <= 0
+ || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
+ sm2_curves[testnum].nid) <= 0
+ || EVP_PKEY_keygen(pctx, &sm2_pkey) <= 0);
+ EVP_PKEY_CTX_free(pctx);
+ if (st == 0)
+ break;
+
+ st = 0; /* set back to zero */
+ /* attach it sooner to rely on main final cleanup */
+ loopargs[i].sm2_pkey[testnum] = sm2_pkey;
+ loopargs[i].sigsize = EVP_PKEY_get_size(sm2_pkey);
+
+ sm2_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
+ sm2_vfy_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
+ if (sm2_pctx == NULL || sm2_vfy_pctx == NULL) {
+ EVP_PKEY_CTX_free(sm2_vfy_pctx);
+ break;
+ }
+
+ /* attach them directly to respective ctx */
+ EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_ctx[testnum], sm2_pctx);
+ EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_vfy_ctx[testnum], sm2_vfy_pctx);
+
+ /*
+ * No need to allow user to set an explicit ID here, just use
+ * the one defined in the 'draft-yang-tls-tl13-sm-suites' I-D.
+ */
+ if (EVP_PKEY_CTX_set1_id(sm2_pctx, SM2_ID, SM2_ID_LEN) != 1
+ || EVP_PKEY_CTX_set1_id(sm2_vfy_pctx, SM2_ID, SM2_ID_LEN) != 1)
+ break;
+
+ if (!EVP_DigestSignInit(loopargs[i].sm2_ctx[testnum], NULL,
+ EVP_sm3(), NULL, sm2_pkey))
+ break;
+ if (!EVP_DigestVerifyInit(loopargs[i].sm2_vfy_ctx[testnum], NULL,
+ EVP_sm3(), NULL, sm2_pkey))
+ break;
+ st = 1; /* mark loop as succeeded */
+ }
+ if (st == 0) {
+ BIO_printf(bio_err, "SM2 init failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ } else {
+ for (i = 0; i < loopargs_len; i++) {
+ /* Perform SM2 signature test */
+ st = EVP_DigestSign(loopargs[i].sm2_ctx[testnum],
+ loopargs[i].buf2, &loopargs[i].sigsize,
+ loopargs[i].buf, 20);
+ if (st == 0)
+ break;
+ }
+ if (st == 0) {
+ BIO_printf(bio_err,
+ "SM2 sign failure. No SM2 sign will be done.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ } else {
+ pkey_print_message("sign", sm2_curves[testnum].name,
+ sm2_c[testnum][0],
+ sm2_curves[testnum].bits, seconds.sm2);
+ Time_F(START);
+ count = run_benchmark(async_jobs, SM2_sign_loop, loopargs);
+ d = Time_F(STOP);
+
+ BIO_printf(bio_err,
+ mr ? "+R10:%ld:%u:%s:%.2f\n" :
+ "%ld %u bits %s signs in %.2fs \n",
+ count, sm2_curves[testnum].bits,
+ sm2_curves[testnum].name, d);
+ sm2_results[testnum][0] = (double)count / d;
+ op_count = count;
+ }
+
+ /* Perform SM2 verification test */
+ for (i = 0; i < loopargs_len; i++) {
+ st = EVP_DigestVerify(loopargs[i].sm2_vfy_ctx[testnum],
+ loopargs[i].buf2, loopargs[i].sigsize,
+ loopargs[i].buf, 20);
+ if (st != 1)
+ break;
+ }
+ if (st != 1) {
+ BIO_printf(bio_err,
+ "SM2 verify failure. No SM2 verify will be done.\n");
+ ERR_print_errors(bio_err);
+ sm2_doit[testnum] = 0;
+ } else {
+ pkey_print_message("verify", sm2_curves[testnum].name,
+ sm2_c[testnum][1],
+ sm2_curves[testnum].bits, seconds.sm2);
+ Time_F(START);
+ count = run_benchmark(async_jobs, SM2_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R11:%ld:%u:%s:%.2f\n"
+ : "%ld %u bits %s verify in %.2fs\n",
+ count, sm2_curves[testnum].bits,
+ sm2_curves[testnum].name, d);
+ sm2_results[testnum][1] = (double)count / d;
+ }
+
+ if (op_count <= 1) {
/* if longer than 10s, don't do any more */
- for (testnum++; testnum < EdDSA_NUM; testnum++)
- eddsa_doit[testnum] = 0;
+ for (testnum++; testnum < SM2_NUM; testnum++)
+ sm2_doit[testnum] = 0;
}
}
}
+#endif /* OPENSSL_NO_SM2 */
+
+#ifndef OPENSSL_NO_DH
+ for (testnum = 0; testnum < FFDH_NUM; testnum++) {
+ int ffdh_checks = 1;
+
+ if (!ffdh_doit[testnum])
+ continue;
+
+ for (i = 0; i < loopargs_len; i++) {
+ EVP_PKEY *pkey_A = NULL;
+ EVP_PKEY *pkey_B = NULL;
+ EVP_PKEY_CTX *ffdh_ctx = NULL;
+ EVP_PKEY_CTX *test_ctx = NULL;
+ size_t secret_size;
+ size_t test_out;
+
+ /* 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);
+ }
-#endif /* OPENSSL_NO_EC */
+ pkey_A = EVP_PKEY_new();
+ if (!pkey_A) {
+ BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ pkey_B = EVP_PKEY_new();
+ if (!pkey_B) {
+ BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ ffdh_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
+ if (!ffdh_ctx) {
+ BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ if (EVP_PKEY_keygen_init(ffdh_ctx) <= 0) {
+ BIO_printf(bio_err, "Error while initialising EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_CTX_set_dh_nid(ffdh_ctx, ffdh_params[testnum].nid) <= 0) {
+ BIO_printf(bio_err, "Error setting DH key size for keygen.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ if (EVP_PKEY_keygen(ffdh_ctx, &pkey_A) <= 0 ||
+ EVP_PKEY_keygen(ffdh_ctx, &pkey_B) <= 0) {
+ BIO_printf(bio_err, "FFDH key generation failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ EVP_PKEY_CTX_free(ffdh_ctx);
+
+ /*
+ * check if the derivation works correctly both ways so that
+ * we know if future derive calls will fail, and we can skip
+ * error checking in benchmarked code
+ */
+ ffdh_ctx = EVP_PKEY_CTX_new(pkey_A, NULL);
+ if (ffdh_ctx == NULL) {
+ BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive_init(ffdh_ctx) <= 0) {
+ BIO_printf(bio_err, "FFDH derivation context init failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive_set_peer(ffdh_ctx, pkey_B) <= 0) {
+ BIO_printf(bio_err, "Assigning peer key for derivation failed.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive(ffdh_ctx, NULL, &secret_size) <= 0) {
+ BIO_printf(bio_err, "Checking size of shared secret failed.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (secret_size > MAX_FFDH_SIZE) {
+ BIO_printf(bio_err, "Assertion failure: shared secret too large.\n");
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive(ffdh_ctx,
+ loopargs[i].secret_ff_a,
+ &secret_size) <= 0) {
+ BIO_printf(bio_err, "Shared secret derive failure.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ /* Now check from side B */
+ test_ctx = EVP_PKEY_CTX_new(pkey_B, NULL);
+ if (!test_ctx) {
+ BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+ if (EVP_PKEY_derive_init(test_ctx) <= 0 ||
+ EVP_PKEY_derive_set_peer(test_ctx, pkey_A) <= 0 ||
+ EVP_PKEY_derive(test_ctx, NULL, &test_out) <= 0 ||
+ EVP_PKEY_derive(test_ctx, loopargs[i].secret_ff_b, &test_out) <= 0 ||
+ test_out != secret_size) {
+ BIO_printf(bio_err, "FFDH computation failure.\n");
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ /* compare the computed secrets */
+ if (CRYPTO_memcmp(loopargs[i].secret_ff_a,
+ loopargs[i].secret_ff_b, secret_size)) {
+ BIO_printf(bio_err, "FFDH computations don't match.\n");
+ ERR_print_errors(bio_err);
+ op_count = 1;
+ ffdh_checks = 0;
+ break;
+ }
+
+ loopargs[i].ffdh_ctx[testnum] = ffdh_ctx;
+
+ EVP_PKEY_free(pkey_A);
+ pkey_A = NULL;
+ EVP_PKEY_free(pkey_B);
+ pkey_B = NULL;
+ EVP_PKEY_CTX_free(test_ctx);
+ test_ctx = NULL;
+ }
+ if (ffdh_checks != 0) {
+ pkey_print_message("", "ffdh", ffdh_c[testnum][0],
+ ffdh_params[testnum].bits, seconds.ffdh);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, FFDH_derive_key_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R12:%ld:%d:%.2f\n" :
+ "%ld %u-bits FFDH ops in %.2fs\n", count,
+ ffdh_params[testnum].bits, d);
+ ffdh_results[testnum][0] = (double)count / d;
+ op_count = count;
+ }
+ if (op_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ stop_it(ffdh_doit, testnum);
+ }
+ }
+#endif /* OPENSSL_NO_DH */
#ifndef NO_FORK
show_res:
#endif
if (!mr) {
- printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
+ printf("version: %s\n", OpenSSL_version(OPENSSL_FULL_VERSION_STRING));
printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
- printf("options:");
- printf("%s ", BN_options());
-#ifndef OPENSSL_NO_MD2
- printf("%s ", MD2_options());
-#endif
-#ifndef OPENSSL_NO_RC4
- printf("%s ", RC4_options());
-#endif
-#ifndef OPENSSL_NO_DES
- printf("%s ", DES_options());
-#endif
- printf("%s ", AES_options());
-#ifndef OPENSSL_NO_IDEA
- printf("%s ", IDEA_options());
-#endif
-#ifndef OPENSSL_NO_BF
- printf("%s ", BF_options());
-#endif
- printf("\n%s\n", OpenSSL_version(OPENSSL_CFLAGS));
+ printf("options: %s\n", BN_options());
+ printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS));
+ printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO));
}
if (pr_header) {
- if (mr)
+ if (mr) {
printf("+H");
- else {
- printf
- ("The 'numbers' are in 1000s of bytes per second processed.\n");
+ } else {
+ printf("The 'numbers' are in 1000s of bytes per second processed.\n");
printf("type ");
}
for (testnum = 0; testnum < size_num; testnum++)
@@ -3252,7 +3147,6 @@ int speed_main(int argc, char **argv)
}
printf("\n");
}
-#ifndef OPENSSL_NO_RSA
testnum = 1;
for (k = 0; k < RSA_NUM; k++) {
if (!rsa_doit[k])
@@ -3263,14 +3157,12 @@ int speed_main(int argc, char **argv)
}
if (mr)
printf("+F2:%u:%u:%f:%f\n",
- k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]);
+ k, rsa_keys[k].bits, rsa_results[k][0], rsa_results[k][1]);
else
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_keys[k].bits, 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
testnum = 1;
for (k = 0; k < DSA_NUM; k++) {
if (!dsa_doit[k])
@@ -3287,8 +3179,6 @@ int speed_main(int argc, char **argv)
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_EC
testnum = 1;
for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) {
if (!ecdsa_doit[k])
@@ -3300,11 +3190,11 @@ int speed_main(int argc, char **argv)
if (mr)
printf("+F4:%u:%u:%f:%f\n",
- k, test_curves[k].bits,
+ k, ec_curves[k].bits,
ecdsa_results[k][0], ecdsa_results[k][1]);
else
printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
- test_curves[k].bits, test_curves[k].name,
+ ec_curves[k].bits, ec_curves[k].name,
1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1],
ecdsa_results[k][0], ecdsa_results[k][1]);
}
@@ -3319,12 +3209,12 @@ int speed_main(int argc, char **argv)
}
if (mr)
printf("+F5:%u:%u:%f:%f\n",
- k, test_curves[k].bits,
+ k, ec_curves[k].bits,
ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
else
printf("%4u bits ecdh (%s) %8.4fs %8.1f\n",
- test_curves[k].bits, test_curves[k].name,
+ ec_curves[k].bits, ec_curves[k].name,
1.0 / ecdh_results[k][0], ecdh_results[k][0]);
}
@@ -3339,15 +3229,56 @@ int speed_main(int argc, char **argv)
if (mr)
printf("+F6:%u:%u:%s:%f:%f\n",
- k, test_ed_curves[k].bits, test_ed_curves[k].name,
+ k, ed_curves[k].bits, 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,
+ ed_curves[k].bits, ed_curves[k].name,
1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1],
eddsa_results[k][0], eddsa_results[k][1]);
}
+
+#ifndef OPENSSL_NO_SM2
+ testnum = 1;
+ for (k = 0; k < OSSL_NELEM(sm2_doit); k++) {
+ if (!sm2_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%30ssign verify sign/s verify/s\n", " ");
+ testnum = 0;
+ }
+
+ if (mr)
+ printf("+F7:%u:%u:%s:%f:%f\n",
+ k, sm2_curves[k].bits, sm2_curves[k].name,
+ sm2_results[k][0], sm2_results[k][1]);
+ else
+ printf("%4u bits SM2 (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
+ sm2_curves[k].bits, sm2_curves[k].name,
+ 1.0 / sm2_results[k][0], 1.0 / sm2_results[k][1],
+ sm2_results[k][0], sm2_results[k][1]);
+ }
#endif
+#ifndef OPENSSL_NO_DH
+ testnum = 1;
+ for (k = 0; k < FFDH_NUM; k++) {
+ if (!ffdh_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%23sop op/s\n", " ");
+ testnum = 0;
+ }
+ if (mr)
+ printf("+F8:%u:%u:%f:%f\n",
+ k, ffdh_params[k].bits,
+ ffdh_results[k][0], 1.0 / ffdh_results[k][0]);
+
+ else
+ printf("%4u bits ffdh %8.4fs %8.1f\n",
+ ffdh_params[k].bits,
+ 1.0 / ffdh_results[k][0], ffdh_results[k][0]);
+ }
+#endif /* OPENSSL_NO_DH */
ret = 0;
@@ -3357,25 +3288,55 @@ int speed_main(int argc, char **argv)
OPENSSL_free(loopargs[i].buf_malloc);
OPENSSL_free(loopargs[i].buf2_malloc);
-#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]);
+ BN_free(bn);
+ EVP_PKEY_CTX_free(genctx);
+ for (k = 0; k < RSA_NUM; k++) {
+ EVP_PKEY_CTX_free(loopargs[i].rsa_sign_ctx[k]);
+ EVP_PKEY_CTX_free(loopargs[i].rsa_verify_ctx[k]);
+ }
+#ifndef OPENSSL_NO_DH
+ OPENSSL_free(loopargs[i].secret_ff_a);
+ OPENSSL_free(loopargs[i].secret_ff_b);
+ for (k = 0; k < FFDH_NUM; k++)
+ EVP_PKEY_CTX_free(loopargs[i].ffdh_ctx[k]);
#endif
-#ifndef OPENSSL_NO_EC
- for (k = 0; k < ECDSA_NUM; k++)
- EC_KEY_free(loopargs[i].ecdsa[k]);
+ for (k = 0; k < DSA_NUM; k++) {
+ EVP_PKEY_CTX_free(loopargs[i].dsa_sign_ctx[k]);
+ EVP_PKEY_CTX_free(loopargs[i].dsa_verify_ctx[k]);
+ }
+ for (k = 0; k < ECDSA_NUM; k++) {
+ EVP_PKEY_CTX_free(loopargs[i].ecdsa_sign_ctx[k]);
+ EVP_PKEY_CTX_free(loopargs[i].ecdsa_verify_ctx[k]);
+ }
for (k = 0; k < EC_NUM; k++)
EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
- for (k = 0; k < EdDSA_NUM; k++)
+ for (k = 0; k < EdDSA_NUM; k++) {
EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]);
+ EVP_MD_CTX_free(loopargs[i].eddsa_ctx2[k]);
+ }
+#ifndef OPENSSL_NO_SM2
+ for (k = 0; k < SM2_NUM; k++) {
+ EVP_PKEY_CTX *pctx = NULL;
+
+ /* free signing ctx */
+ if (loopargs[i].sm2_ctx[k] != NULL
+ && (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_ctx[k])) != NULL)
+ EVP_PKEY_CTX_free(pctx);
+ EVP_MD_CTX_free(loopargs[i].sm2_ctx[k]);
+ /* free verification ctx */
+ if (loopargs[i].sm2_vfy_ctx[k] != NULL
+ && (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_vfy_ctx[k])) != NULL)
+ EVP_PKEY_CTX_free(pctx);
+ EVP_MD_CTX_free(loopargs[i].sm2_vfy_ctx[k]);
+ /* free pkey */
+ EVP_PKEY_free(loopargs[i].sm2_pkey[k]);
+ }
+#endif
OPENSSL_free(loopargs[i].secret_a);
OPENSSL_free(loopargs[i].secret_b);
-#endif
}
+ OPENSSL_free(evp_hmac_name);
+ OPENSSL_free(evp_cmac_name);
if (async_jobs > 0) {
for (i = 0; i < loopargs_len; i++)
@@ -3387,49 +3348,38 @@ int speed_main(int argc, char **argv)
}
OPENSSL_free(loopargs);
release_engine(e);
+ EVP_CIPHER_free(evp_cipher);
+ EVP_MAC_free(mac);
return ret;
}
static void print_message(const char *s, long num, int length, int tm)
{
-#ifdef SIGALRM
BIO_printf(bio_err,
mr ? "+DT:%s:%d:%d\n"
: "Doing %s for %ds on %d size blocks: ", s, tm, length);
(void)BIO_flush(bio_err);
run = 1;
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
}
static void pkey_print_message(const char *str, const char *str2, long num,
unsigned int bits, int tm)
{
-#ifdef SIGALRM
BIO_printf(bio_err,
mr ? "+DTP:%d:%s:%s:%d\n"
: "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm);
(void)BIO_flush(bio_err);
run = 1;
alarm(tm);
-#else
- BIO_printf(bio_err,
- mr ? "+DNP:%ld:%d:%s:%s\n"
- : "Doing %ld %u bits %s %s's: ", num, bits, str, str2);
- (void)BIO_flush(bio_err);
-#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, "%s error!\n", names[alg]);
+ ERR_print_errors(bio_err);
+ return;
}
BIO_printf(bio_err,
mr ? "+R:%d:%s:%f\n"
@@ -3454,9 +3404,8 @@ static char *sstrsep(char **string, const char *delim)
delim++;
}
- while (!isdelim[(unsigned char)(**string)]) {
+ while (!isdelim[(unsigned char)(**string)])
(*string)++;
- }
if (**string) {
**string = 0;
@@ -3471,6 +3420,7 @@ static int do_multi(int multi, int size_num)
int n;
int fd[2];
int *fds;
+ int status;
static char sep[] = ":";
fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi");
@@ -3506,7 +3456,12 @@ static int do_multi(int multi, int size_num)
char buf[1024];
char *p;
- f = fdopen(fds[n], "r");
+ if ((f = fdopen(fds[n], "r")) == NULL) {
+ BIO_printf(bio_err, "fdopen failure with 0x%x\n",
+ errno);
+ OPENSSL_free(fds);
+ return 1;
+ }
while (fgets(buf, sizeof(buf), f)) {
p = strchr(buf, '\n');
if (p)
@@ -3540,9 +3495,7 @@ static int do_multi(int multi, int size_num)
d = atof(sstrsep(&p, sep));
rsa_results[k][1] += d;
- }
-# ifndef OPENSSL_NO_DSA
- else if (strncmp(buf, "+F3:", 4) == 0) {
+ } else if (strncmp(buf, "+F3:", 4) == 0) {
int k;
double d;
@@ -3555,10 +3508,7 @@ static int do_multi(int multi, int size_num)
d = atof(sstrsep(&p, sep));
dsa_results[k][1] += d;
- }
-# endif
-# ifndef OPENSSL_NO_EC
- else if (strncmp(buf, "+F4:", 4) == 0) {
+ } else if (strncmp(buf, "+F4:", 4) == 0) {
int k;
double d;
@@ -3595,19 +3545,59 @@ static int do_multi(int multi, int size_num)
d = atof(sstrsep(&p, sep));
eddsa_results[k][1] += d;
- }
-# endif
+# ifndef OPENSSL_NO_SM2
+ } else if (strncmp(buf, "+F7:", 4) == 0) {
+ int k;
+ double d;
- else if (strncmp(buf, "+H:", 3) == 0) {
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ sm2_results[k][0] += d;
+
+ d = atof(sstrsep(&p, sep));
+ sm2_results[k][1] += d;
+# endif /* OPENSSL_NO_SM2 */
+# ifndef OPENSSL_NO_DH
+ } else if (strncmp(buf, "+F8:", 4) == 0) {
+ int k;
+ double d;
+
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ ffdh_results[k][0] += d;
+# endif /* OPENSSL_NO_DH */
+ } else if (strncmp(buf, "+H:", 3) == 0) {
;
- } else
+ } else {
BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf,
n);
+ }
}
fclose(f);
}
OPENSSL_free(fds);
+ for (n = 0; n < multi; ++n) {
+ while (wait(&status) == -1)
+ if (errno != EINTR) {
+ BIO_printf(bio_err, "Waitng for child failed with 0x%x\n",
+ errno);
+ return 1;
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status)) {
+ BIO_printf(bio_err, "Child exited with %d\n", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ BIO_printf(bio_err, "Child terminated by signal %d\n",
+ WTERMSIG(status));
+ }
+ }
return 1;
}
#endif
@@ -3620,8 +3610,8 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
const int *mblengths = mblengths_list;
int j, count, keylen, num = OSSL_NELEM(mblengths_list);
const char *alg_name;
- unsigned char *inp, *out, *key, no_key[32], no_iv[16];
- EVP_CIPHER_CTX *ctx;
+ unsigned char *inp = NULL, *out = NULL, *key, no_key[32], no_iv[16];
+ EVP_CIPHER_CTX *ctx = NULL;
double d = 0.0;
if (lengths_single) {
@@ -3631,22 +3621,32 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
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);
+ if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
+ app_bail_out("failed to allocate cipher context\n");
+ if (!EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv))
+ app_bail_out("failed to initialise cipher context\n");
- keylen = EVP_CIPHER_CTX_key_length(ctx);
+ if ((keylen = EVP_CIPHER_CTX_get_key_length(ctx)) < 0) {
+ BIO_printf(bio_err, "Impossible negative key length: %d\n", keylen);
+ goto err;
+ }
key = app_malloc(keylen, "evp_cipher key");
- EVP_CIPHER_CTX_rand_key(ctx, key);
- EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);
+ if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
+ app_bail_out("failed to generate random cipher key\n");
+ if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL))
+ app_bail_out("failed to set cipher key\n");
OPENSSL_clear_free(key, keylen);
- 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));
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY,
+ sizeof(no_key), no_key) <= 0)
+ app_bail_out("failed to set AEAD key\n");
+ if ((alg_name = EVP_CIPHER_get0_name(evp_cipher)) == NULL)
+ app_bail_out("failed to get cipher name\n");
for (j = 0; j < num; j++) {
print_message(alg_name, 0, mblengths[j], seconds->sym);
Time_F(START);
- for (count = 0; run && count < 0x7fffffff; count++) {
+ for (count = 0; run && count < INT_MAX; count++) {
unsigned char aad[EVP_AEAD_TLS1_AAD_LEN];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
size_t len = mblengths[j];
@@ -3670,8 +3670,9 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
mb_param.out = out;
mb_param.inp = inp;
mb_param.len = len;
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
- sizeof(mb_param), &mb_param);
+ (void)EVP_CIPHER_CTX_ctrl(ctx,
+ EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
+ sizeof(mb_param), &mb_param);
} else {
int pad;
@@ -3717,6 +3718,7 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
fprintf(stdout, "\n");
}
+ err:
OPENSSL_free(inp);
OPENSSL_free(out);
EVP_CIPHER_CTX_free(ctx);
diff --git a/apps/spkac.c b/apps/spkac.c
index f384af6eb60b..d92be7d6450e 100644
--- a/apps/spkac.c
+++ b/apps/spkac.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -21,29 +21,38 @@
#include <openssl/pem.h>
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
OPT_NOOUT, OPT_PUBKEY, OPT_VERIFY, OPT_IN, OPT_OUT,
OPT_ENGINE, OPT_KEY, OPT_CHALLENGE, OPT_PASSIN, OPT_SPKAC,
- OPT_SPKSECT, OPT_KEYFORM
+ OPT_SPKSECT, OPT_KEYFORM, OPT_DIGEST,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS spkac_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+ {"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
+
+ OPT_SECTION("Input"),
{"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)"},
+ {"keyform", OPT_KEYFORM, 'f', "Private key file format (ENGINE, other values ignored)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"challenge", OPT_CHALLENGE, 's', "Challenge string"},
{"spkac", OPT_SPKAC, 's', "Alternative SPKAC name"},
+
+ OPT_SECTION("Output"),
+ {"digest", OPT_DIGEST, 's', "Sign new SPKAC with the specified digest (default: MD5)" },
+ {"out", OPT_OUT, '>', "Output file"},
{"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
+
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -58,8 +67,10 @@ int spkac_main(int argc, char **argv)
char *infile = NULL, *outfile = NULL, *passinarg = NULL, *passin = NULL;
char *spkstr = NULL, *prog;
const char *spkac = "SPKAC", *spksect = "default";
+ const char *digest = "MD5";
+ EVP_MD *md = NULL;
int i, ret = 1, verify = 0, noout = 0, pubkey = 0;
- int keyformat = FORMAT_PEM;
+ int keyformat = FORMAT_UNDEF;
OPTION_CHOICE o;
prog = opt_init(argc, argv, spkac_options);
@@ -108,11 +119,20 @@ int spkac_main(int argc, char **argv)
case OPT_SPKSECT:
spksect = opt_arg();
break;
+ case OPT_DIGEST:
+ digest = opt_arg();
+ break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
@@ -123,6 +143,9 @@ int spkac_main(int argc, char **argv)
}
if (keyfile != NULL) {
+ if (!opt_md(digest, &md))
+ goto end;
+
pkey = load_key(strcmp(keyfile, "-") ? keyfile : NULL,
keyformat, 1, passin, e, "private key");
if (pkey == NULL)
@@ -133,8 +156,15 @@ int spkac_main(int argc, char **argv)
if (challenge != NULL)
ASN1_STRING_set(spki->spkac->challenge,
challenge, (int)strlen(challenge));
- NETSCAPE_SPKI_set_pubkey(spki, pkey);
- NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
+ if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) {
+ BIO_printf(bio_err, "Error setting public key\n");
+ goto end;
+ }
+ i = NETSCAPE_SPKI_sign(spki, pkey, md);
+ if (i <= 0) {
+ BIO_printf(bio_err, "Error signing SPKAC\n");
+ goto end;
+ }
spkstr = NETSCAPE_SPKI_b64_encode(spki);
if (spkstr == NULL)
goto end;
@@ -192,6 +222,7 @@ int spkac_main(int argc, char **argv)
ret = 0;
end:
+ EVP_MD_free(md);
NCONF_free(conf);
NETSCAPE_SPKI_free(spki);
BIO_free_all(out);
diff --git a/apps/srp.c b/apps/srp.c
index 6c5817387973..a9466f830289 100644
--- a/apps/srp.c
+++ b/apps/srp.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -11,7 +11,11 @@
* for the EdelKey project.
*/
+/* SRP is deprecated, so we're going to have to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
#include <openssl/opensslconf.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -186,31 +190,42 @@ static char *srp_create_user(char *user, char **srp_verifier,
}
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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
+ OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS srp_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [user...]\n"},
+
+ OPT_SECTION("General"),
{"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"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Action"),
+ {"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"},
+
+ OPT_SECTION("Configuration"),
+ {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"},
{"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
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"user", 0, 0, "Username(s) to process (optional)"},
{NULL}
};
@@ -283,11 +298,20 @@ int srp_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Optional parameters are usernames. */
argc = opt_num_rest();
argv = opt_rest();
+ if (!app_RAND_load())
+ goto end;
+
if (srpvfile != NULL && configfile != NULL) {
BIO_printf(bio_err,
"-srpvfile and -configfile cannot be specified together.\n");
@@ -320,10 +344,7 @@ int srp_main(int argc, char **argv)
if (configfile == NULL)
configfile = default_config_file;
- if (verbose)
- BIO_printf(bio_err, "Using configuration from %s\n",
- configfile);
- conf = app_load_config(configfile);
+ conf = app_load_config_verbose(configfile, verbose);
if (conf == NULL)
goto end;
if (configfile != default_config_file && !app_load_modules(conf))
@@ -358,8 +379,10 @@ int srp_main(int argc, char **argv)
srpvfile);
db = load_index(srpvfile, NULL);
- if (db == NULL)
+ if (db == NULL) {
+ BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", srpvfile);
goto end;
+ }
/* Lets check some fields */
for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
diff --git a/apps/storeutl.c b/apps/storeutl.c
index 644fe28499d6..30c9915de3e8 100644
--- a/apps/storeutl.c
+++ b/apps/storeutl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -19,24 +19,29 @@
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);
+ const char *prog, OSSL_LIB_CTX *libctx);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN,
+ OPT_COMMON,
+ 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
+ OPT_MD, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS storeutl_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\n"},
+
+ OPT_SECTION("General"),
{"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"},
+ {"", OPT_MD, '-', "Any supported digest"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+
+ OPT_SECTION("Search"),
{"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"},
{"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"},
{"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"},
@@ -45,11 +50,20 @@ const OPTIONS storeutl_options[] = {
{"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"},
+
+ OPT_SECTION("Input"),
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+
+ OPT_SECTION("Output"),
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"text", OPT_TEXT, '-', "Print a text form of the objects"},
+ {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"uri", 0, 0, "URI of the store object"},
{NULL}
};
@@ -68,9 +82,10 @@ int storeutl_main(int argc, char *argv[])
ASN1_INTEGER *serial = NULL;
unsigned char *fingerprint = NULL;
size_t fingerprintlen = 0;
- char *alias = NULL;
+ char *alias = NULL, *digestname = NULL;
OSSL_STORE_SEARCH *search = NULL;
- const EVP_MD *digest = NULL;
+ EVP_MD *digest = NULL;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
@@ -142,16 +157,13 @@ int storeutl_main(int argc, char *argv[])
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);
+ subject = parse_name(opt_arg(), MBSTRING_UTF8, 1, "subject");
+ if (subject == NULL)
goto end;
- }
break;
case OPT_CRITERION_ISSUER:
if (criterion != 0
- || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
- && issuer != NULL)) {
+ && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) {
BIO_printf(bio_err, "%s: criterion already given.\n",
prog);
goto end;
@@ -162,16 +174,13 @@ int storeutl_main(int argc, char *argv[])
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);
+ issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1, "issuer");
+ if (issuer == NULL)
goto end;
- }
break;
case OPT_CRITERION_SERIAL:
if (criterion != 0
- || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
- && serial != NULL)) {
+ && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) {
BIO_printf(bio_err, "%s: criterion already given.\n",
prog);
goto end;
@@ -237,20 +246,24 @@ int storeutl_main(int argc, char *argv[])
e = setup_engine(opt_arg(), 0);
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &digest))
- goto opthelp;
+ digestname = opt_unknown();
+ break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* One argument, the URI */
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);
+ if (argc != 1)
goto opthelp;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &digest))
+ goto opthelp;
}
if (criterion != 0) {
@@ -305,9 +318,10 @@ int storeutl_main(int argc, char *argv[])
ret = process(argv[0], get_ui_method(), &pw_cb_data,
expected, criterion, search,
- text, noout, recursive, 0, out, prog);
+ text, noout, recursive, 0, out, prog, libctx);
end:
+ EVP_MD_free(digest);
OPENSSL_free(fingerprint);
OPENSSL_free(alias);
ASN1_INTEGER_free(serial);
@@ -336,12 +350,13 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...)
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)
+ const char *prog, OSSL_LIB_CTX *libctx)
{
OSSL_STORE_CTX *store_ctx = NULL;
int ret = 1, items = 0;
- if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL))
+ if ((store_ctx = OSSL_STORE_open_ex(uri, libctx, app_get0_propq(), uimeth, uidata,
+ NULL, NULL, NULL))
== NULL) {
BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri);
ERR_print_errors(bio_err);
@@ -379,18 +394,20 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
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);
+ if (OSSL_STORE_eof(store_ctx))
+ break;
ret++;
continue;
}
+ if (OSSL_STORE_eof(store_ctx))
+ break;
+
BIO_printf(bio_err,
"ERROR: OSSL_STORE_load() returned NULL without "
"eof or error indications\n");
@@ -422,7 +439,8 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
ret += process(suburi, uimeth, uidata,
expected, criterion, search,
- text, noout, recursive, indent + 2, out, prog);
+ text, noout, recursive, indent + 2, out, prog,
+ libctx);
}
break;
case OSSL_STORE_INFO_PARAMS:
@@ -433,6 +451,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
PEM_write_bio_Parameters(out,
OSSL_STORE_INFO_get0_PARAMS(info));
break;
+ case OSSL_STORE_INFO_PUBKEY:
+ if (text)
+ EVP_PKEY_print_public(out, OSSL_STORE_INFO_get0_PUBKEY(info),
+ 0, NULL);
+ if (!noout)
+ PEM_write_bio_PUBKEY(out, OSSL_STORE_INFO_get0_PUBKEY(info));
+ break;
case OSSL_STORE_INFO_PKEY:
if (text)
EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info),
diff --git a/apps/testdsa.h b/apps/testdsa.h
index 3c4b459db117..d80d2cf7f2d2 100644
--- a/apps/testdsa.h
+++ b/apps/testdsa.h
@@ -1,14 +1,16 @@
/*
- * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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/param_build.h>
+
/* used by speed.c */
-DSA *get_dsa(int);
+EVP_PKEY *get_dsa(int);
static unsigned char dsa512_priv[] = {
0x65, 0xe5, 0xc7, 0x38, 0x60, 0x24, 0xb5, 0x89, 0xd4, 0x9c, 0xeb, 0x4c,
@@ -211,11 +213,14 @@ typedef struct testdsa_st {
st.q_l = sizeof(dsa##bits##_q); \
} while (0)
-DSA *get_dsa(int dsa_bits)
+EVP_PKEY *get_dsa(int dsa_bits)
{
- DSA *dsa;
+ EVP_PKEY *pkey = NULL;
BIGNUM *priv_key, *pub_key, *p, *q, *g;
+ EVP_PKEY_CTX *pctx;
testdsa dsa_t;
+ OSSL_PARAM_BLD *tmpl = NULL;
+ OSSL_PARAM *params = NULL;
switch (dsa_bits) {
case 512:
@@ -231,30 +236,44 @@ DSA *get_dsa(int dsa_bits)
return NULL;
}
- if ((dsa = DSA_new()) == NULL)
+ if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL)
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)) {
+ 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;
-
- if (!DSA_set0_key(dsa, pub_key, priv_key))
+ if ((tmpl = OSSL_PARAM_BLD_new()) == NULL
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P,
+ p)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q,
+ q)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G,
+ g)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
+ priv_key)
+ || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
+ pub_key)
+ || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;
- return dsa;
- err:
- DSA_free(dsa);
+ if (EVP_PKEY_fromdata_init(pctx) <= 0
+ || EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR,
+ params) <= 0)
+ pkey = NULL;
+err:
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(tmpl);
BN_free(priv_key);
BN_free(pub_key);
BN_free(p);
BN_free(q);
BN_free(g);
- return NULL;
+ EVP_PKEY_CTX_free(pctx);
+ return pkey;
}
diff --git a/apps/testrsa.h b/apps/testrsa.h
index 1350ce54e3fb..8c3a967414c6 100644
--- a/apps/testrsa.h
+++ b/apps/testrsa.h
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
diff --git a/apps/timeouts.h b/apps/timeouts.h
index 7e606cba0b20..002852724763 100644
--- a/apps/timeouts.h
+++ b/apps/timeouts.h
@@ -1,7 +1,7 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
diff --git a/apps/ts.c b/apps/ts.c
index 66a0c810e0c3..57292e187cd2 100644
--- a/apps/ts.c
+++ b/apps/ts.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -63,60 +63,68 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
/* Verify related functions. */
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);
+ const char *CApath, const char *CAfile,
+ const char *CAstore,
+ 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,
+ const char *CAstore,
+ char *untrusted,
X509_VERIFY_PARAM *vpm);
static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
- X509_VERIFY_PARAM *vpm);
+ const char *CAstore, 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_COMMON,
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
+ OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, OPT_UNTRUSTED,
+ OPT_MD, OPT_V_ENUM, OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS ts_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"config", OPT_CONFIG, '<', "Configuration file"},
{"section", OPT_SECTION, 's', "Section to use within config file"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"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"},
+ {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"},
+ {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"},
+ {"CAstore", OPT_CASTORE, ':', "URI to trusted CA store"},
+ {"untrusted", OPT_UNTRUSTED, '<', "Extra untrusted certs"},
+ {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"},
+ {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"", OPT_MD, '-', "Any supported digest"},
+
+ OPT_SECTION("Query"),
{"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"},
+ {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"},
{"cert", OPT_CERT, '-', "Put cert request into query"},
{"in", OPT_IN, '<', "Input file"},
- {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"},
+
+ OPT_SECTION("Verify"),
+ {"verify", OPT_VERIFY, '-', "Verify a TS response"},
+ {"reply", OPT_REPLY, '-', "Generate a TS reply"},
+ {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"},
+ {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"},
{"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_R_OPTIONS,
OPT_V_OPTIONS,
- {OPT_HELP_STR, 1, '-', "\n"},
+ OPT_PROV_OPTIONS,
{NULL}
};
@@ -124,41 +132,43 @@ const OPTIONS ts_options[] = {
* 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]",
+ " openssl ts -query [-rand file...] [-config file] [-data file]",
+ " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]",
+ " [-in file] [-out file] [-text]",
+ "",
+ " openssl 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]",
+ " [-text] [-engine id]",
#else
- " [-text]",
+ " [-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']]",
+ "",
+ " openssl ts -verify -CApath dir -CAfile root-cert.pem -CAstore uri",
+ " -untrusted extra-certs.pem [-data file] [-digest hexstring]",
+ " [-queryfile request.tsq] -in response.tsr [-token_in] ...",
NULL,
};
int ts_main(int argc, char **argv)
{
CONF *conf = NULL;
- const char *CAfile = NULL, *untrusted = NULL, *prog;
+ const char *CAfile = NULL, *prog;
+ char *untrusted = NULL;
const char *configfile = default_config_file, *engine = NULL;
- const char *section = NULL;
+ const char *section = NULL, *digestname = 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 *CAstore = NULL;
+ EVP_MD *md = NULL;
OPTION_CHOICE o, mode = OPT_ERR;
int ret = 1, no_nonce = 0, cert = 0, text = 0;
int vpmtouched = 0;
@@ -208,6 +218,10 @@ int ts_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_TSPOLICY:
policy = opt_arg();
break;
@@ -253,6 +267,9 @@ int ts_main(int argc, char **argv)
case OPT_CAFILE:
CAfile = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_UNTRUSTED:
untrusted = opt_arg();
break;
@@ -260,8 +277,7 @@ int ts_main(int argc, char **argv)
engine = opt_arg();
break;
case OPT_MD:
- if (!opt_md(opt_unknown(), &md))
- goto opthelp;
+ digestname = opt_unknown();
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
@@ -270,9 +286,19 @@ int ts_main(int argc, char **argv)
break;
}
}
- if (mode == OPT_ERR || opt_num_rest() != 0)
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0 || mode == OPT_ERR)
goto opthelp;
+ if (!app_RAND_load())
+ goto end;
+
+ if (digestname != NULL) {
+ if (!opt_md(digestname, &md))
+ goto opthelp;
+ }
if (mode == OPT_REPLY && passin &&
!app_passwd(passin, NULL, &password, NULL)) {
BIO_printf(bio_err, "Error getting password.\n");
@@ -309,7 +335,7 @@ int ts_main(int argc, char **argv)
if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest))
goto opthelp;
ret = !verify_command(data, digest, queryfile, in, token_in,
- CApath, CAfile, untrusted,
+ CApath, CAfile, CAstore, untrusted,
vpmtouched ? vpm : NULL);
} else {
goto opthelp;
@@ -317,6 +343,7 @@ int ts_main(int argc, char **argv)
end:
X509_VERIFY_PARAM_free(vpm);
+ EVP_MD_free(md);
NCONF_free(conf);
OPENSSL_free(password);
return ret;
@@ -423,7 +450,7 @@ static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md,
ASN1_OBJECT *policy_obj = NULL;
ASN1_INTEGER *nonce_asn1 = NULL;
- if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL)
+ if (md == NULL && (md = EVP_get_digestbyname("sha256")) == NULL)
goto err;
if ((ts_req = TS_REQ_new()) == NULL)
goto err;
@@ -433,7 +460,7 @@ static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md,
goto err;
if ((algo = X509_ALGOR_new()) == NULL)
goto err;
- if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL)
+ if ((algo->algorithm = OBJ_nid2obj(EVP_MD_get_type(md))) == NULL)
goto err;
if ((algo->parameter = ASN1_TYPE_new()) == NULL)
goto err;
@@ -482,7 +509,7 @@ static int create_digest(BIO *input, const char *digest, const EVP_MD *md,
int rv = 0;
EVP_MD_CTX *md_ctx = NULL;
- md_value_len = EVP_MD_size(md);
+ md_value_len = EVP_MD_get_size(md);
if (md_value_len < 0)
return 0;
@@ -502,11 +529,12 @@ static int create_digest(BIO *input, const char *digest, const EVP_MD *md,
}
if (!EVP_DigestFinal(md_ctx, *md_value, NULL))
goto err;
- md_value_len = EVP_MD_size(md);
+ md_value_len = EVP_MD_get_size(md);
} else {
long digest_len;
+
*md_value = OPENSSL_hexstr2buf(digest, &digest_len);
- if (!*md_value || md_value_len != digest_len) {
+ if (*md_value == NULL || md_value_len != digest_len) {
OPENSSL_free(*md_value);
*md_value = NULL;
BIO_printf(bio_err, "bad digest, %d bytes "
@@ -817,7 +845,8 @@ static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial)
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,
+ const char *CApath, const char *CAfile,
+ const char *CAstore, char *untrusted,
X509_VERIFY_PARAM *vpm)
{
BIO *in_bio = NULL;
@@ -837,7 +866,7 @@ static int verify_command(const char *data, const char *digest, const char *quer
}
if ((verify_ctx = create_verify_ctx(data, digest, queryfile,
- CApath, CAfile, untrusted,
+ CApath, CAfile, CAstore, untrusted,
vpm)) == NULL)
goto end;
@@ -864,10 +893,12 @@ static int verify_command(const char *data, const char *digest, const char *quer
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,
+ const char *CAstore,
+ char *untrusted,
X509_VERIFY_PARAM *vpm)
{
TS_VERIFY_CTX *ctx = NULL;
+ STACK_OF(X509) *certs;
BIO *input = NULL;
TS_REQ *request = NULL;
int ret = 0;
@@ -912,14 +943,18 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE);
/* Initialising the X509_STORE object. */
- if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile, vpm))
+ if (TS_VERIFY_CTX_set_store(ctx,
+ create_cert_store(CApath, CAfile, CAstore, vpm))
== NULL)
goto err;
- /* Loading untrusted certificates. */
- if (untrusted
- && TS_VERIFY_CTS_set_certs(ctx, TS_CONF_load_certs(untrusted)) == NULL)
- goto err;
+ /* Loading any extra untrusted certificates. */
+ if (untrusted != NULL) {
+ certs = load_certs_multifile(untrusted, NULL, "extra untrusted certs",
+ vpm);
+ if (certs == NULL || TS_VERIFY_CTX_set_certs(ctx, certs) == NULL)
+ goto err;
+ }
ret = 1;
err:
@@ -933,13 +968,18 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
}
static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
- X509_VERIFY_PARAM *vpm)
+ const char *CAstore, X509_VERIFY_PARAM *vpm)
{
X509_STORE *cert_ctx = NULL;
X509_LOOKUP *lookup = NULL;
- int i;
+ OSSL_LIB_CTX *libctx = app_get0_libctx();
+ const char *propq = app_get0_propq();
cert_ctx = X509_STORE_new();
+ if (cert_ctx == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ return NULL;
+ }
X509_STORE_set_verify_cb(cert_ctx, verify_cb);
if (CApath != NULL) {
lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
@@ -947,8 +987,7 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
BIO_printf(bio_err, "memory allocation failure\n");
goto err;
}
- i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM);
- if (!i) {
+ if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) {
BIO_printf(bio_err, "Error loading directory %s\n", CApath);
goto err;
}
@@ -960,13 +999,25 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
BIO_printf(bio_err, "memory allocation failure\n");
goto err;
}
- i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM);
- if (!i) {
+ if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM, libctx,
+ propq) <= 0) {
BIO_printf(bio_err, "Error loading file %s\n", CAfile);
goto err;
}
}
+ if (CAstore != NULL) {
+ lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_store());
+ if (lookup == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ goto err;
+ }
+ if (X509_LOOKUP_load_store_ex(lookup, CAstore, libctx, propq) <= 0) {
+ BIO_printf(bio_err, "Error loading store URI %s\n", CAstore);
+ goto err;
+ }
+ }
+
if (vpm != NULL)
X509_STORE_set1_param(cert_ctx, vpm);
diff --git a/apps/tsget.in b/apps/tsget.in
index bec365e28ce5..3b5f83cf9b57 100644
--- a/apps/tsget.in
+++ b/apps/tsget.in
@@ -1,8 +1,8 @@
#!{- $config{HASHBANGPERL} -}
-# Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2002-2021 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
+# Licensed under the Apache License 2.0 (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
@@ -21,10 +21,10 @@ sub read_body {
my $return_data = "";
my $data_len = length ${$state->{data}};
if ($state->{bytes} < $data_len) {
- $data_len = $data_len - $state->{bytes};
- $data_len = $maxlength if $data_len > $maxlength;
- $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len;
- $state->{bytes} += $data_len;
+ $data_len = $data_len - $state->{bytes};
+ $data_len = $maxlength if $data_len > $maxlength;
+ $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len;
+ $state->{bytes} += $data_len;
}
return $return_data;
}
@@ -47,14 +47,14 @@ sub create_curl {
$curl->setopt(CURLOPT_VERBOSE, 1) if $options{d};
$curl->setopt(CURLOPT_FAILONERROR, 1);
$curl->setopt(CURLOPT_USERAGENT,
- "OpenTSA tsget.pl/openssl-{- $config{version} -}");
+ "OpenTSA tsget.pl/openssl-{- $config{full_version} -}");
# Options for POST method.
$curl->setopt(CURLOPT_UPLOAD, 1);
$curl->setopt(CURLOPT_CUSTOMREQUEST, "POST");
$curl->setopt(CURLOPT_HTTPHEADER,
- ["Content-Type: application/timestamp-query",
- "Accept: application/timestamp-reply,application/timestamp-response"]);
+ ["Content-Type: application/timestamp-query",
+ "Accept: application/timestamp-reply,application/timestamp-response"]);
$curl->setopt(CURLOPT_READFUNCTION, \&read_body);
$curl->setopt(CURLOPT_HEADERFUNCTION, sub { return length($_[0]); });
@@ -63,8 +63,8 @@ sub create_curl {
# SSL related options.
$curl->setopt(CURLOPT_SSLKEYTYPE, "PEM");
- $curl->setopt(CURLOPT_SSL_VERIFYPEER, 1); # Verify server's certificate.
- $curl->setopt(CURLOPT_SSL_VERIFYHOST, 2); # Check server's CN.
+ $curl->setopt(CURLOPT_SSL_VERIFYPEER, 1); # Verify server's certificate.
+ $curl->setopt(CURLOPT_SSL_VERIFYHOST, 2); # Check server's CN.
$curl->setopt(CURLOPT_SSLKEY, $options{k}) if defined($options{k});
$curl->setopt(CURLOPT_SSLKEYPASSWD, $options{p}) if defined($options{p});
$curl->setopt(CURLOPT_SSLCERT, $options{c}) if defined($options{c});
@@ -101,15 +101,15 @@ sub get_timestamp {
my $error_string;
if ($error_code != 0) {
my $http_code = $curl->getinfo(CURLINFO_HTTP_CODE);
- $error_string = "could not get timestamp";
- $error_string .= ", http code: $http_code" unless $http_code == 0;
- $error_string .= ", curl code: $error_code";
- $error_string .= " ($::error_buf)" if defined($::error_buf);
+ $error_string = "could not get timestamp";
+ $error_string .= ", http code: $http_code" unless $http_code == 0;
+ $error_string .= ", curl code: $error_code";
+ $error_string .= " ($::error_buf)" if defined($::error_buf);
} else {
my $ct = $curl->getinfo(CURLINFO_CONTENT_TYPE);
- if (lc($ct) ne "application/timestamp-reply"
- && lc($ct) ne "application/timestamp-response") {
- $error_string = "unexpected content type returned: $ct";
+ if (lc($ct) ne "application/timestamp-reply"
+ && lc($ct) ne "application/timestamp-response") {
+ $error_string = "unexpected content type returned: $ct";
}
}
return ($ts_body, $error_string);
@@ -163,15 +163,15 @@ REQUEST: foreach (@ARGV) {
# Read request.
my $body;
if ($input eq "-") {
- # Read the request from STDIN;
- $body = <STDIN>;
+ # Read the request from STDIN;
+ $body = <STDIN>;
} else {
- # Read the request from file.
+ # Read the request from file.
open INPUT, "<" . $input
- or warn("$input: could not open input file: $!\n"), next REQUEST;
+ or warn("$input: could not open input file: $!\n"), next REQUEST;
$body = <INPUT>;
close INPUT
- or warn("$input: could not close input file: $!\n"), next REQUEST;
+ or warn("$input: could not close input file: $!\n"), next REQUEST;
}
# Send request.
@@ -179,21 +179,21 @@ REQUEST: foreach (@ARGV) {
my ($ts_body, $error) = get_timestamp $curl, \$body;
if (defined($error)) {
- die "$input: fatal error: $error\n";
+ die "$input: fatal error: $error\n";
}
STDERR->printflush(", reply received") if $options{v};
# Write response.
if ($output eq "-") {
- # Write to STDOUT.
+ # Write to STDOUT.
print $ts_body;
} else {
- # Write to file.
+ # Write to file.
open OUTPUT, ">", $output
- or warn("$output: could not open output file: $!\n"), next REQUEST;
+ or warn("$output: could not open output file: $!\n"), next REQUEST;
print OUTPUT $ts_body;
close OUTPUT
- or warn("$output: could not close output file: $!\n"), next REQUEST;
+ or warn("$output: could not close output file: $!\n"), next REQUEST;
}
STDERR->printflush(", $output written.\n") if $options{v};
}
diff --git a/apps/verify.c b/apps/verify.c
index 1f9385606046..3aae931f69df 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -21,42 +21,58 @@
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, int show_chain);
+ STACK_OF(X509_CRL) *crls, int show_chain,
+ STACK_OF(OPENSSL_STRING) *opts);
static int v_verbose = 0, vflags = 0;
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
- OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE,
+ OPT_COMMON,
+ OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
+ OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN,
- OPT_V_ENUM, OPT_NAMEOPT,
- OPT_VERBOSE
+ OPT_V_ENUM, OPT_NAMEOPT, OPT_VFYOPT,
+ OPT_VERBOSE,
+ OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS verify_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
- {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"},
+
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
{"verbose", OPT_VERBOSE, '-',
"Print extra information about the operations being performed."},
- {"CApath", OPT_CAPATH, '/', "A directory of trusted certificates"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
+
+ OPT_SECTION("Certificate chain"),
+ {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"},
{"CAfile", OPT_CAFILE, '<', "A file of trusted certificates"},
+ {"CApath", OPT_CAPATH, '/', "A directory of files with trusted certificates"},
+ {"CAstore", OPT_CASTORE, ':', "URI to a store of trusted certificates"},
{"no-CAfile", OPT_NOCAFILE, '-',
- "Do not load the default certificates file"},
+ "Do not load the default trusted certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
- "Do not load certificates from the default certificates directory"},
+ "Do not load trusted certificates from the default directory"},
+ {"no-CAstore", OPT_NOCASTORE, '-',
+ "Do not load trusted certificates from the default certificates store"},
{"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"},
+ "Try downloading CRL information for certificates via their CDP entries"},
{"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
+ {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
+
+ OPT_PROV_OPTIONS,
+
+ OPT_PARAMETERS(),
+ {"cert", 0, 0, "Certificate(s) to verify (optional; stdin used otherwise)"},
{NULL}
};
@@ -65,10 +81,11 @@ int verify_main(int argc, char **argv)
ENGINE *e = NULL;
STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
STACK_OF(X509_CRL) *crls = NULL;
+ STACK_OF(OPENSSL_STRING) *vfyopts = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
- const char *prog, *CApath = NULL, *CAfile = NULL;
- int noCApath = 0, noCAfile = 0;
+ const char *prog, *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
+ int noCApath = 0, noCAfile = 0, noCAstore = 0;
int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1;
OPTION_CHOICE o;
@@ -80,24 +97,25 @@ int verify_main(int argc, char **argv)
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(verify_options);
- BIO_printf(bio_err, "Recognized usages:\n");
+ BIO_printf(bio_err, "\nRecognized certificate chain purposes:\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 *ptmp = X509_PURPOSE_get0(i);
+
+ BIO_printf(bio_err, " %-15s %s\n",
X509_PURPOSE_get0_sname(ptmp),
X509_PURPOSE_get0_name(ptmp));
}
- BIO_printf(bio_err, "Recognized verify names:\n");
+ BIO_printf(bio_err, "Recognized certificate policy 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",
+ const X509_VERIFY_PARAM *vptmp = X509_VERIFY_PARAM_get0(i);
+
+ BIO_printf(bio_err, " %s\n",
X509_VERIFY_PARAM_get0_name(vptmp));
}
ret = 0;
@@ -113,15 +131,21 @@ int verify_main(int argc, char **argv)
case OPT_CAFILE:
CAfile = opt_arg();
break;
+ case OPT_CASTORE:
+ CAstore = opt_arg();
+ break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
+ case OPT_NOCASTORE:
+ noCAstore = 1;
+ break;
case OPT_UNTRUSTED:
/* Zero or more times */
- if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL,
+ if (!load_certs(opt_arg(), 0, &untrusted, NULL,
"untrusted certificates"))
goto end;
break;
@@ -129,14 +153,13 @@ int verify_main(int argc, char **argv)
/* Zero or more times */
noCAfile = 1;
noCApath = 1;
- if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL,
- "trusted certificates"))
+ noCAstore = 1;
+ if (!load_certs(opt_arg(), 0, &trusted, NULL, "trusted certificates"))
goto end;
break;
case OPT_CRLFILE:
/* Zero or more times */
- if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL,
- "other CRLs"))
+ if (!load_crls(opt_arg(), &crls, NULL, "other CRLs"))
goto end;
break;
case OPT_CRL_DOWNLOAD:
@@ -155,21 +178,36 @@ int verify_main(int argc, char **argv)
if (!set_nameopt(opt_arg()))
goto end;
break;
+ case OPT_VFYOPT:
+ if (!vfyopts)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
+ goto opthelp;
+ break;
case OPT_VERBOSE:
v_verbose = 1;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
}
}
+
+ /* Extra arguments are certificates to verify. */
argc = opt_num_rest();
argv = opt_rest();
- if (trusted != NULL && (CAfile || CApath)) {
+
+ if (trusted != NULL
+ && (CAfile != NULL || CApath != NULL || CAstore != NULL)) {
BIO_printf(bio_err,
- "%s: Cannot use -trusted with -CAfile or -CApath\n",
+ "%s: Cannot use -trusted with -CAfile, -CApath or -CAstore\n",
prog);
goto end;
}
- if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+ CAstore, noCAstore)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, cb);
@@ -183,12 +221,13 @@ int verify_main(int argc, char **argv)
ret = 0;
if (argc < 1) {
- if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1)
+ if (check(store, NULL, untrusted, trusted, crls, show_chain,
+ vfyopts) != 1)
ret = -1;
} else {
for (i = 0; i < argc; i++)
- if (check(store, argv[i], untrusted, trusted, crls,
- show_chain) != 1)
+ if (check(store, argv[i], untrusted, trusted, crls, show_chain,
+ vfyopts) != 1)
ret = -1;
}
@@ -198,13 +237,15 @@ int verify_main(int argc, char **argv)
sk_X509_pop_free(untrusted, X509_free);
sk_X509_pop_free(trusted, X509_free);
sk_X509_CRL_pop_free(crls, X509_CRL_free);
+ sk_OPENSSL_STRING_free(vfyopts);
release_engine(e);
return (ret < 0 ? 2 : ret);
}
static int check(X509_STORE *ctx, const char *file,
STACK_OF(X509) *uchain, STACK_OF(X509) *tchain,
- STACK_OF(X509_CRL) *crls, int show_chain)
+ STACK_OF(X509_CRL) *crls, int show_chain,
+ STACK_OF(OPENSSL_STRING) *opts)
{
X509 *x = NULL;
int i = 0, ret = 0;
@@ -212,22 +253,35 @@ static int check(X509_STORE *ctx, const char *file,
STACK_OF(X509) *chain = NULL;
int num_untrusted;
- x = load_cert(file, FORMAT_PEM, "certificate file");
+ x = load_cert(file, FORMAT_UNDEF, "certificate file");
if (x == NULL)
goto end;
+ if (opts != NULL) {
+ for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
+ char *opt = sk_OPENSSL_STRING_value(opts, i);
+ if (x509_ctrl_string(x, opt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
+ ERR_print_errors(bio_err);
+ X509_free(x);
+ return 0;
+ }
+ }
+ }
+
csc = X509_STORE_CTX_new();
if (csc == NULL) {
- printf("error %s: X.509 store context allocation failed\n",
- (file == NULL) ? "stdin" : file);
+ BIO_printf(bio_err, "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)) {
X509_STORE_CTX_free(csc);
- printf("error %s: X.509 store context initialization failed\n",
- (file == NULL) ? "stdin" : file);
+ BIO_printf(bio_err,
+ "error %s: X.509 store context initialization failed\n",
+ (file == NULL) ? "stdin" : file);
goto end;
}
if (tchain != NULL)
@@ -236,28 +290,30 @@ static int check(X509_STORE *ctx, const char *file,
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);
+ BIO_printf(bio_out, "%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");
+ BIO_printf(bio_out, "Chain:\n");
for (j = 0; j < sk_X509_num(chain); j++) {
X509 *cert = sk_X509_value(chain, j);
- printf("depth=%d: ", j);
+ BIO_printf(bio_out, "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");
+ BIO_printf(bio_out, " (untrusted)");
+ BIO_printf(bio_out, "\n");
}
sk_X509_pop_free(chain, X509_free);
}
} else {
- printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file);
+ BIO_printf(bio_err,
+ "error %s: verification failed\n",
+ (file == NULL) ? "stdin" : file);
}
X509_STORE_CTX_free(csc);
@@ -298,19 +354,34 @@ static int cb(int ok, X509_STORE_CTX *ctx)
policies_print(ctx);
/* fall thru */
case X509_V_ERR_CERT_HAS_EXPIRED:
- /* Continue even if the leaf is a self signed cert */
+ /* Continue even if the leaf is a self-signed cert */
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
/* Continue after extension errors too */
case X509_V_ERR_INVALID_CA:
case X509_V_ERR_INVALID_NON_CA:
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
- case X509_V_ERR_INVALID_PURPOSE:
case X509_V_ERR_CRL_HAS_EXPIRED:
case X509_V_ERR_CRL_NOT_YET_VALID:
case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+ /* errors due to strict conformance checking (-x509_strict) */
+ case X509_V_ERR_INVALID_PURPOSE:
+ case X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA:
+ case X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN:
+ case X509_V_ERR_CA_BCONS_NOT_CRITICAL:
+ case X509_V_ERR_CA_CERT_MISSING_KEY_USAGE:
+ case X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA:
+ case X509_V_ERR_ISSUER_NAME_EMPTY:
+ case X509_V_ERR_SUBJECT_NAME_EMPTY:
+ case X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL:
+ case X509_V_ERR_EMPTY_SUBJECT_ALT_NAME:
+ case X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY:
+ case X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL:
+ case X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL:
+ case X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER:
+ case X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER:
+ case X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3:
ok = 1;
}
-
return ok;
}
diff --git a/apps/version.c b/apps/version.c
index 2aca1636152b..cab17a46bf18 100644
--- a/apps/version.c
+++ b/apps/version.c
@@ -1,7 +1,7 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -15,56 +15,36 @@
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/bn.h>
-#ifndef OPENSSL_NO_MD2
-# include <openssl/md2.h>
-#endif
-#ifndef OPENSSL_NO_RC4
-# include <openssl/rc4.h>
-#endif
-#ifndef OPENSSL_NO_DES
-# include <openssl/des.h>
-#endif
-#ifndef OPENSSL_NO_IDEA
-# include <openssl/idea.h>
-#endif
-#ifndef OPENSSL_NO_BF
-# include <openssl/blowfish.h>
-#endif
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
+ OPT_COMMON,
+ OPT_B, OPT_D, OPT_E, OPT_M, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R, OPT_C
} OPTION_CHOICE;
const OPTIONS version_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ OPT_SECTION("Output"),
{"a", OPT_A, '-', "Show all data"},
{"b", OPT_B, '-', "Show build date"},
{"d", OPT_D, '-', "Show configuration directory"},
{"e", OPT_E, '-', "Show engines directory"},
+ {"m", OPT_M, '-', "Show modules 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"},
+ {"c", OPT_C, '-', "Show CPU settings info"},
{NULL}
};
-#if defined(OPENSSL_RAND_SEED_DEVRANDOM) || defined(OPENSSL_RAND_SEED_EGD)
-static void printlist(const char *prefix, const char **dev)
-{
- printf("%s (", prefix);
- for ( ; *dev != NULL; dev++)
- printf(" \"%s\"", *dev);
- printf(" )");
-}
-#endif
-
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;
+ int engdir = 0, moddir = 0, cpuinfo = 0;
char *prog;
OPTION_CHOICE o;
@@ -89,6 +69,9 @@ opthelp:
case OPT_E:
dirty = engdir = 1;
break;
+ case OPT_M:
+ dirty = moddir = 1;
+ break;
case OPT_F:
dirty = cflags = 1;
break;
@@ -104,48 +87,35 @@ opthelp:
case OPT_V:
dirty = version = 1;
break;
+ case OPT_C:
+ dirty = cpuinfo = 1;
+ break;
case OPT_A:
- seed = options = cflags = version = date = platform = dir = engdir
+ seed = options = cflags = version = date = platform
+ = dir = engdir = moddir = cpuinfo
= 1;
break;
}
}
- if (opt_num_rest() != 0) {
- BIO_printf(bio_err, "Extra parameters given.\n");
+
+ /* No extra arguments. */
+ argc = opt_num_rest();
+ if (argc != 0)
goto opthelp;
- }
+
if (!dirty)
version = 1;
- if (version) {
- if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER)
- printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
- else
- printf("%s (Library: %s)\n",
- OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
- }
+ if (version)
+ printf("%s (Library: %s)\n",
+ OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
if (date)
printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
if (platform)
printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM));
if (options) {
- printf("options: ");
- printf("%s ", BN_options());
-#ifndef OPENSSL_NO_MD2
- printf("%s ", MD2_options());
-#endif
-#ifndef OPENSSL_NO_RC4
- printf("%s ", RC4_options());
-#endif
-#ifndef OPENSSL_NO_DES
- printf("%s ", DES_options());
-#endif
-#ifndef OPENSSL_NO_IDEA
- printf("%s ", IDEA_options());
-#endif
-#ifndef OPENSSL_NO_BF
- printf("%s ", BF_options());
-#endif
+ printf("options: ");
+ printf(" %s", BN_options());
printf("\n");
}
if (cflags)
@@ -154,41 +124,28 @@ opthelp:
printf("%s\n", OpenSSL_version(OPENSSL_DIR));
if (engdir)
printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR));
+ if (moddir)
+ printf("%s\n", OpenSSL_version(OPENSSL_MODULES_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");
+ const char *src = OPENSSL_info(OPENSSL_INFO_SEED_SOURCE);
+ printf("Seeding source: %s\n", src ? src : "N/A");
}
+ if (cpuinfo)
+ printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO));
ret = 0;
end:
return ret;
}
+
+
+#if defined(__TANDEM) && defined(OPENSSL_VPROC)
+/*
+ * Define a VPROC function for the openssl program.
+ * This is used by platform version identification tools.
+ * Do not inline this procedure or make it static.
+ */
+# define OPENSSL_VPROC_STRING_(x) x##_OPENSSL
+# define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x)
+# define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC)
+void OPENSSL_VPROC_FUNC(void) {}
+#endif
diff --git a/apps/x509.c b/apps/x509.c
index 8d4bf71a03ee..a919d787457c 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -1,7 +1,7 @@
/*
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (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
@@ -21,162 +21,271 @@
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
-#ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-#endif
+#include <openssl/rsa.h>
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
#undef POSTFIX
#define POSTFIX ".srl"
-#define DEF_DAYS 30
+#define DEFAULT_DAYS 30 /* default cert validity period in days */
+#define UNSET_DAYS -2 /* -1 is used for testing expiration checks */
+#define EXT_COPY_UNSET -1
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, 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, const char *serialfile,
- int create, int days, int clrext, CONF *conf,
- const char *section, ASN1_INTEGER *sno, int reqfile,
- int preserve_dates);
+static ASN1_INTEGER *x509_load_serial(const char *CAfile,
+ const char *serialfile, int create);
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
-static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts);
+static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names);
typedef enum OPTION_choice {
- OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMMON,
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_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
+ OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY,
+ OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ,
+ OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT,
+ 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_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS,
OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
- OPT_R_ENUM, OPT_EXT
+ OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT
} OPTION_CHOICE;
const OPTIONS x509_options[] = {
+ OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
+
+ {"in", OPT_IN, '<',
+ "Certificate input, or CSR input file with -req (default stdin)"},
+ {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"},
+ {"new", OPT_NEW, '-', "Generate a certificate from scratch"},
+ {"x509toreq", OPT_X509TOREQ, '-',
+ "Output a certification request (rather than a certificate)"},
+ {"req", OPT_REQ, '-', "Input is a CSR file (rather than a certificate)"},
+ {"copy_extensions", OPT_COPY_EXTENSIONS, 's',
+ "copy extensions when converting from CSR to x509 or vice versa"},
{"inform", OPT_INFORM, 'f',
- "Input format - default PEM (one of DER or PEM)"},
- {"in", OPT_IN, '<', "Input file - default stdin"},
- {"outform", OPT_OUTFORM, 'f',
- "Output format - default PEM (one of DER or PEM)"},
+ "CSR input file format (DER or PEM) - default PEM"},
+ {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"},
+ {"key", OPT_KEY, 's',
+ "Key for signing, and to include unless using -force_pubkey"},
+ {"signkey", OPT_SIGNKEY, 's',
+ "Same as -key"},
+ {"keyform", OPT_KEYFORM, 'E',
+ "Key input format (ENGINE, other values ignored)"},
{"out", OPT_OUT, '>', "Output file - default stdout"},
- {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
- {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"},
+ {"outform", OPT_OUTFORM, 'f',
+ "Output format (DER or PEM) - default PEM"},
+ {"nocert", OPT_NOCERT, '-',
+ "No cert output (except for requested printing)"},
+ {"noout", OPT_NOOUT, '-', "No output (except for requested printing)"},
+
+ OPT_SECTION("Certificate printing"),
+ {"text", OPT_TEXT, '-', "Print the certificate in text form"},
+ {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."},
+ {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"},
+ {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"},
+ {"alias", OPT_ALIAS, '-', "Print certificate alias"},
{"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"},
+ {"startdate", OPT_STARTDATE, '-', "Print the notBefore field"},
+ {"enddate", OPT_ENDDATE, '-', "Print the notAfter field"},
+ {"dates", OPT_DATES, '-', "Print both notBefore and notAfter fields"},
{"subject", OPT_SUBJECT, '-', "Print subject DN"},
{"issuer", OPT_ISSUER, '-', "Print issuer DN"},
+ {"nameopt", OPT_NAMEOPT, 's',
+ "Certificate subject/issuer name printing options"},
{"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"},
+ {"hash", OPT_HASH, '-', "Synonym for -subject_hash (for backward compat)"},
+ {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
+#ifndef OPENSSL_NO_MD5
+ {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
+ "Print old-style (MD5) subject hash value"},
+#endif
+ {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
+#ifndef OPENSSL_NO_MD5
+ {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
+ "Print old-style (MD5) issuer hash value"},
+#endif
+ {"ext", OPT_EXT, 's',
+ "Restrict which X.509 extensions to print and/or copy"},
{"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"},
+ {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
+ {"pubkey", OPT_PUBKEY, '-', "Print the public key in PEM format"},
+ {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
+
+ OPT_SECTION("Certificate checking"),
{"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, 's', "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"},
+ "Check whether cert expires in the next arg seconds"},
+ {OPT_MORE_STR, 1, 1, "Exit 1 (failure) if so, 0 if not"},
{"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, 'E', "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"},
+
+ OPT_SECTION("Certificate output"),
+ {"set_serial", OPT_SET_SERIAL, 's',
+ "Serial number to use, overrides -CAserial"},
+ {"next_serial", OPT_NEXT_SERIAL, '-',
+ "Increment current certificate serial number"},
+ {"days", OPT_DAYS, 'n',
+ "Number of days until newly generated certificate expires - default 30"},
+ {"preserve_dates", OPT_PRESERVE_DATES, '-',
+ "Preserve existing validity dates"},
+ {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
+ {"force_pubkey", OPT_FORCE_PUBKEY, '<',
+ "Place the given key in new certificate"},
+ {"clrext", OPT_CLREXT, '-',
+ "Do not take over any extensions from the source certificate or request"},
+ {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"},
+ {"extensions", OPT_EXTENSIONS, 's',
+ "Section of extfile to use - default: unnamed section"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter, in n:v form"},
+ {"badsig", OPT_BADSIG, '-',
+ "Corrupt last byte of certificate signature (for test)"},
+ {"", OPT_MD, '-', "Any supported digest, used for signing and printing"},
+
+ OPT_SECTION("Micro-CA"),
+ {"CA", OPT_CA, '<',
+ "Use the given CA certificate, conflicts with -key"},
+ {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"},
+ {"CAkey", OPT_CAKEY, 's', "The corresponding CA key; default is -CA arg"},
+ {"CAkeyform", OPT_CAKEYFORM, 'E',
+ "CA key format (ENGINE, other values ignored)"},
+ {"CAserial", OPT_CASERIAL, 's',
+ "File that keeps track of CA-generated serial number"},
+ {"CAcreateserial", OPT_CACREATESERIAL, '-',
+ "Create CA serial number file if it does not exist"},
+
+ OPT_SECTION("Certificate trust output"),
+ {"trustout", OPT_TRUSTOUT, '-', "Mark certificate PEM output as trusted"},
+ {"setalias", OPT_SETALIAS, 's', "Set certificate alias (nickname)"},
+ {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
+ {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
{"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) subject hash value"},
- {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
- "Print old-style (MD5) issuer hash value"},
-#endif
+ {"addreject", OPT_ADDREJECT, 's',
+ "Reject certificate for a given purpose"},
+
+ OPT_R_OPTIONS,
#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"},
+ OPT_PROV_OPTIONS,
{NULL}
};
+static void warn_copying(ASN1_OBJECT *excluded, const char *names)
+{
+ const char *sn = OBJ_nid2sn(OBJ_obj2nid(excluded));
+
+ if (names != NULL && strstr(names, sn) != NULL)
+ BIO_printf(bio_err,
+ "Warning: -ext should not specify copying %s extension to CSR; ignoring this\n",
+ sn);
+}
+
+static X509_REQ *x509_to_req(X509 *cert, int ext_copy, const char *names)
+{
+ const STACK_OF(X509_EXTENSION) *cert_exts = X509_get0_extensions(cert);
+ int i, n = sk_X509_EXTENSION_num(cert_exts /* may be NULL */);
+ ASN1_OBJECT *skid = OBJ_nid2obj(NID_subject_key_identifier);
+ ASN1_OBJECT *akid = OBJ_nid2obj(NID_authority_key_identifier);
+ STACK_OF(X509_EXTENSION) *exts;
+ X509_REQ *req = X509_to_X509_REQ(cert, NULL, NULL);
+
+ if (req == NULL)
+ return NULL;
+
+ /*
+ * Filter out SKID and AKID extensions, which make no sense in a CSR.
+ * If names is not NULL, copy only those extensions listed there.
+ */
+ warn_copying(skid, names);
+ warn_copying(akid, names);
+ if ((exts = sk_X509_EXTENSION_new_reserve(NULL, n)) == NULL)
+ goto err;
+ for (i = 0; i < n; i++) {
+ X509_EXTENSION *ex = sk_X509_EXTENSION_value(cert_exts, i);
+ ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
+
+ if (OBJ_cmp(obj, skid) != 0 && OBJ_cmp(obj, akid) != 0
+ && !sk_X509_EXTENSION_push(exts, ex))
+ goto err;
+ }
+
+ if (sk_X509_EXTENSION_num(exts) > 0) {
+ if (ext_copy != EXT_COPY_UNSET && ext_copy != EXT_COPY_NONE
+ && !X509_REQ_add_extensions(req, exts)) {
+ BIO_printf(bio_err, "Error copying extensions from certificate\n");
+ goto err;
+ }
+ }
+ sk_X509_EXTENSION_free(exts);
+ return req;
+
+ err:
+ sk_X509_EXTENSION_free(exts);
+ X509_REQ_free(req);
+ return NULL;
+}
+
+static int self_signed(X509_STORE *ctx, X509 *cert)
+{
+ X509_STORE_CTX *xsc = X509_STORE_CTX_new();
+ int ret = 0;
+
+ if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, cert, NULL)) {
+ BIO_printf(bio_err, "Error initialising X509 store\n");
+ } else {
+ X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
+ ret = X509_verify_cert(xsc) > 0;
+ }
+ X509_STORE_CTX_free(xsc);
+ return ret;
+}
+
int x509_main(int argc, char **argv)
{
ASN1_INTEGER *sno = NULL;
ASN1_OBJECT *objtmp = NULL;
BIO *out = NULL;
CONF *extconf = NULL;
- EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
+ int ext_copy = EXT_COPY_UNSET;
+ X509V3_CTX ext_ctx;
+ EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL;
+ EVP_PKEY *pkey;
+ int newcert = 0;
+ char *subj = NULL, *digest = NULL;
+ X509_NAME *fsubj = NULL;
+ const unsigned long chtype = MBSTRING_ASC;
+ const int multirdn = 1;
STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
- STACK_OF(OPENSSL_STRING) *sigopts = NULL;
- X509 *x = NULL, *xca = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
+ X509 *x = NULL, *xca = NULL, *issuer_cert;
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 *CAkeyfile = NULL, *CAserial = NULL, *pubkeyfile = NULL, *alias = NULL;
+ char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
+ char *ext_names = NULL;
char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
- char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
+ char *infile = NULL, *outfile = NULL, *privkeyfile = NULL, *CAfile = NULL;
char *prog;
- int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
- int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
+ int days = UNSET_DAYS; /* not explicitly set */
+ int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0;
+ int CAformat = FORMAT_UNDEF, CAkeyformat = FORMAT_UNDEF;
+ unsigned long dateopt = ASN1_DTFLGS_RFC822;
int fingerprint = 0, reqfile = 0, checkend = 0;
- int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
+ int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF;
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 noout = 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 ret = 1, i, j, 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;
@@ -206,7 +315,7 @@ int x509_main(int argc, char **argv)
ret = 0;
goto end;
case OPT_INFORM:
- if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
goto opthelp;
break;
case OPT_IN:
@@ -217,15 +326,15 @@ int x509_main(int argc, char **argv)
goto opthelp;
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_CAFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAformat))
goto opthelp;
break;
case OPT_CAKEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &CAkeyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
goto opthelp;
break;
case OPT_OUT:
@@ -235,16 +344,40 @@ int x509_main(int argc, char **argv)
reqfile = 1;
break;
+ case OPT_DATEOPT:
+ if (!set_dateopt(&dateopt, opt_arg())) {
+ BIO_printf(bio_err,
+ "Invalid date format: %s\n", opt_arg());
+ goto end;
+ }
+ break;
+ case OPT_COPY_EXTENSIONS:
+ if (!set_ext_copy(&ext_copy, opt_arg())) {
+ BIO_printf(bio_err,
+ "Invalid extension copy option: %s\n", opt_arg());
+ goto end;
+ }
+ break;
+
case OPT_SIGOPT:
if (!sigopts)
sigopts = sk_OPENSSL_STRING_new_null();
if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto opthelp;
break;
- case OPT_DAYS:
- if (preserve_dates)
+ case OPT_VFYOPT:
+ if (!vfyopts)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
goto opthelp;
+ break;
+ case OPT_DAYS:
days = atoi(opt_arg());
+ if (days < -1) {
+ BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
+ prog);
+ goto end;
+ }
break;
case OPT_PASSIN:
passinarg = opt_arg();
@@ -256,16 +389,19 @@ int x509_main(int argc, char **argv)
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_EXTENSIONS:
extsect = opt_arg();
break;
+ case OPT_KEY:
case OPT_SIGNKEY:
- keyfile = opt_arg();
- sign_flag = ++num;
+ privkeyfile = opt_arg();
break;
case OPT_CA:
CAfile = opt_arg();
- CA_flag = ++num;
break;
case OPT_CAKEY:
CAkeyfile = opt_arg();
@@ -281,34 +417,35 @@ int x509_main(int argc, char **argv)
if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
goto opthelp;
break;
+ case OPT_NEW:
+ newcert = 1;
+ break;
case OPT_FORCE_PUBKEY:
- fkeyfile = opt_arg();
+ pubkeyfile = opt_arg();
+ break;
+ case OPT_SUBJ:
+ subj = opt_arg();
break;
case OPT_ADDTRUST:
+ if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
+ goto end;
if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
- BIO_printf(bio_err,
- "%s: Invalid trust object value %s\n",
+ 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;
break;
case OPT_ADDREJECT:
+ if (reject == NULL && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
+ goto end;
if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
- BIO_printf(bio_err,
- "%s: Invalid reject object value %s\n",
+ BIO_printf(bio_err, "%s: Invalid reject object value %s\n",
prog, opt_arg());
goto opthelp;
}
- if (reject == NULL
- && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
- goto end;
sk_ASN1_OBJECT_push(reject, objtmp);
- objtmp = NULL;
trustout = 1;
break;
case OPT_SETALIAS:
@@ -326,9 +463,6 @@ int x509_main(int argc, char **argv)
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
- case OPT_C:
- C = ++num;
- break;
case OPT_EMAIL:
email = ++num;
break;
@@ -345,10 +479,10 @@ int x509_main(int argc, char **argv)
modulus = ++num;
break;
case OPT_PUBKEY:
- pubkey = ++num;
+ print_pubkey = ++num;
break;
case OPT_X509TOREQ:
- x509req = ++num;
+ x509toreq = 1;
break;
case OPT_TEXT:
text = ++num;
@@ -382,7 +516,7 @@ int x509_main(int argc, char **argv)
break;
case OPT_EXT:
ext = ++num;
- exts = opt_arg();
+ ext_names = opt_arg();
break;
case OPT_NOCERT:
nocert = 1;
@@ -430,12 +564,12 @@ int x509_main(int argc, char **argv)
case OPT_CHECKEND:
checkend = 1;
{
- intmax_t temp = 0;
- if (!opt_imax(opt_arg(), &temp))
+ ossl_intmax_t temp = 0;
+ if (!opt_intmax(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",
+ if ((ossl_intmax_t)checkoffset != temp) {
+ BIO_printf(bio_err, "%s: Checkend time out of range %s\n",
prog, opt_arg());
goto opthelp;
}
@@ -451,48 +585,103 @@ int x509_main(int argc, char **argv)
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;
+ digest = opt_unknown();
+ break;
}
}
+
+ /* No extra arguments. */
argc = opt_num_rest();
- argv = opt_rest();
- if (argc != 0) {
- BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
+ if (argc != 0)
goto opthelp;
+
+ if (!app_RAND_load())
+ goto end;
+
+ if (preserve_dates && days != UNSET_DAYS) {
+ BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n");
+ goto end;
}
+ if (days == UNSET_DAYS)
+ days = DEFAULT_DAYS;
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
- if (!X509_STORE_set_default_paths(ctx)) {
- ERR_print_errors(bio_err);
+ if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(),
+ app_get0_propq()))
+ goto end;
+
+ if (newcert && infile != NULL) {
+ BIO_printf(bio_err, "The -in option cannot be used with -new\n");
+ goto end;
+ }
+ if (newcert && reqfile) {
+ BIO_printf(bio_err,
+ "The -req option cannot be used with -new\n");
goto end;
}
+ if (privkeyfile != NULL) {
+ privkey = load_key(privkeyfile, keyformat, 0, passin, e, "private key");
+ if (privkey == NULL)
+ goto end;
+ }
+ if (pubkeyfile != NULL) {
+ if ((pubkey = load_pubkey(pubkeyfile, keyformat, 0, NULL, e,
+ "explicitly set public key")) == NULL)
+ goto end;
+ }
- if (fkeyfile != NULL) {
- fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
- if (fkey == NULL)
+ if (newcert) {
+ if (subj == NULL) {
+ BIO_printf(bio_err,
+ "The -new option requires a subject to be set using -subj\n");
goto end;
+ }
+ if (privkeyfile == NULL && pubkeyfile == NULL) {
+ BIO_printf(bio_err,
+ "The -new option requires using the -key or -force_pubkey option\n");
+ goto end;
+ }
}
+ if (subj != NULL
+ && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
+ goto end;
- if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
+ if (CAkeyfile == NULL)
CAkeyfile = CAfile;
- } else if ((CA_flag) && (CAkeyfile == NULL)) {
- BIO_printf(bio_err,
- "need to specify a CAkey if using the CA command\n");
- goto end;
+ if (CAfile != NULL) {
+ if (privkeyfile != NULL) {
+ BIO_printf(bio_err, "Cannot use both -key/-signkey and -CA option\n");
+ goto end;
+ }
+ } else {
+#define WARN_NO_CA(opt) BIO_printf(bio_err, \
+ "Warning: ignoring " opt " option since -CA option is not given\n");
+ if (CAkeyfile != NULL)
+ WARN_NO_CA("-CAkey");
+ if (CAkeyformat != FORMAT_UNDEF)
+ WARN_NO_CA("-CAkeyform");
+ if (CAformat != FORMAT_UNDEF)
+ WARN_NO_CA("-CAform");
+ if (CAserial != NULL)
+ WARN_NO_CA("-CAserial");
+ if (CA_createserial)
+ WARN_NO_CA("-CAcreateserial");
}
- if (extfile != NULL) {
+ if (extfile == NULL) {
+ if (extsect != NULL)
+ BIO_printf(bio_err,
+ "Warning: ignoring -extensions option without -extfile\n");
+ } else {
X509V3_CTX ctx2;
+
if ((extconf = app_load_config(extfile)) == NULL)
goto end;
if (extsect == NULL) {
@@ -506,92 +695,79 @@ int x509_main(int argc, char **argv)
X509V3_set_nconf(&ctx2, extconf);
if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
BIO_printf(bio_err,
- "Error Loading extension section %s\n", extsect);
- ERR_print_errors(bio_err);
+ "Error checking extension section %s\n", extsect);
goto end;
}
}
if (reqfile) {
- EVP_PKEY *pkey;
- BIO *in;
-
- if (!sign_flag && !CA_flag) {
- BIO_printf(bio_err, "We need a private key to sign with\n");
+ req = load_csr(infile, informat, "certificate request input");
+ if (req == NULL)
goto end;
- }
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
- goto end;
- req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
- BIO_free(in);
-
- if (req == NULL) {
- ERR_print_errors(bio_err);
- goto end;
- }
if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
- BIO_printf(bio_err, "error unpacking public key\n");
+ BIO_printf(bio_err, "Error unpacking public key from CSR\n");
goto end;
}
- i = X509_REQ_verify(req, pkey);
- if (i < 0) {
- BIO_printf(bio_err, "Signature verification error\n");
- ERR_print_errors(bio_err);
+ i = do_X509_REQ_verify(req, pkey, vfyopts);
+ if (i <= 0) {
+ BIO_printf(bio_err, i < 0
+ ? "Error while verifying certificate request self-signature\n"
+ : "Certificate request self-signature did not match the contents\n");
goto end;
}
- if (i == 0) {
+ BIO_printf(bio_err, "Certificate request self-signature ok\n");
+
+ print_name(bio_err, "subject=", X509_REQ_get_subject_name(req));
+ } else if (!x509toreq && ext_copy != EXT_COPY_UNSET) {
+ BIO_printf(bio_err, "Warning: ignoring -copy_extensions since neither -x509toreq nor -req is given\n");
+ }
+
+ if (reqfile || newcert) {
+ if (preserve_dates)
BIO_printf(bio_err,
- "Signature did not match the certificate request\n");
+ "Warning: ignoring -preserve_dates option with -req or -new\n");
+ preserve_dates = 0;
+ if (privkeyfile == NULL && CAkeyfile == NULL) {
+ BIO_printf(bio_err,
+ "We need a private key to sign with, use -key or -CAkey or -CA with private key\n");
goto end;
- } else {
- BIO_printf(bio_err, "Signature ok\n");
}
-
- print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
- get_nameopt());
-
- if ((x = X509_new()) == NULL)
+ if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
goto end;
-
- if (sno == NULL) {
+ if (CAfile == NULL && sno == NULL) {
sno = ASN1_INTEGER_new();
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)) {
- goto end;
}
-
- 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 (!set_cert_times(x, NULL, NULL, days))
- goto end;
-
- if (fkey != NULL) {
- X509_set_pubkey(x, fkey);
- } else {
- pkey = X509_REQ_get0_pubkey(req);
- X509_set_pubkey(x, pkey);
+ if (req != NULL && ext_copy != EXT_COPY_UNSET) {
+ if (clrext && ext_copy != EXT_COPY_NONE) {
+ BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n");
+ goto end;
+ } else if (!copy_extensions(x, req, ext_copy)) {
+ BIO_printf(bio_err, "Error copying extensions from request\n");
+ goto end;
+ }
}
} else {
- x = load_cert(infile, informat, "Certificate");
+ x = load_cert_pass(infile, informat, 1, passin, "certificate");
+ if (x == NULL)
+ goto end;
}
-
- if (x == NULL)
+ if ((fsubj != NULL || req != NULL)
+ && !X509_set_subject_name(x, fsubj != NULL ? fsubj :
+ X509_REQ_get_subject_name(req)))
goto end;
- if (CA_flag) {
- xca = load_cert(CAfile, CAformat, "CA Certificate");
+ if ((pubkey != NULL || privkey != NULL || req != NULL)
+ && !X509_set_pubkey(x, pubkey != NULL ? pubkey :
+ privkey != NULL ? privkey :
+ X509_REQ_get0_pubkey(req)))
+ goto end;
+
+ if (CAfile != NULL) {
+ xca = load_cert_pass(CAfile, CAformat, 1, passin, "CA certificate");
if (xca == NULL)
goto end;
- if (reqfile && !X509_set_issuer_name(x, X509_get_subject_name(xca)))
- goto end;
}
out = bio_open_default(outfile, 'w', outformat);
@@ -610,21 +786,120 @@ int x509_main(int argc, char **argv)
X509_reject_clear(x);
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;
+ for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
+ X509_add1_trust_object(x, sk_ASN1_OBJECT_value(trust, i));
}
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);
+ for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
+ X509_add1_reject_object(x, sk_ASN1_OBJECT_value(reject, i));
+ }
+
+ if (clrext && ext_names != NULL)
+ BIO_printf(bio_err, "Warning: Ignoring -ext since -clrext is given\n");
+ for (i = X509_get_ext_count(x) - 1; i >= 0; i--) {
+ X509_EXTENSION *ex = X509_get_ext(x, i);
+ const char *sn = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ex)));
+
+ if (clrext || (ext_names != NULL && strstr(ext_names, sn) == NULL))
+ X509_EXTENSION_free(X509_delete_ext(x, i));
+ }
+
+ issuer_cert = x;
+ if (CAfile != NULL) {
+ issuer_cert = xca;
+ if (sno == NULL)
+ sno = x509_load_serial(CAfile, CAserial, CA_createserial);
+ if (sno == NULL)
+ goto end;
+ if (!x509toreq && !reqfile && !newcert && !self_signed(ctx, x))
+ goto end;
+ }
+
+ if (sno != NULL && !X509_set_serialNumber(x, sno))
+ goto end;
+
+ if (reqfile || newcert || privkey != NULL || CAfile != NULL) {
+ if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
+ goto end;
+ if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
+ goto end;
+ }
+
+ X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE);
+ /* prepare fallback for AKID, but only if issuer cert equals subject cert */
+ if (CAfile == NULL) {
+ if (!X509V3_set_issuer_pkey(&ext_ctx, privkey))
+ goto end;
+ }
+ if (extconf != NULL && !x509toreq) {
+ X509V3_set_nconf(&ext_ctx, extconf);
+ if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) {
+ BIO_printf(bio_err,
+ "Error adding extensions from section %s\n", extsect);
+ goto end;
}
- objtmp = NULL;
}
+ /* At this point the contents of the certificate x have been finished. */
+
+ pkey = X509_get0_pubkey(x);
+ if ((print_pubkey != 0 || modulus != 0) && pkey == NULL) {
+ BIO_printf(bio_err, "Error getting public key\n");
+ goto end;
+ }
+
+ if (x509toreq) { /* also works in conjunction with -req */
+ if (privkey == NULL) {
+ BIO_printf(bio_err, "Must specify request signing key using -key\n");
+ goto end;
+ }
+ if (clrext && ext_copy != EXT_COPY_NONE) {
+ BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n");
+ goto end;
+ }
+ if ((rq = x509_to_req(x, ext_copy, ext_names)) == NULL)
+ goto end;
+ if (extconf != NULL) {
+ X509V3_set_nconf(&ext_ctx, extconf);
+ if (!X509V3_EXT_REQ_add_nconf(extconf, &ext_ctx, extsect, rq)) {
+ BIO_printf(bio_err,
+ "Error adding request extensions from section %s\n", extsect);
+ goto end;
+ }
+ }
+ if (!do_X509_REQ_sign(rq, privkey, digest, sigopts))
+ goto end;
+ if (!noout) {
+ if (outformat == FORMAT_ASN1) {
+ X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
+ i = i2d_X509_bio(out, x);
+ } else {
+ i = PEM_write_bio_X509_REQ(out, rq);
+ }
+ if (!i) {
+ BIO_printf(bio_err,
+ "Unable to write certificate request\n");
+ goto end;
+ }
+ }
+ noout = 1;
+ } else if (privkey != NULL) {
+ if (!do_X509_sign(x, privkey, digest, sigopts, &ext_ctx))
+ goto end;
+ } else if (CAfile != NULL) {
+ if ((CAkey = load_key(CAkeyfile, CAkeyformat,
+ 0, passin, e, "CA private key")) == NULL)
+ goto end;
+ if (!X509_check_private_key(xca, CAkey)) {
+ BIO_printf(bio_err,
+ "CA certificate and CA private key do not match\n");
+ goto end;
+ }
+
+ if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx))
+ goto end;
+ }
if (badsig) {
const ASN1_BIT_STRING *signature;
@@ -632,236 +907,133 @@ int x509_main(int argc, char **argv)
corrupt_signature(signature);
}
- if (num) {
- for (i = 1; i <= num; i++) {
- if (issuer == i) {
- print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
- } else if (subject == i) {
- print_name(out, "subject=",
- X509_get_subject_name(x), get_nameopt());
- } else if (serial == i) {
- BIO_printf(out, "serial=");
- i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
- BIO_printf(out, "\n");
- } else if (next_serial == i) {
- 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))
- goto end;
- ser = BN_to_ASN1_INTEGER(bnser, NULL);
- if (!ser)
- goto end;
+ /* Process print options in the given order, as indicated by index i */
+ for (i = 1; i <= num; i++) {
+ if (i == issuer) {
+ print_name(out, "issuer=", X509_get_issuer_name(x));
+ } else if (i == subject) {
+ print_name(out, "subject=", X509_get_subject_name(x));
+ } else if (i == serial) {
+ BIO_printf(out, "serial=");
+ i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x));
+ BIO_printf(out, "\n");
+ } else if (i == next_serial) {
+ ASN1_INTEGER *ser;
+ BIGNUM *bnser = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x), NULL);
+
+ if (bnser == NULL)
+ goto end;
+ if (!BN_add_word(bnser, 1)
+ || (ser = BN_to_ASN1_INTEGER(bnser, NULL)) == NULL) {
BN_free(bnser);
- i2a_ASN1_INTEGER(out, ser);
- ASN1_INTEGER_free(ser);
- BIO_puts(out, "\n");
- } else if ((email == i) || (ocsp_uri == i)) {
- int j;
- STACK_OF(OPENSSL_STRING) *emlst;
- if (email == i)
- emlst = X509_get1_email(x);
- else
- emlst = X509_get1_ocsp(x);
- for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
- 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(out, "%s\n", alstr);
- else
- BIO_puts(out, "<No Alias>\n");
- } else if (subject_hash == i) {
- BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
+ goto end;
}
+ BN_free(bnser);
+ i2a_ASN1_INTEGER(out, ser);
+ ASN1_INTEGER_free(ser);
+ BIO_puts(out, "\n");
+ } else if (i == email || i == ocsp_uri) {
+ STACK_OF(OPENSSL_STRING) *emlst =
+ i == email ? X509_get1_email(x) : X509_get1_ocsp(x);
+
+ for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
+ BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j));
+ X509_email_free(emlst);
+ } else if (i == aliasout) {
+ unsigned char *alstr = X509_alias_get0(x, NULL);
+
+ if (alstr)
+ BIO_printf(out, "%s\n", alstr);
+ else
+ BIO_puts(out, "<No Alias>\n");
+ } else if (i == subject_hash) {
+ BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
#ifndef OPENSSL_NO_MD5
- else if (subject_hash_old == i) {
- BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
- }
+ } else if (i == subject_hash_old) {
+ BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
#endif
- else if (issuer_hash == i) {
- BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
- }
+ } else if (i == issuer_hash) {
+ BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
#ifndef OPENSSL_NO_MD5
- else if (issuer_hash_old == i) {
- BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
- }
+ } else if (i == issuer_hash_old) {
+ BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
#endif
- else if (pprint == i) {
- X509_PURPOSE *ptmp;
- int j;
- BIO_printf(out, "Certificate purposes:\n");
- for (j = 0; j < X509_PURPOSE_get_count(); j++) {
- ptmp = X509_PURPOSE_get0(j);
- purpose_print(out, x, ptmp);
- }
- } else if (modulus == i) {
- EVP_PKEY *pkey;
-
- pkey = X509_get0_pubkey(x);
- if (pkey == NULL) {
- BIO_printf(bio_err, "Modulus=unavailable\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- BIO_printf(out, "Modulus=");
-#ifndef OPENSSL_NO_RSA
- 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 (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(out, "Wrong Algorithm type");
- }
- BIO_printf(out, "\n");
- } else if (pubkey == i) {
- EVP_PKEY *pkey;
-
- 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(out, pkey);
- } else if (C == i) {
- unsigned char *d;
- char *m;
- int len;
-
- 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;
- len = i2d_X509_NAME(X509_get_subject_name(x), &d);
- print_array(out, "the_subject_name", len, (unsigned char *)m);
- d = (unsigned char *)m;
- len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
- print_array(out, "the_public_key", len, (unsigned char *)m);
- d = (unsigned char *)m;
- len = i2d_X509(x, &d);
- print_array(out, "the_certificate", len, (unsigned char *)m);
- OPENSSL_free(m);
- } else if (text == i) {
- X509_print_ex(out, x, get_nameopt(), certflag);
- } else if (startdate == i) {
- BIO_puts(out, "notBefore=");
- ASN1_TIME_print(out, X509_get0_notBefore(x));
- BIO_puts(out, "\n");
- } else if (enddate == i) {
- 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 == NULL)
- fdig = EVP_sha1();
-
- if (!X509_digest(x, fdig, md, &n)) {
- BIO_printf(bio_err, "out of memory\n");
- goto end;
- }
- BIO_printf(out, "%s Fingerprint=",
- OBJ_nid2sn(EVP_MD_type(fdig)));
- for (j = 0; j < (int)n; j++) {
- BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
- ? '\n' : ':');
- }
+ } else if (i == pprint) {
+ BIO_printf(out, "Certificate purposes:\n");
+ for (j = 0; j < X509_PURPOSE_get_count(); j++)
+ purpose_print(out, x, X509_PURPOSE_get0(j));
+ } else if (i == modulus) {
+ BIO_printf(out, "Modulus=");
+ if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+ BIGNUM *n = NULL;
+
+ /* Every RSA key has an 'n' */
+ EVP_PKEY_get_bn_param(pkey, "n", &n);
+ BN_print(out, n);
+ BN_free(n);
+ } else if (EVP_PKEY_is_a(pkey, "DSA")) {
+ BIGNUM *dsapub = NULL;
+
+ /* Every DSA key has a 'pub' */
+ EVP_PKEY_get_bn_param(pkey, "pub", &dsapub);
+ BN_print(out, dsapub);
+ BN_free(dsapub);
+ } else {
+ BIO_printf(out, "No modulus for this public key type");
}
-
- /* should be in the library */
- else if ((sign_flag == i) && (x509req == 0)) {
- BIO_printf(bio_err, "Getting Private key\n");
- if (Upkey == NULL) {
- Upkey = load_key(keyfile, keyformat, 0,
- passin, e, "Private key");
- if (Upkey == NULL)
- goto end;
- }
-
- 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(CAkeyfile, CAkeyformat,
- 0, passin, e, "CA Private Key");
- if (CApkey == NULL)
- goto end;
- }
-
- if (!x509_certify(ctx, CAfile, digest, x, xca,
- CApkey, sigopts,
- CAserial, CA_createserial, days, clrext,
- extconf, extsect, sno, reqfile, preserve_dates))
- goto end;
- } else if (x509req == i) {
- EVP_PKEY *pk;
-
- BIO_printf(bio_err, "Getting request Private Key\n");
- if (keyfile == NULL) {
- BIO_printf(bio_err, "no request key file specified\n");
- goto end;
- } else {
- pk = load_key(keyfile, keyformat, 0,
- passin, e, "request key");
- if (pk == NULL)
- goto end;
- }
-
- BIO_printf(bio_err, "Generating certificate request\n");
-
- rq = X509_to_X509_REQ(x, pk, digest);
- EVP_PKEY_free(pk);
- if (rq == NULL) {
- ERR_print_errors(bio_err);
- goto end;
- }
- if (!noout) {
- 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);
+ BIO_printf(out, "\n");
+ } else if (i == print_pubkey) {
+ PEM_write_bio_PUBKEY(out, pkey);
+ } else if (i == text) {
+ X509_print_ex(out, x, get_nameopt(), certflag);
+ } else if (i == startdate) {
+ BIO_puts(out, "notBefore=");
+ ASN1_TIME_print_ex(out, X509_get0_notBefore(x), dateopt);
+ BIO_puts(out, "\n");
+ } else if (i == enddate) {
+ BIO_puts(out, "notAfter=");
+ ASN1_TIME_print_ex(out, X509_get0_notAfter(x), dateopt);
+ BIO_puts(out, "\n");
+ } else if (i == fingerprint) {
+ unsigned int n;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ const char *fdigname = digest;
+ EVP_MD *fdig;
+ int digres;
+
+ if (fdigname == NULL)
+ fdigname = "SHA1";
+
+ if ((fdig = EVP_MD_fetch(app_get0_libctx(), fdigname,
+ app_get0_propq())) == NULL) {
+ BIO_printf(bio_err, "Unknown digest\n");
+ goto end;
+ }
+ digres = X509_digest(x, fdig, md, &n);
+ EVP_MD_free(fdig);
+ if (!digres) {
+ BIO_printf(bio_err, "Out of memory\n");
+ goto end;
}
+
+ BIO_printf(out, "%s Fingerprint=", fdigname);
+ for (j = 0; j < (int)n; j++)
+ BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':');
+ } else if (i == ocspid) {
+ X509_ocspid_print(out, x);
+ } else if (i == ext) {
+ print_x509v3_exts(out, x, ext_names);
}
}
if (checkend) {
time_t tcheck = time(NULL) + checkoffset;
- if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) {
+ ret = X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0;
+ if (ret)
BIO_printf(out, "Certificate will expire\n");
- ret = 1;
- } else {
+ else
BIO_printf(out, "Certificate will not expire\n");
- ret = 0;
- }
goto end;
}
@@ -880,33 +1052,36 @@ int x509_main(int argc, char **argv)
else
i = PEM_write_bio_X509(out, x);
} else {
- BIO_printf(bio_err, "bad output format specified for outfile\n");
+ BIO_printf(bio_err, "Bad output format specified for outfile\n");
goto end;
}
if (!i) {
- BIO_printf(bio_err, "unable to write certificate\n");
- ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Unable to write certificate\n");
goto end;
}
ret = 0;
+
end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
NCONF_free(extconf);
BIO_free_all(out);
X509_STORE_free(ctx);
+ X509_NAME_free(fsubj);
X509_REQ_free(req);
X509_free(x);
X509_free(xca);
- EVP_PKEY_free(Upkey);
- EVP_PKEY_free(CApkey);
- EVP_PKEY_free(fkey);
+ EVP_PKEY_free(privkey);
+ EVP_PKEY_free(CAkey);
+ EVP_PKEY_free(pubkey);
sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(vfyopts);
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);
- OPENSSL_free(passin);
+ clear_free(passin);
return ret;
}
@@ -934,7 +1109,7 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile,
goto end;
if (!BN_add_word(serial, 1)) {
- BIO_printf(bio_err, "add_word failure\n");
+ BIO_printf(bio_err, "Serial number increment failure\n");
goto end;
}
@@ -949,92 +1124,14 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile,
return bs;
}
-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,
- 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 = NULL;
- EVP_PKEY *upkey;
-
- 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);
-
- 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)) == NULL)
- 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)
- goto end;
-
- if (!X509_check_private_key(xca, pkey)) {
- BIO_printf(bio_err,
- "CA certificate and CA private key do not match\n");
- goto end;
- }
-
- if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
- goto end;
- if (!X509_set_serialNumber(x, bs))
- goto end;
-
- if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
- goto end;
-
- if (clrext) {
- while (X509_get_ext_count(x) > 0)
- X509_delete_ext(x, 0);
- }
-
- if (conf != NULL) {
- X509V3_CTX ctx2;
- X509_set_version(x, 2); /* version 3 certificate */
- 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(x, pkey, digest, sigopts))
- goto end;
- ret = 1;
- end:
- X509_STORE_CTX_free(xsc);
- if (!ret)
- ERR_print_errors(bio_err);
- if (!sno)
- ASN1_INTEGER_free(bs);
- return ret;
-}
-
static int callb(int ok, X509_STORE_CTX *ctx)
{
int err;
X509 *err_cert;
/*
- * it is ok to use a self signed certificate This case will catch both
- * the initial ok == 0 and the final ok == 1 calls to this function
+ * It is ok to use a self-signed certificate. This case will catch both
+ * the initial ok == 0 and the final ok == 1 calls to this function.
*/
err = X509_STORE_CTX_get_error(ctx);
if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
@@ -1047,51 +1144,19 @@ static int callb(int ok, X509_STORE_CTX *ctx)
*/
if (ok) {
BIO_printf(bio_err,
- "error with certificate to be certified - should be self signed\n");
+ "Error with certificate to be certified - should be self-signed\n");
return 0;
} else {
err_cert = X509_STORE_CTX_get_current_cert(ctx);
- print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
+ print_name(bio_err, "subject=", X509_get_subject_name(err_cert));
BIO_printf(bio_err,
- "error with certificate - error %d at depth %d\n%s\n", err,
+ "Error with certificate - error %d at depth %d\n%s\n", err,
X509_STORE_CTX_get_error_depth(ctx),
X509_verify_cert_error_string(err));
return 1;
}
}
-/* self sign */
-static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
- const EVP_MD *digest, CONF *conf, const char *section,
- int preserve_dates)
-{
-
- if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
- goto err;
- 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 != NULL) {
- X509V3_CTX ctx;
- X509_set_version(x, 2); /* version 3 certificate */
- X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
- X509V3_set_nconf(&ctx, conf);
- if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
- goto err;
- }
- if (!X509_sign(x, pkey, digest))
- goto err;
- return 1;
- err:
- ERR_print_errors(bio_err);
- return 0;
-}
-
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
{
int id, i, idret;
@@ -1150,7 +1215,7 @@ static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names)
exts = X509_get0_extensions(x);
if ((num = sk_X509_EXTENSION_num(exts)) <= 0) {
- BIO_printf(bio, "No extensions in certificate\n");
+ BIO_printf(bio_err, "No extensions in certificate\n");
ret = 1;
goto end;
}