From 36734a17b35f50bc601c70d44e33310d849201f6 Mon Sep 17 00:00:00 2001 From: Michael Baentsch <57787676+baentsch@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:52:09 +0200 Subject: [PATCH 01/16] adding -outpubkey option to genpkey Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22173) Signed-off-by: fly2x --- apps/genpkey.c | 26 +++++++++++++++++++++----- doc/man1/openssl-genpkey.pod.in | 18 ++++++++++++------ test/recipes/15-test_genec.t | 4 +++- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/apps/genpkey.c b/apps/genpkey.c index 080f1f6075..66f0e1eaf0 100644 --- a/apps/genpkey.c +++ b/apps/genpkey.c @@ -23,7 +23,7 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE, OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER, - OPT_VERBOSE, OPT_QUIET, OPT_CONFIG, + OPT_VERBOSE, OPT_QUIET, OPT_CONFIG, OPT_OUTPUBKEY, OPT_PROV_ENUM } OPTION_CHOICE; @@ -42,11 +42,12 @@ const OPTIONS genpkey_options[] = { OPT_CONFIG_OPTION, OPT_SECTION("Output"), - {"out", OPT_OUT, '>', "Output file"}, + {"out", OPT_OUT, '>', "Output (private key) file"}, + {"outpubkey", OPT_OUTPUBKEY, '>', "Output public key 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"}, + {"text", OPT_TEXT, '-', "Print the private key in text"}, {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"}, OPT_PROV_OPTIONS, @@ -104,11 +105,12 @@ cleanup: int genpkey_main(int argc, char **argv) { CONF *conf = NULL; - BIO *in = NULL, *out = NULL; + BIO *in = NULL, *out = NULL, *outpubkey = NULL; ENGINE *e = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog, *p; + char *outpubkeyfile = NULL; const char *ciphername = NULL, *paramfile = NULL, *algname = NULL; EVP_CIPHER *cipher = NULL; OPTION_CHOICE o; @@ -141,6 +143,9 @@ int genpkey_main(int argc, char **argv) case OPT_OUT: outfile = opt_arg(); break; + case OPT_OUTPUBKEY: + outpubkeyfile = opt_arg(); + break; case OPT_PASS: passarg = opt_arg(); break; @@ -228,6 +233,12 @@ int genpkey_main(int argc, char **argv) if (out == NULL) goto end; + if (outpubkeyfile != NULL) { + outpubkey = bio_open_owner(outpubkeyfile, outformat, private); + if (outpubkey == NULL) + goto end; + } + if (verbose) EVP_PKEY_CTX_set_cb(ctx, progress_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); @@ -242,9 +253,13 @@ int genpkey_main(int argc, char **argv) } else if (outformat == FORMAT_PEM) { assert(private); rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass); + if (rv > 0 && outpubkey != NULL) + rv = PEM_write_bio_PUBKEY(outpubkey, pkey); } else if (outformat == FORMAT_ASN1) { assert(private); rv = i2d_PrivateKey_bio(out, pkey); + if (rv > 0 && outpubkey != NULL) + rv = i2d_PUBKEY_bio(outpubkey, pkey); } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; @@ -253,7 +268,7 @@ int genpkey_main(int argc, char **argv) ret = 0; if (rv <= 0) { - BIO_puts(bio_err, "Error writing key\n"); + BIO_puts(bio_err, "Error writing key(s)\n"); ret = 1; } @@ -277,6 +292,7 @@ int genpkey_main(int argc, char **argv) EVP_PKEY_CTX_free(ctx); EVP_CIPHER_free(cipher); BIO_free_all(out); + BIO_free_all(outpubkey); BIO_free(in); release_engine(e); OPENSSL_free(pass); diff --git a/doc/man1/openssl-genpkey.pod.in b/doc/man1/openssl-genpkey.pod.in index e760d613fe..aa0b74e8aa 100644 --- a/doc/man1/openssl-genpkey.pod.in +++ b/doc/man1/openssl-genpkey.pod.in @@ -7,13 +7,14 @@ =head1 NAME -openssl-genpkey - generate a private key +openssl-genpkey - generate a private key or key pair =head1 SYNOPSIS B B [B<-help>] [B<-out> I] +[B<-outpubkey> I] [B<-outform> B|B] [B<-verbose>] [B<-quiet>] @@ -29,7 +30,7 @@ B B =head1 DESCRIPTION -This command generates a private key. +This command generates a private key or key pair. =head1 OPTIONS @@ -41,8 +42,13 @@ Print out a usage message. =item B<-out> I -Output the key to the specified file. If this argument is not specified then -standard output is used. +Output the private key to the specified file. If this argument is not +specified then standard output is used. + +=item B<-outpubkey> I + +Output the public key to the specified file. If this argument is not +specified then the public key is not output. =item B<-outform> B|B @@ -73,8 +79,8 @@ name accepted by EVP_get_cipherbyname() is acceptable such as B. Public key algorithm to use such as RSA, DSA, DH or DHX. If used this option must precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm> -are mutually exclusive. Engines may add algorithms in addition to the standard -built-in ones. +are mutually exclusive. Engines or providers may add algorithms in addition to +the standard built-in ones. Valid built-in algorithm names for private key generation are RSA, RSA-PSS, EC, X25519, X448, ED25519 and ED448. diff --git a/test/recipes/15-test_genec.t b/test/recipes/15-test_genec.t index 2dfed387ca..3e8c55071c 100644 --- a/test/recipes/15-test_genec.t +++ b/test/recipes/15-test_genec.t @@ -232,13 +232,15 @@ foreach my $curvename (@curve_list) { foreach my $outform (@output_formats) { my $outfile = "ecgen.${curvename}.${paramenc}." . lc $outform; + my $outpubfile = "ecgen.${curvename}.${paramenc}-pub." . lc $outform; $fn->("genpkey EC key on ${curvename} with ec_param_enc:'${paramenc}' (${outform})", app([ 'openssl', 'genpkey', '-algorithm', 'EC', '-pkeyopt', 'ec_paramgen_curve:'.$curvename, '-pkeyopt', 'ec_param_enc:'.$paramenc, '-outform', $outform, - '-out', $outfile])); + '-out', $outfile, + '-outpubkey', $outpubfile])); } } } -- Gitee From 41fb5d3f9116e4b610fe51e5e214d6850f3bcf05 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 22 Sep 2023 17:31:34 +0100 Subject: [PATCH 02/16] Remove a spurious inclusion of the sparse array header file Reviewed-by: Richard Levitte Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/22174) Signed-off-by: fly2x --- ssl/event_queue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ssl/event_queue.c b/ssl/event_queue.c index 49890a36b5..20f4020db5 100644 --- a/ssl/event_queue.c +++ b/ssl/event_queue.c @@ -9,7 +9,6 @@ #include #include "internal/event_queue.h" -#include "crypto/sparse_array.h" #include "ssl_local.h" struct ossl_event_queue_st { -- Gitee From 221c839e6b4cd60e1fa1d8dee7062b9e1007aeaf Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 21 Sep 2023 11:59:58 +0100 Subject: [PATCH 03/16] Implement a public BIO_ADDR_copy() function We already have BIO_ADDR_dup() but in some contexts that is not sufficent. We implement BIO_ADDR_copy() and make BIO_ADDR_dup() use it. Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/22164) Signed-off-by: fly2x --- crypto/bio/bio_addr.c | 19 +++++++++++++++++-- include/openssl/bio.h.in | 1 + util/libcrypto.num | 1 + 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/crypto/bio/bio_addr.c b/crypto/bio/bio_addr.c index aec94237fc..2a6f6d522c 100644 --- a/crypto/bio/bio_addr.c +++ b/crypto/bio/bio_addr.c @@ -65,14 +65,29 @@ void BIO_ADDR_free(BIO_ADDR *ap) OPENSSL_free(ap); } +int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src) +{ + if (dst == NULL || src == NULL) + return 0; + + if (src->sa.sa_family == AF_UNSPEC) { + BIO_ADDR_clear(dst); + return 1; + } + + return BIO_ADDR_make(dst, &src->sa); +} + BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap) { BIO_ADDR *ret = NULL; if (ap != NULL) { ret = BIO_ADDR_new(); - if (ret != NULL) - BIO_ADDR_make(ret, &ap->sa); + if (ret != NULL && !BIO_ADDR_copy(ret, ap)) { + BIO_ADDR_free(ret); + ret = NULL; + } } return ret; } diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index 8aad141446..c534dcd76c 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -806,6 +806,7 @@ int BIO_hex_string(BIO *out, int indent, int width, const void *data, # ifndef OPENSSL_NO_SOCK BIO_ADDR *BIO_ADDR_new(void); +int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src); BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap); int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, const void *where, size_t wherelen, unsigned short port); diff --git a/util/libcrypto.num b/util/libcrypto.num index e4265b4cef..6af1fe1707 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5535,3 +5535,4 @@ OSSL_ERR_STATE_save_to_mark ? 3_2_0 EXIST::FUNCTION: X509_STORE_CTX_set_get_crl ? 3_2_0 EXIST::FUNCTION: X509_STORE_CTX_set_current_reasons ? 3_2_0 EXIST::FUNCTION: OSSL_STORE_delete ? 3_2_0 EXIST::FUNCTION: +BIO_ADDR_copy ? 3_2_0 EXIST::FUNCTION:SOCK -- Gitee From fa4ae3c34aac1d28e6bc8d9357cc2d0b8ee61424 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 21 Sep 2023 12:10:15 +0100 Subject: [PATCH 04/16] Add documentation for the BIO_ADDR_copy() function Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/22164) Signed-off-by: fly2x --- doc/man3/BIO_ADDR.pod | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/man3/BIO_ADDR.pod b/doc/man3/BIO_ADDR.pod index aa5bf77191..20cd364d48 100644 --- a/doc/man3/BIO_ADDR.pod +++ b/doc/man3/BIO_ADDR.pod @@ -2,8 +2,8 @@ =head1 NAME -BIO_ADDR, BIO_ADDR_new, BIO_ADDR_dup, BIO_ADDR_clear, BIO_ADDR_free, -BIO_ADDR_rawmake, +BIO_ADDR, BIO_ADDR_new, BIO_ADDR_copy, BIO_ADDR_dup, BIO_ADDR_clear, +BIO_ADDR_free, BIO_ADDR_rawmake, BIO_ADDR_family, BIO_ADDR_rawaddress, BIO_ADDR_rawport, BIO_ADDR_hostname_string, BIO_ADDR_service_string, BIO_ADDR_path_string - BIO_ADDR routines @@ -16,6 +16,7 @@ BIO_ADDR_path_string - BIO_ADDR routines typedef union bio_addr_st BIO_ADDR; BIO_ADDR *BIO_ADDR_new(void); + int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src); BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap); void BIO_ADDR_free(BIO_ADDR *); void BIO_ADDR_clear(BIO_ADDR *ap); @@ -39,6 +40,9 @@ BIO_ADDR_new() creates a new unfilled B, to be used with routines that will fill it with information, such as BIO_accept_ex(). +BIO_ADDR_copy() copies the contents of B into B. Neither B or +B can be NULL. + BIO_ADDR_dup() creates a new B, with a copy of the address data in B. @@ -112,6 +116,8 @@ BIO_ADDR_service_string() and BIO_ADDR_path_string() will return B on error and leave an error indication on the OpenSSL error stack. +BIO_ADDR_copy() returns 1 on success or 0 on error. + All other functions described here return 0 or B when the information they should return isn't available. @@ -121,7 +127,7 @@ L, L =head1 HISTORY -BIO_ADDR_dup() was added in OpenSSL 3.2. +BIO_ADDR_copy() and BIO_ADDR_dup() were added in OpenSSL 3.2. =head1 COPYRIGHT -- Gitee From bc3ac1eda06068072b4f4d812e82a772ec668d23 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 21 Sep 2023 12:16:38 +0100 Subject: [PATCH 05/16] Clean away the test code implementation of bio_addr_copy We now have a public function for BIO_ADDR_copy() which can be used in preference to the test code's private implementation. Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/22164) Signed-off-by: fly2x --- test/helpers/quictestlib.c | 42 ++------------------------------------ test/helpers/quictestlib.h | 3 --- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index f5a46efb6f..17da14766f 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -1086,44 +1086,6 @@ int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen) return 1; } -/* There isn't a public function to do BIO_ADDR_copy() so we create one */ -int bio_addr_copy(BIO_ADDR *dst, BIO_ADDR *src) -{ - size_t len; - void *data = NULL; - int res = 0; - int family; - - if (src == NULL || dst == NULL) - return 0; - - family = BIO_ADDR_family(src); - if (family == AF_UNSPEC) { - BIO_ADDR_clear(dst); - return 1; - } - - if (!BIO_ADDR_rawaddress(src, NULL, &len)) - return 0; - - if (len > 0) { - data = OPENSSL_malloc(len); - if (!TEST_ptr(data)) - return 0; - } - - if (!BIO_ADDR_rawaddress(src, data, &len)) - goto err; - - if (!BIO_ADDR_rawmake(src, family, data, len, BIO_ADDR_rawport(src))) - goto err; - - res = 1; - err: - OPENSSL_free(data); - return res; -} - int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src) { /* @@ -1135,13 +1097,13 @@ int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src) dst->flags = src->flags; if (dst->local != NULL) { if (src->local != NULL) { - if (!TEST_true(bio_addr_copy(dst->local, src->local))) + if (!TEST_true(BIO_ADDR_copy(dst->local, src->local))) return 0; } else { BIO_ADDR_clear(dst->local); } } - if (!TEST_true(bio_addr_copy(dst->peer, src->peer))) + if (!TEST_true(BIO_ADDR_copy(dst->peer, src->peer))) return 0; return 1; diff --git a/test/helpers/quictestlib.h b/test/helpers/quictestlib.h index 844aec8a60..f090299b22 100644 --- a/test/helpers/quictestlib.h +++ b/test/helpers/quictestlib.h @@ -242,9 +242,6 @@ int qtest_fault_set_datagram_listener(QTEST_FAULT *fault, */ int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen); -/* Copy a BIO_ADDR */ -int bio_addr_copy(BIO_ADDR *dst, BIO_ADDR *src); - /* Copy a BIO_MSG */ int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src); -- Gitee From 6b86e715bbe9b38b68d04f0bdd1bc819f937d88d Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 21 Sep 2023 16:28:58 +0100 Subject: [PATCH 06/16] Add a test for BIO_ADDR_copy() We also add a test for BIO_ADDR_dup() which was also added in 3.2 Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/22164) Signed-off-by: fly2x --- test/bio_addr_test.c | 164 ++++++++++++++++++++++++++++++++ test/build.info | 6 ++ test/recipes/61-test_bio_addr.t | 20 ++++ 3 files changed, 190 insertions(+) create mode 100644 test/bio_addr_test.c create mode 100644 test/recipes/61-test_bio_addr.t diff --git a/test/bio_addr_test.c b/test/bio_addr_test.c new file mode 100644 index 0000000000..a985d03b14 --- /dev/null +++ b/test/bio_addr_test.c @@ -0,0 +1,164 @@ +/* + * Copyright 2023 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 +#include "internal/e_os.h" +#include "internal/sockets.h" +#include "testutil.h" + +static int families[] = { + AF_INET, +#if OPENSSL_USE_IPV6 + AF_INET6, +#endif +#ifndef OPENSSL_NO_UNIX_SOCK + AF_UNIX +#endif +}; + +static BIO_ADDR *make_dummy_addr(int family) +{ + BIO_ADDR *addr; + union { + struct sockaddr_in sin; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 sin6; +#endif +#ifndef OPENSSL_NO_UNIX_SOCK + struct sockaddr_un sun; +#endif + } sa; + void *where; + size_t wherelen; + + /* Fill with a dummy address */ + switch(family) { + case AF_INET: + where = &(sa.sin.sin_addr); + wherelen = sizeof(sa.sin.sin_addr); + break; +#if OPENSSL_USE_IPV6 + case AF_INET6: + where = &(sa.sin6.sin6_addr); + wherelen = sizeof(sa.sin6.sin6_addr); + break; +#endif +#ifndef OPENSSL_NO_UNIX_SOCK + case AF_UNIX: + where = &(sa.sun.sun_path); + /* BIO_ADDR_rawmake needs an extra byte for a NUL-terminator*/ + wherelen = sizeof(sa.sun.sun_path) - 1; + break; +#endif + default: + TEST_error("Unsupported address family"); + return 0; + } + /* + * Could be any data, but we make it printable because BIO_ADDR_rawmake + * expects the AF_UNIX address to be a string. + */ + memset(where, 'a', wherelen); + + addr = BIO_ADDR_new(); + if (!TEST_ptr(addr)) + return NULL; + + if (!TEST_true(BIO_ADDR_rawmake(addr, family, where, wherelen, 1000))) { + BIO_ADDR_free(addr); + return NULL; + } + + return addr; +} + +static int bio_addr_is_eq(const BIO_ADDR *a, const BIO_ADDR *b) +{ + struct sockaddr_storage adata, bdata; + size_t alen, blen; + + /* True even if a and b are NULL */ + if (a == b) + return 1; + + /* If one is NULL the other cannot be due to the test above */ + if (a == NULL || b == NULL) + return 0; + + if (BIO_ADDR_family(a) != BIO_ADDR_family(b)) + return 0; + + /* Works even with AF_UNIX/AF_UNSPEC which just returns 0 */ + if (BIO_ADDR_rawport(a) != BIO_ADDR_rawport(b)) + return 0; + + if (!BIO_ADDR_rawaddress(a, NULL, &alen) + || alen > sizeof(adata) + || !BIO_ADDR_rawaddress(a, &adata, &alen)) + return 0; + + if (!BIO_ADDR_rawaddress(a, NULL, &blen) + || blen > sizeof(bdata) + || !BIO_ADDR_rawaddress(a, &bdata, &blen)) + return 0; + + if (alen != blen) + return 0; + + if (alen == 0) + return 1; + + return memcmp(&adata, &bdata, alen) == 0; +} + +static int test_bio_addr_copy_dup(int idx) +{ + BIO_ADDR *src = NULL, *dst = NULL; + int ret = 0; + int docopy = idx & 1; + + idx >>= 1; + + src = make_dummy_addr(families[idx]); + if (!TEST_ptr(src)) + return 0; + + if (docopy) { + dst = BIO_ADDR_new(); + if (!TEST_ptr(dst)) + goto err; + + if (!TEST_true(BIO_ADDR_copy(dst, src))) + goto err; + } else { + dst = BIO_ADDR_dup(src); + if (!TEST_ptr(dst)) + goto err; + } + + if (!TEST_true(bio_addr_is_eq(src, dst))) + goto err; + + ret = 1; + err: + BIO_ADDR_free(src); + BIO_ADDR_free(dst); + return ret; +} + +int setup_tests(void) +{ + if (!test_skip_common_options()) { + TEST_error("Error parsing test options\n"); + return 0; + } + + ADD_ALL_TESTS(test_bio_addr_copy_dup, OSSL_NELEM(families) * 2); + return 1; +} diff --git a/test/build.info b/test/build.info index 4c81a2b779..73f8de1f7a 100644 --- a/test/build.info +++ b/test/build.info @@ -522,6 +522,12 @@ IF[{- !$disabled{tests} -}] INCLUDE[http_test]=../include ../apps/include DEPEND[http_test]=../libcrypto libtestutil.a ENDIF + + PROGRAMS{noinst}=bio_addr_test + + SOURCE[bio_addr_test]=bio_addr_test.c + INCLUDE[bio_addr_test]=../include ../apps/include + DEPEND[bio_addr_test]=../libcrypto libtestutil.a ENDIF SOURCE[dtlstest]=dtlstest.c helpers/ssltestlib.c diff --git a/test/recipes/61-test_bio_addr.t b/test/recipes/61-test_bio_addr.t new file mode 100644 index 0000000000..bd4c23a71f --- /dev/null +++ b/test/recipes/61-test_bio_addr.t @@ -0,0 +1,20 @@ +#! /usr/bin/env perl +# Copyright 2023 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 + + +use OpenSSL::Test; +use OpenSSL::Test::Utils; + +setup("test_bio_addr"); + +plan skip_all => "No sockets in this configuration" + if disabled("sock"); + +plan tests => 1; + +ok(run(test(["bio_addr_test"])), "running bio_addr_test"); -- Gitee From 1a56c504ce1c015a921e5231fcb7668fbcd2435e Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Sat, 1 Jul 2023 15:56:40 +0000 Subject: [PATCH 07/16] Support all NULL-syntax X.509v3 extensions Signed-off-by: Jonathan M. Wilbur Reviewed-by: Todd Short Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/21342) Signed-off-by: fly2x --- crypto/x509/build.info | 3 +- crypto/x509/ext_dat.h | 6 ++++ crypto/x509/standard_exts.h | 8 ++++- crypto/x509/v3_group_ac.c | 53 +++++++++++++++++++++++++++++++ crypto/x509/v3_ind_iss.c | 53 +++++++++++++++++++++++++++++++ crypto/x509/v3_no_ass.c | 53 +++++++++++++++++++++++++++++++ crypto/x509/v3_no_rev_avail.c | 53 +++++++++++++++++++++++++++++++ crypto/x509/v3_single_use.c | 53 +++++++++++++++++++++++++++++++ crypto/x509/v3_soa_id.c | 53 +++++++++++++++++++++++++++++++ test/certs/ext-groupAC.pem | 11 +++++++ test/certs/ext-indirectIssuer.pem | 11 +++++++ test/certs/ext-noAssertion.pem | 11 +++++++ test/certs/ext-noRevAvail.pem | 11 +++++++ test/certs/ext-sOAIdentifier.pem | 11 +++++++ test/certs/ext-singleUse.pem | 12 +++++++ test/recipes/25-test_x509.t | 26 ++++++++++++++- 16 files changed, 425 insertions(+), 3 deletions(-) create mode 100644 crypto/x509/v3_group_ac.c create mode 100644 crypto/x509/v3_ind_iss.c create mode 100644 crypto/x509/v3_no_ass.c create mode 100644 crypto/x509/v3_no_rev_avail.c create mode 100644 crypto/x509/v3_single_use.c create mode 100644 crypto/x509/v3_soa_id.c create mode 100644 test/certs/ext-groupAC.pem create mode 100644 test/certs/ext-indirectIssuer.pem create mode 100644 test/certs/ext-noAssertion.pem create mode 100644 test/certs/ext-noRevAvail.pem create mode 100644 test/certs/ext-sOAIdentifier.pem create mode 100644 test/certs/ext-singleUse.pem diff --git a/crypto/x509/build.info b/crypto/x509/build.info index 8820f983bb..3f70f3ff36 100644 --- a/crypto/x509/build.info +++ b/crypto/x509/build.info @@ -14,7 +14,8 @@ SOURCE[../../libcrypto]=\ v3_info.c v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c \ v3_pcia.c v3_pci.c v3_ist.c \ pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \ - v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c + v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c v3_no_rev_avail.c \ + v3_soa_id.c v3_no_ass.c v3_group_ac.c v3_single_use.c v3_ind_iss.c IF[{- !$disabled{'deprecated-3.0'} -}] SOURCE[../../libcrypto]=x509type.c diff --git a/crypto/x509/ext_dat.h b/crypto/x509/ext_dat.h index a0a7f88ccd..8325aacfa5 100644 --- a/crypto/x509/ext_dat.h +++ b/crypto/x509/ext_dat.h @@ -25,3 +25,9 @@ extern const X509V3_EXT_METHOD ossl_v3_tls_feature; extern const X509V3_EXT_METHOD ossl_v3_ext_admission; extern const X509V3_EXT_METHOD ossl_v3_utf8_list[1]; extern const X509V3_EXT_METHOD ossl_v3_issuer_sign_tool; +extern const X509V3_EXT_METHOD ossl_v3_group_ac; +extern const X509V3_EXT_METHOD ossl_v3_soa_identifier; +extern const X509V3_EXT_METHOD ossl_v3_no_assertion; +extern const X509V3_EXT_METHOD ossl_v3_no_rev_avail; +extern const X509V3_EXT_METHOD ossl_v3_single_use; +extern const X509V3_EXT_METHOD ossl_v3_indirect_issuer; diff --git a/crypto/x509/standard_exts.h b/crypto/x509/standard_exts.h index 27a99a4b13..e5c9e3f9e0 100644 --- a/crypto/x509/standard_exts.h +++ b/crypto/x509/standard_exts.h @@ -53,6 +53,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = { #endif &ossl_v3_sinfo, &ossl_v3_policy_constraints, + &ossl_v3_no_rev_avail, #ifndef OPENSSL_NO_OCSP &ossl_v3_crl_hold, #endif @@ -71,7 +72,12 @@ static const X509V3_EXT_METHOD *standard_exts[] = { &ossl_v3_utf8_list[0], &ossl_v3_issuer_sign_tool, &ossl_v3_tls_feature, - &ossl_v3_ext_admission + &ossl_v3_ext_admission, + &ossl_v3_soa_identifier, + &ossl_v3_indirect_issuer, + &ossl_v3_no_assertion, + &ossl_v3_single_use, + &ossl_v3_group_ac }; /* Number of standard extensions */ diff --git a/crypto/x509/v3_group_ac.c b/crypto/x509/v3_group_ac.c new file mode 100644 index 0000000000..9a2b69dece --- /dev/null +++ b/crypto/x509/v3_group_ac.c @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static int i2r_GROUP_AC(X509V3_EXT_METHOD *method, + void *su, BIO *out, + int indent) +{ + return 1; +} + +static void *r2i_GROUP_AC(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value) +{ + return ASN1_NULL_new(); +} + +static char *i2s_GROUP_AC(const X509V3_EXT_METHOD *method, void *val) +{ + return OPENSSL_strdup("NULL"); +} + +static void *s2i_GROUP_AC(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +/* + * The groupAC X.509v3 extension is defined in ITU Recommendation X.509 + * (2019), Section 17.1.2.6. See: https://www.itu.int/rec/T-REC-X.509-201910-I/en. + */ +const X509V3_EXT_METHOD ossl_v3_group_ac = { + NID_group_ac, 0, ASN1_ITEM_ref(ASN1_NULL), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_GROUP_AC, + (X509V3_EXT_S2I)s2i_GROUP_AC, + 0, 0, + (X509V3_EXT_I2R)i2r_GROUP_AC, + (X509V3_EXT_R2I)r2i_GROUP_AC, + NULL +}; diff --git a/crypto/x509/v3_ind_iss.c b/crypto/x509/v3_ind_iss.c new file mode 100644 index 0000000000..ff41ba7bed --- /dev/null +++ b/crypto/x509/v3_ind_iss.c @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static int i2r_INDIRECT_ISSUER(X509V3_EXT_METHOD *method, + void *su, BIO *out, + int indent) +{ + return 1; +} + +static void *r2i_INDIRECT_ISSUER(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value) +{ + return ASN1_NULL_new(); +} + +static char *i2s_INDIRECT_ISSUER(const X509V3_EXT_METHOD *method, void *val) +{ + return OPENSSL_strdup("NULL"); +} + +static void *s2i_INDIRECT_ISSUER(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +/* + * The indirectIssuer X.509v3 extension is defined in ITU Recommendation X.509 + * (2019), Section 17.5.2.5. See: https://www.itu.int/rec/T-REC-X.509-201910-I/en. + */ +const X509V3_EXT_METHOD ossl_v3_indirect_issuer = { + NID_indirect_issuer, 0, ASN1_ITEM_ref(ASN1_NULL), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_INDIRECT_ISSUER, + (X509V3_EXT_S2I)s2i_INDIRECT_ISSUER, + 0, 0, + (X509V3_EXT_I2R)i2r_INDIRECT_ISSUER, + (X509V3_EXT_R2I)r2i_INDIRECT_ISSUER, + NULL +}; diff --git a/crypto/x509/v3_no_ass.c b/crypto/x509/v3_no_ass.c new file mode 100644 index 0000000000..873e20a751 --- /dev/null +++ b/crypto/x509/v3_no_ass.c @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static int i2r_NO_ASSERTION(X509V3_EXT_METHOD *method, + void *su, BIO *out, + int indent) +{ + return 1; +} + +static void *r2i_NO_ASSERTION(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value) +{ + return ASN1_NULL_new(); +} + +static char *i2s_NO_ASSERTION(const X509V3_EXT_METHOD *method, void *val) +{ + return OPENSSL_strdup("NULL"); +} + +static void *s2i_NO_ASSERTION(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +/* + * The noAssertion X.509v3 extension is defined in ITU Recommendation X.509 + * (2019), Section 17.5.2.7. See: https://www.itu.int/rec/T-REC-X.509-201910-I/en. + */ +const X509V3_EXT_METHOD ossl_v3_no_assertion = { + NID_no_assertion, 0, ASN1_ITEM_ref(ASN1_NULL), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_NO_ASSERTION, + (X509V3_EXT_S2I)s2i_NO_ASSERTION, + 0, 0, + (X509V3_EXT_I2R)i2r_NO_ASSERTION, + (X509V3_EXT_R2I)r2i_NO_ASSERTION, + NULL +}; diff --git a/crypto/x509/v3_no_rev_avail.c b/crypto/x509/v3_no_rev_avail.c new file mode 100644 index 0000000000..849feda5ec --- /dev/null +++ b/crypto/x509/v3_no_rev_avail.c @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static int i2r_NO_REV_AVAIL(X509V3_EXT_METHOD *method, + void *su, BIO *out, + int indent) +{ + return 1; +} + +static void *r2i_NO_REV_AVAIL(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value) +{ + return ASN1_NULL_new(); +} + +static char *i2s_NO_REV_AVAIL(const X509V3_EXT_METHOD *method, void *val) +{ + return OPENSSL_strdup("NULL"); +} + +static void *s2i_NO_REV_AVAIL(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +/* + * The noRevAvail X.509v3 extension is defined in ITU Recommendation X.509 + * (2019), Section 17.2.2.7. See: https://www.itu.int/rec/T-REC-X.509-201910-I/en. + */ +const X509V3_EXT_METHOD ossl_v3_no_rev_avail = { + NID_no_rev_avail, 0, ASN1_ITEM_ref(ASN1_NULL), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_NO_REV_AVAIL, + (X509V3_EXT_S2I)s2i_NO_REV_AVAIL, + 0, 0, + (X509V3_EXT_I2R)i2r_NO_REV_AVAIL, + (X509V3_EXT_R2I)r2i_NO_REV_AVAIL, + NULL +}; diff --git a/crypto/x509/v3_single_use.c b/crypto/x509/v3_single_use.c new file mode 100644 index 0000000000..50da6e1770 --- /dev/null +++ b/crypto/x509/v3_single_use.c @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static int i2r_SINGLE_USE(X509V3_EXT_METHOD *method, + void *su, BIO *out, + int indent) +{ + return 1; +} + +static void *r2i_SINGLE_USE(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value) +{ + return ASN1_NULL_new(); +} + +static char *i2s_SINGLE_USE(const X509V3_EXT_METHOD *method, void *val) +{ + return OPENSSL_strdup("NULL"); +} + +static void *s2i_SINGLE_USE(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +/* + * The singleUse X.509v3 extension is defined in ITU Recommendation X.509 + * (2019), Section 17.1.2.5. See: https://www.itu.int/rec/T-REC-X.509-201910-I/en. + */ +const X509V3_EXT_METHOD ossl_v3_single_use = { + NID_single_use, 0, ASN1_ITEM_ref(ASN1_NULL), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_SINGLE_USE, + (X509V3_EXT_S2I)s2i_SINGLE_USE, + 0, 0, + (X509V3_EXT_I2R)i2r_SINGLE_USE, + (X509V3_EXT_R2I)r2i_SINGLE_USE, + NULL +}; diff --git a/crypto/x509/v3_soa_id.c b/crypto/x509/v3_soa_id.c new file mode 100644 index 0000000000..8be5bd8aa5 --- /dev/null +++ b/crypto/x509/v3_soa_id.c @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static int i2r_SOA_IDENTIFIER(X509V3_EXT_METHOD *method, + void *su, BIO *out, + int indent) +{ + return 1; +} + +static void *r2i_SOA_IDENTIFIER(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value) +{ + return ASN1_NULL_new(); +} + +static char *i2s_SOA_IDENTIFIER(const X509V3_EXT_METHOD *method, void *val) +{ + return OPENSSL_strdup("NULL"); +} + +static void *s2i_SOA_IDENTIFIER(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +/* + * The sOAIdentifier X.509v3 extension is defined in ITU Recommendation X.509 + * (2019), Section 17.3.2.1.1. See: https://www.itu.int/rec/T-REC-X.509-201910-I/en. + */ +const X509V3_EXT_METHOD ossl_v3_soa_identifier = { + NID_soa_identifier, 0, ASN1_ITEM_ref(ASN1_NULL), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_SOA_IDENTIFIER, + (X509V3_EXT_S2I)s2i_SOA_IDENTIFIER, + 0, 0, + (X509V3_EXT_I2R)i2r_SOA_IDENTIFIER, + (X509V3_EXT_R2I)r2i_SOA_IDENTIFIER, + NULL +}; diff --git a/test/certs/ext-groupAC.pem b/test/certs/ext-groupAC.pem new file mode 100644 index 0000000000..f5325eb2ae --- /dev/null +++ b/test/certs/ext-groupAC.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBhjCCAXKgAwIBAgIDAQIDMAsGCSqGSIb3DQEBBTAAMCIYDzIwMjEwODMwMDA1 +MzE3WhgPMjAyMTA4MzAwMDUzMTdaMAAwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIB +CgKCAQEAtnjLm1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmq +nuGrBOUfgbmH3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWir +Gu0oDRzhWLHe1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqI +qpOynJB02thXrTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06 +GkwLFJHNv2tU+tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3Vus +pVz+6pU2xgl3nrAVMQHB4fReQPH0pQIDAQABow0wCzAJBgNVHUIEAgUAMAsGCSqG +SIb3DQEBBQMBAA== +-----END CERTIFICATE----- diff --git a/test/certs/ext-indirectIssuer.pem b/test/certs/ext-indirectIssuer.pem new file mode 100644 index 0000000000..afc21806ae --- /dev/null +++ b/test/certs/ext-indirectIssuer.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBhjCCAXKgAwIBAgIDAQIDMAsGCSqGSIb3DQEBBTAAMCIYDzIwMjEwODMxMDIy +NzM4WhgPMjAyMTA4MzEwMjI3MzhaMAAwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIB +CgKCAQEAtnjLm1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmq +nuGrBOUfgbmH3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWir +Gu0oDRzhWLHe1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqI +qpOynJB02thXrTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06 +GkwLFJHNv2tU+tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3Vus +pVz+6pU2xgl3nrAVMQHB4fReQPH0pQIDAQABow0wCzAJBgNVHT0EAgUAMAsGCSqG +SIb3DQEBBQMBAA== +-----END CERTIFICATE----- diff --git a/test/certs/ext-noAssertion.pem b/test/certs/ext-noAssertion.pem new file mode 100644 index 0000000000..1aaa860bdd --- /dev/null +++ b/test/certs/ext-noAssertion.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBhjCCAXKgAwIBAgIDAQIDMAsGCSqGSIb3DQEBBTAAMCIYDzIwMjEwODMwMDA1 +NDMyWhgPMjAyMTA4MzAwMDU0MzJaMAAwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIB +CgKCAQEAtnjLm1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmq +nuGrBOUfgbmH3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWir +Gu0oDRzhWLHe1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqI +qpOynJB02thXrTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06 +GkwLFJHNv2tU+tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3Vus +pVz+6pU2xgl3nrAVMQHB4fReQPH0pQIDAQABow0wCzAJBgNVHT4EAgUAMAsGCSqG +SIb3DQEBBQMBAA== +-----END CERTIFICATE----- diff --git a/test/certs/ext-noRevAvail.pem b/test/certs/ext-noRevAvail.pem new file mode 100644 index 0000000000..23bf49b985 --- /dev/null +++ b/test/certs/ext-noRevAvail.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBiTCCAXWgAwIBAgIDAQIDMAsGCSqGSIb3DQEBBTAAMCIYDzIwMjEwOTE1MDAw +OTM1WhgPMjAyMTA5MTUwMDA5MzVaMAAwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIB +CgKCAQEAtnjLm1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmq +nuGrBOUfgbmH3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWir +Gu0oDRzhWLHe1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqI +qpOynJB02thXrTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06 +GkwLFJHNv2tU+tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3Vus +pVz+6pU2xgl3nrAVMQHB4fReQPH0pQIDAQABoxAwDjAMBgNVHTgBAf8EAgUAMAsG +CSqGSIb3DQEBBQMBAA== +-----END CERTIFICATE----- diff --git a/test/certs/ext-sOAIdentifier.pem b/test/certs/ext-sOAIdentifier.pem new file mode 100644 index 0000000000..7da3a3b448 --- /dev/null +++ b/test/certs/ext-sOAIdentifier.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBhjCCAXKgAwIBAgIDAQIDMAsGCSqGSIb3DQEBBTAAMCIYDzIwMjEwODMwMDA1 +NDA4WhgPMjAyMTA4MzAwMDU0MDhaMAAwggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIB +CgKCAQEAtnjLm1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmq +nuGrBOUfgbmH3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWir +Gu0oDRzhWLHe1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqI +qpOynJB02thXrTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06 +GkwLFJHNv2tU+tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3Vus +pVz+6pU2xgl3nrAVMQHB4fReQPH0pQIDAQABow0wCzAJBgNVHTIEAgUAMAsGCSqG +SIb3DQEBBQMBAA== +-----END CERTIFICATE----- diff --git a/test/certs/ext-singleUse.pem b/test/certs/ext-singleUse.pem new file mode 100644 index 0000000000..e72701c305 --- /dev/null +++ b/test/certs/ext-singleUse.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBrzCCAZmgAwIBAgIEDCI4TjANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQDDAZI +aSBtb20wIhgPMjAyMzA3MDExMzA4MDRaGA8yMDIzMDcwMTEzMDgwNFowETEPMA0G +A1UEAwwGSGkgbW9tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtnjL +m1ts1hC4fNNt3UnQD9y73bDXgioTyWYSI3ca/KNfuTydjFTEYAmqnuGrBOUfgbmH +3PRQ0AmpqljgWTb3d3K8H4UFvDWQTPSS21IMjm8oqd19nE5GxWirGu0oDRzhWLHe +1RZ7ZrohCPg/1Ocsy47QZuK2laFB0rEmrRWBmEYbDl3/wxf5XfqIqpOynJB02thX +rTCcTM7Rz1FqCFt/ZVZB5hKY2S+CTdE9OIVKlr4WHMfuvUYeOj06GkwLFJHNv2tU ++tovI3mYRxUuY4UupkS3MC+Otey7XKm1P+INjWWoegm6iCAt3VuspVz+6pU2xgl3 +nrAVMQHB4fReQPH0pQIDAQABow0wCzAJBgNVHUEEAgUAMA0GCSqGSIb3DQEBBQUA +AwEA +-----END CERTIFICATE----- diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t index 408ac40c7c..9bf011c188 100644 --- a/test/recipes/25-test_x509.t +++ b/test/recipes/25-test_x509.t @@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; setup("test_x509"); -plan tests => 37; +plan tests => 43; # Prevent MSys2 filename munging for arguments that look like file paths but # aren't @@ -110,6 +110,30 @@ cert_contains(srctop_file(@certs, "fake-gp.pem"), "2.16.528.1.1003.1.3.5.5.2-1-0000006666-Z-12345678-01.015-12345678", 1, 'x500 -- subjectAltName'); +cert_contains(srctop_file(@certs, "ext-noAssertion.pem"), + "No Assertion", + 1, 'X.509 Not Assertion Extension'); + +cert_contains(srctop_file(@certs, "ext-groupAC.pem"), + "Group Attribute Certificate", + 1, 'X.509 Group Attribute Certificate Extension'); + +cert_contains(srctop_file(@certs, "ext-sOAIdentifier.pem"), + "Source of Authority", + 1, 'X.509 Source of Authority Extension'); + +cert_contains(srctop_file(@certs, "ext-noRevAvail.pem"), + "No Revocation Available", + 1, 'X.509 No Revocation Available'); + +cert_contains(srctop_file(@certs, "ext-singleUse.pem"), + "Single Use", + 1, 'X509v3 Single Use'); + +cert_contains(srctop_file(@certs, "ext-indirectIssuer.pem"), + "Indirect Issuer", + 1, 'X.509 Indirect Issuer'); + sub test_errors { # actually tests diagnostics of OSSL_STORE my ($expected, $cert, @opts) = @_; my $infile = srctop_file(@certs, $cert); -- Gitee From db54b15061a8abfae4fd33db10fe204f69bfae2b Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 4 Sep 2023 14:37:09 +1000 Subject: [PATCH 08/16] remove redundant free of NULL Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- providers/fips/fipsprov.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 0a95d2364d..607ee11763 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -697,15 +697,8 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, /* Create a context. */ if ((*provctx = ossl_prov_ctx_new()) == NULL - || (libctx = OSSL_LIB_CTX_new()) == NULL) { - /* - * We free libctx separately here and only here because it hasn't - * been attached to *provctx. All other error paths below rely - * solely on fips_teardown. - */ - OSSL_LIB_CTX_free(libctx); + || (libctx = OSSL_LIB_CTX_new()) == NULL) goto err; - } if ((fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FIPS_PROV_INDEX)) == NULL) goto err; -- Gitee From 5fd3e3524639e6b3561203926b722ac14b676239 Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 4 Sep 2023 10:22:29 +1000 Subject: [PATCH 09/16] fix indentation Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- providers/implementations/rands/drbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c index 348d5f5080..1586288692 100644 --- a/providers/implementations/rands/drbg.c +++ b/providers/implementations/rands/drbg.c @@ -336,7 +336,7 @@ static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout, memset(&data, 0, sizeof(data)); data.drbg = drbg; if (!CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count, - dngbl->rand_nonce_lock)) + dngbl->rand_nonce_lock)) return 0; return ossl_prov_get_nonce(drbg->provctx, pout, min_len, max_len, &data, sizeof(data)); -- Gitee From bd4ba8309e648651e586f87c4058a8c64cf19415 Mon Sep 17 00:00:00 2001 From: Pauli Date: Wed, 13 Sep 2023 10:54:28 +1000 Subject: [PATCH 10/16] Provider cross version checks warning Add a warning note to the provider cross version checks indicating that a pull request branch will not be used if execution is set to on pull request. Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- .github/workflows/provider-compatibility.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/provider-compatibility.yml b/.github/workflows/provider-compatibility.yml index f118db1aee..e95a847522 100644 --- a/.github/workflows/provider-compatibility.yml +++ b/.github/workflows/provider-compatibility.yml @@ -10,6 +10,10 @@ name: Provider compatibility across versions + +# NOTE: if this is being run on pull_request, it will **not** use the pull +# request's branch. It is hardcoded to use the master branch. +# on: #[pull_request] schedule: - cron: '0 15 * * *' -- Gitee From 09d3c8ce5f95c4480b32e21924b7a1b36eabfe80 Mon Sep 17 00:00:00 2001 From: Pauli Date: Tue, 5 Sep 2023 10:16:49 +1000 Subject: [PATCH 11/16] fips selftest: avoid relying on a real RNG for self tests Rather than instantiate the private and primary DRBGs during the selftest, instead use a test RNG. This leaves the DRBG setup pristine and permits later replacement of the seed source despite the very early running power up self tests. Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- crypto/rand/rand_lib.c | 20 ++- include/crypto/rand.h | 4 + providers/fips/self_test.c | 17 +-- providers/fips/self_test_kats.c | 136 +++++++++++++-------- providers/implementations/rands/test_rng.c | 47 +++++-- util/perl/OpenSSL/paramnames.pm | 1 + 6 files changed, 154 insertions(+), 71 deletions(-) diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 8dd1d071e8..4630f19da0 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -345,6 +345,8 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif + if (num < 0) + return 0; rand = RAND_get0_private(ctx); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -354,8 +356,6 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, int RAND_priv_bytes(unsigned char *buf, int num) { - if (num < 0) - return 0; return RAND_priv_bytes_ex(NULL, buf, (size_t)num, 0); } @@ -374,6 +374,8 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif + if (num < 0) + return 0; rand = RAND_get0_public(ctx); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -383,8 +385,6 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, int RAND_bytes(unsigned char *buf, int num) { - if (num < 0) - return 0; return RAND_bytes_ex(NULL, buf, (size_t)num, 0); } @@ -738,6 +738,18 @@ EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx) return rand; } +#ifdef FIPS_MODULE +EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + + if (dgbl == NULL) + return NULL; + + return CRYPTO_THREAD_get_local(&dgbl->private); +} +#endif + int RAND_set0_public(OSSL_LIB_CTX *ctx, EVP_RAND_CTX *rand) { RAND_GLOBAL *dgbl = rand_get_global(ctx); diff --git a/include/crypto/rand.h b/include/crypto/rand.h index 758aeed4af..7345bf625f 100644 --- a/include/crypto/rand.h +++ b/include/crypto/rand.h @@ -125,4 +125,8 @@ void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, size_t ossl_pool_acquire_entropy(RAND_POOL *pool); int ossl_pool_add_nonce_data(RAND_POOL *pool); +# ifdef FIPS_MODULE +EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx); +# endif + #endif diff --git a/providers/fips/self_test.c b/providers/fips/self_test.c index 0be314692e..b8dc9817b2 100644 --- a/providers/fips/self_test.c +++ b/providers/fips/self_test.c @@ -19,6 +19,7 @@ #include "internal/e_os.h" #include "internal/tsan_assist.h" #include "prov/providercommon.h" +#include "crypto/rand.h" /* * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS @@ -406,14 +407,14 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) } /* Verify that the RNG has been restored properly */ - testrand = EVP_RAND_fetch(st->libctx, "TEST-RAND", NULL); - if (testrand == NULL - || (rng = RAND_get0_private(st->libctx)) == NULL - || strcmp(EVP_RAND_get0_name(EVP_RAND_CTX_get0_rand(rng)), - EVP_RAND_get0_name(testrand)) == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE); - goto end; - } + rng = ossl_rand_get0_private_noncreating(st->libctx); + if (rng != NULL) + if ((testrand = EVP_RAND_fetch(st->libctx, "TEST-RAND", NULL)) == NULL + || strcmp(EVP_RAND_get0_name(EVP_RAND_CTX_get0_rand(rng)), + EVP_RAND_get0_name(testrand)) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE); + goto end; + } ok = 1; end: diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c index bdf599aaad..82a7ac78fb 100644 --- a/providers/fips/self_test_kats.c +++ b/providers/fips/self_test_kats.c @@ -13,6 +13,7 @@ #include #include #include +#include "crypto/rand.h" #include "internal/cryptlib.h" #include "internal/nelem.h" #include "self_test.h" @@ -22,7 +23,7 @@ static int set_kat_drbg(OSSL_LIB_CTX *ctx, const unsigned char *entropy, size_t entropy_len, const unsigned char *nonce, size_t nonce_len, const unsigned char *persstr, size_t persstr_len); -static int reset_original_drbg(OSSL_LIB_CTX *ctx); +static int reset_main_drbg(OSSL_LIB_CTX *ctx); static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) @@ -701,39 +702,12 @@ static int self_test_signatures(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) return 0; if (!self_test_sign(t, st, libctx)) ret = 0; - if (!reset_original_drbg(libctx)) + if (!reset_main_drbg(libctx)) ret = 0; } return ret; } -/* - * Run the algorithm KAT's. - * Return 1 is successful, otherwise return 0. - * This runs all the tests regardless of if any fail. - */ -int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) -{ - int ret = 1; - - if (!self_test_digests(st, libctx)) - ret = 0; - if (!self_test_ciphers(st, libctx)) - ret = 0; - if (!self_test_signatures(st, libctx)) - ret = 0; - if (!self_test_kdfs(st, libctx)) - ret = 0; - if (!self_test_drbgs(st, libctx)) - ret = 0; - if (!self_test_kas(st, libctx)) - ret = 0; - if (!self_test_asym_ciphers(st, libctx)) - ret = 0; - - return ret; -} - /* * Swap the library context DRBG for KAT testing * @@ -745,13 +719,12 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) */ /* - * The default private DRBG of the library context, saved for the duration - * of KAT testing. + * Replacement "random" sources + * main_rand is used for most tests and it's set to generate mode. + * kat_rand is used for KATs where specific input is mandated. */ -static EVP_RAND_CTX *saved_rand = NULL; - -/* Replacement "random" source */ static EVP_RAND_CTX *kat_rand = NULL; +static EVP_RAND_CTX *main_rand = NULL; static int set_kat_drbg(OSSL_LIB_CTX *ctx, const unsigned char *entropy, size_t entropy_len, @@ -765,7 +738,7 @@ static int set_kat_drbg(OSSL_LIB_CTX *ctx, }; /* If not NULL, we didn't cleanup from last call: BAD */ - if (kat_rand != NULL || saved_rand != NULL) + if (kat_rand != NULL) return 0; rand = EVP_RAND_fetch(ctx, "TEST-RAND", NULL); @@ -777,7 +750,8 @@ static int set_kat_drbg(OSSL_LIB_CTX *ctx, if (parent_rand == NULL) goto err; - drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength); + drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, + &strength); if (!EVP_RAND_CTX_set_params(parent_rand, drbg_params)) goto err; @@ -810,37 +784,30 @@ static int set_kat_drbg(OSSL_LIB_CTX *ctx, if (!EVP_RAND_instantiate(kat_rand, strength, 0, persstr, persstr_len, NULL)) goto err; + /* When we set the new private generator this one is freed, so upref it */ + if (!EVP_RAND_CTX_up_ref(main_rand)) + goto err; + /* Update the library context DRBG */ - if ((saved_rand = RAND_get0_private(ctx)) != NULL) - /* Avoid freeing this since we replace it */ - if (!EVP_RAND_CTX_up_ref(saved_rand)) { - saved_rand = NULL; - goto err; - } if (RAND_set0_private(ctx, kat_rand) > 0) { /* Keeping a copy to verify zeroization */ if (EVP_RAND_CTX_up_ref(kat_rand)) return 1; - if (saved_rand != NULL) - RAND_set0_private(ctx, saved_rand); + RAND_set0_private(ctx, main_rand); } err: EVP_RAND_CTX_free(parent_rand); - EVP_RAND_CTX_free(saved_rand); EVP_RAND_CTX_free(kat_rand); - kat_rand = saved_rand = NULL; + kat_rand = NULL; return 0; } -static int reset_original_drbg(OSSL_LIB_CTX *ctx) { +static int reset_main_drbg(OSSL_LIB_CTX *ctx) { int ret = 1; - if (saved_rand != NULL) { - if (!RAND_set0_private(ctx, saved_rand)) - ret = 0; - saved_rand = NULL; - } + if (!RAND_set0_private(ctx, main_rand)) + ret = 0; if (kat_rand != NULL) { if (!EVP_RAND_uninstantiate(kat_rand) || !EVP_RAND_verify_zeroization(kat_rand)) @@ -851,3 +818,68 @@ static int reset_original_drbg(OSSL_LIB_CTX *ctx) { return ret; } +static int setup_main_random(OSSL_LIB_CTX *libctx) +{ + OSSL_PARAM drbg_params[3] = { + OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END + }; + unsigned int strength = 256, generate = 1; + EVP_RAND *rand; + + rand = EVP_RAND_fetch(libctx, "TEST-RAND", NULL); + if (rand == NULL) + return 0; + + main_rand = EVP_RAND_CTX_new(rand, NULL); + EVP_RAND_free(rand); + if (main_rand == NULL) + goto err; + + drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_GENERATE, + &generate); + drbg_params[1] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, + &strength); + + if (!EVP_RAND_instantiate(main_rand, strength, 0, NULL, 0, drbg_params)) + goto err; + return 1; + err: + EVP_RAND_CTX_free(main_rand); + return 0; +} + +/* + * Run the algorithm KAT's. + * Return 1 is successful, otherwise return 0. + * This runs all the tests regardless of if any fail. + */ +int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +{ + EVP_RAND_CTX *saved_rand = ossl_rand_get0_private_noncreating(libctx); + int ret = 1; + + if (!setup_main_random(libctx) + || !RAND_set0_private(libctx, main_rand)) { + EVP_RAND_CTX_free(main_rand); + return 0; + } + + if (!self_test_digests(st, libctx)) + ret = 0; + if (!self_test_ciphers(st, libctx)) + ret = 0; + if (!self_test_signatures(st, libctx)) + ret = 0; + if (!self_test_kdfs(st, libctx)) + ret = 0; + if (!self_test_drbgs(st, libctx)) + ret = 0; + if (!self_test_kas(st, libctx)) + ret = 0; + if (!self_test_asym_ciphers(st, libctx)) + ret = 0; + + RAND_set0_private(libctx, saved_rand); + return ret; +} + diff --git a/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c index bbea11cd6b..0006468d06 100644 --- a/providers/implementations/rands/test_rng.c +++ b/providers/implementations/rands/test_rng.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -39,6 +40,7 @@ static OSSL_FUNC_rand_get_seed_fn test_rng_get_seed; typedef struct { void *provctx; + unsigned int generate; int state; unsigned int strength; size_t max_request; @@ -99,16 +101,30 @@ static int test_rng_uninstantiate(void *vtest) return 1; } +static unsigned char gen_byte(PROV_TEST_RNG *t) +{ + return rand() & 0xff; +} + static int test_rng_generate(void *vtest, unsigned char *out, size_t outlen, unsigned int strength, int prediction_resistance, const unsigned char *adin, size_t adin_len) { PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; + size_t i; - if (strength > t->strength || t->entropy_len - t->entropy_pos < outlen) + if (strength > t->strength) return 0; - memcpy(out, t->entropy + t->entropy_pos, outlen); - t->entropy_pos += outlen; + if (t->generate) { + for (i = 0; i < outlen; i++) + out[i] = gen_byte(t); + } else { + if (t->entropy_len - t->entropy_pos < outlen) + return 0; + + memcpy(out, t->entropy + t->entropy_pos, outlen); + t->entropy_pos += outlen; + } return 1; } @@ -123,15 +139,23 @@ static int test_rng_reseed(ossl_unused void *vtest, } static size_t test_rng_nonce(void *vtest, unsigned char *out, - unsigned int strength, - ossl_unused size_t min_noncelen, + unsigned int strength, size_t min_noncelen, ossl_unused size_t max_noncelen) { PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest; + size_t i; - if (t->nonce == NULL || strength > t->strength) + if (strength > t->strength) return 0; + if (t->generate) { + for (i = 0; i < min_noncelen; i++) + out[i] = gen_byte(t); + return min_noncelen; + } + + if (t->nonce == NULL) + return 0; if (out != NULL) memcpy(out, t->nonce, t->nonce_len); return t->nonce_len; @@ -153,6 +177,10 @@ static int test_rng_get_ctx_params(void *vtest, OSSL_PARAM params[]) p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST); if (p != NULL && !OSSL_PARAM_set_size_t(p, t->max_request)) return 0; + + p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_GENERATE); + if (p != NULL && OSSL_PARAM_set_uint(p, t->generate)) + return 0; return 1; } @@ -163,6 +191,7 @@ static const OSSL_PARAM *test_rng_gettable_ctx_params(ossl_unused void *vtest, OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), + OSSL_PARAM_uint(OSSL_RAND_PARAM_GENERATE, NULL), OSSL_PARAM_END }; return known_gettable_ctx_params; @@ -203,9 +232,12 @@ static int test_rng_set_ctx_params(void *vtest, const OSSL_PARAM params[]) } p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_MAX_REQUEST); - if (p != NULL && !OSSL_PARAM_get_size_t(p, &t->max_request)) + if (p != NULL && !OSSL_PARAM_get_size_t(p, &t->max_request)) return 0; + p = OSSL_PARAM_locate_const(params, OSSL_RAND_PARAM_GENERATE); + if (p != NULL && !OSSL_PARAM_get_uint(p, &t->generate)) + return 0; return 1; } @@ -217,6 +249,7 @@ static const OSSL_PARAM *test_rng_settable_ctx_params(ossl_unused void *vtest, OSSL_PARAM_octet_string(OSSL_RAND_PARAM_TEST_NONCE, NULL, 0), OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), + OSSL_PARAM_uint(OSSL_RAND_PARAM_GENERATE, NULL), OSSL_PARAM_END }; return known_settable_ctx_params; diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm index a5126858e7..c37ed7815f 100644 --- a/util/perl/OpenSSL/paramnames.pm +++ b/util/perl/OpenSSL/paramnames.pm @@ -198,6 +198,7 @@ my %params = ( 'RAND_PARAM_MAX_REQUEST' => "max_request", 'RAND_PARAM_TEST_ENTROPY' => "test_entropy", 'RAND_PARAM_TEST_NONCE' => "test_nonce", + 'RAND_PARAM_GENERATE' => "generate", # RAND/DRBG names 'DRBG_PARAM_RESEED_REQUESTS' => "reseed_requests", -- Gitee From feccd2a2c6a6ee4f396733bd0933a62dfd54777c Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 25 Sep 2023 14:25:58 +1000 Subject: [PATCH 12/16] rand: add extra error code Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- crypto/err/openssl.txt | 1 + crypto/rand/rand_err.c | 4 +++- include/crypto/randerr.h | 2 +- include/openssl/randerr.h | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 3eeaa6d5d5..6952560d86 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1154,6 +1154,7 @@ RAND_R_FWRITE_ERROR:123:Error writing file RAND_R_GENERATE_ERROR:112:generate error RAND_R_INSUFFICIENT_DRBG_STRENGTH:139:insufficient drbg strength RAND_R_INTERNAL_ERROR:113:internal error +RAND_R_INVALID_PROPERTY_QUERY:137:invalid property query RAND_R_IN_ERROR_STATE:114:in error state RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file RAND_R_NOT_INSTANTIATED:115:not instantiated diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c index b9c2bf1760..41a4c9cdea 100644 --- a/crypto/rand/rand_err.c +++ b/crypto/rand/rand_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 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 @@ -51,6 +51,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = { {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INSUFFICIENT_DRBG_STRENGTH), "insufficient drbg strength"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INVALID_PROPERTY_QUERY), + "invalid property query"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE), "Not a regular file"}, diff --git a/include/crypto/randerr.h b/include/crypto/randerr.h index 832a8b7d36..6e2eb0716f 100644 --- a/include/crypto/randerr.h +++ b/include/crypto/randerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2023 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 diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h index b5e08e4362..04880374a3 100644 --- a/include/openssl/randerr.h +++ b/include/openssl/randerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 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 @@ -41,6 +41,7 @@ # define RAND_R_GENERATE_ERROR 112 # define RAND_R_INSUFFICIENT_DRBG_STRENGTH 139 # define RAND_R_INTERNAL_ERROR 113 +# define RAND_R_INVALID_PROPERTY_QUERY 137 # define RAND_R_IN_ERROR_STATE 114 # define RAND_R_NOT_A_REGULAR_FILE 122 # define RAND_R_NOT_INSTANTIATED 115 -- Gitee From 97ec9f5917569e9bf5e0da8842f94207fccda549 Mon Sep 17 00:00:00 2001 From: Pauli Date: Tue, 5 Sep 2023 12:51:05 +1000 Subject: [PATCH 13/16] fips: use seed source requested Fixes #21909 Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- crypto/initthread.c | 2 +- crypto/provider_core.c | 68 +++++++++++-- crypto/rand/prov_seed.c | 66 ++++++++++++- crypto/rand/rand_lib.c | 100 +++++++++++++++++--- doc/internal/man3/ossl_rand_get_entropy.pod | 45 +++++++-- doc/man7/EVP_RAND-TEST-RAND.pod | 7 ++ doc/man7/provider-base.pod | 28 +++++- include/crypto/rand.h | 17 +++- include/openssl/core_dispatch.h | 11 +++ providers/baseprov.c | 8 ++ providers/common/provider_seeding.c | 53 +++++++++-- 11 files changed, 350 insertions(+), 55 deletions(-) diff --git a/crypto/initthread.c b/crypto/initthread.c index 03586bcbca..54a33c3286 100644 --- a/crypto/initthread.c +++ b/crypto/initthread.c @@ -257,7 +257,7 @@ void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx) if (tlocal == NULL) return NULL; - if (!CRYPTO_THREAD_init_local(tlocal, NULL)) { + if (!CRYPTO_THREAD_init_local(tlocal, NULL)) { goto err; } diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 7f5e48f26c..266934937c 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -1930,10 +1930,12 @@ OSSL_FUNC_BIO_free_fn ossl_core_bio_free; OSSL_FUNC_BIO_vprintf_fn ossl_core_bio_vprintf; OSSL_FUNC_BIO_vsnprintf_fn BIO_vsnprintf; static OSSL_FUNC_self_test_cb_fn core_self_test_get_callback; -OSSL_FUNC_get_entropy_fn ossl_rand_get_entropy; -OSSL_FUNC_cleanup_entropy_fn ossl_rand_cleanup_entropy; -OSSL_FUNC_get_nonce_fn ossl_rand_get_nonce; -OSSL_FUNC_cleanup_nonce_fn ossl_rand_cleanup_nonce; +static OSSL_FUNC_get_user_entropy_fn rand_get_user_entropy; +static OSSL_FUNC_get_entropy_fn rand_get_entropy; +static OSSL_FUNC_cleanup_entropy_fn rand_cleanup_entropy; +static OSSL_FUNC_get_user_nonce_fn rand_get_user_nonce; +static OSSL_FUNC_get_nonce_fn rand_get_nonce; +static OSSL_FUNC_cleanup_nonce_fn rand_cleanup_nonce; #endif OSSL_FUNC_CRYPTO_malloc_fn CRYPTO_malloc; OSSL_FUNC_CRYPTO_zalloc_fn CRYPTO_zalloc; @@ -2094,6 +2096,54 @@ static void core_self_test_get_callback(OPENSSL_CORE_CTX *libctx, OSSL_SELF_TEST_get_callback((OSSL_LIB_CTX *)libctx, cb, cbarg); } +static size_t rand_get_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + return ossl_rand_get_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, entropy, min_len, max_len); +} + +static size_t rand_get_user_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + return ossl_rand_get_user_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, entropy, min_len, max_len); +} + +static void rand_cleanup_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + +static size_t rand_get_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + return ossl_rand_get_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, min_len, max_len, salt, salt_len); +} + +static size_t rand_get_user_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + return ossl_rand_get_user_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, min_len, max_len, salt, salt_len); +} + +static void rand_cleanup_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + static const char *core_provider_get0_name(const OSSL_CORE_HANDLE *prov) { return OSSL_PROVIDER_get0_name((const OSSL_PROVIDER *)prov); @@ -2187,10 +2237,12 @@ static const OSSL_DISPATCH core_dispatch_[] = { { OSSL_FUNC_BIO_VPRINTF, (void (*)(void))ossl_core_bio_vprintf }, { OSSL_FUNC_BIO_VSNPRINTF, (void (*)(void))BIO_vsnprintf }, { OSSL_FUNC_SELF_TEST_CB, (void (*)(void))core_self_test_get_callback }, - { OSSL_FUNC_GET_ENTROPY, (void (*)(void))ossl_rand_get_entropy }, - { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))ossl_rand_cleanup_entropy }, - { OSSL_FUNC_GET_NONCE, (void (*)(void))ossl_rand_get_nonce }, - { OSSL_FUNC_CLEANUP_NONCE, (void (*)(void))ossl_rand_cleanup_nonce }, + { OSSL_FUNC_GET_ENTROPY, (void (*)(void))rand_get_entropy }, + { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))rand_cleanup_entropy }, + { OSSL_FUNC_GET_NONCE, (void (*)(void))rand_get_nonce }, + { OSSL_FUNC_CLEANUP_NONCE, (void (*)(void))rand_cleanup_nonce }, + { OSSL_FUNC_GET_USER_ENTROPY, (void (*)(void))rand_get_user_entropy }, + { OSSL_FUNC_GET_USER_NONCE, (void (*)(void))rand_get_user_nonce }, #endif { OSSL_FUNC_CRYPTO_MALLOC, (void (*)(void))CRYPTO_malloc }, { OSSL_FUNC_CRYPTO_ZALLOC, (void (*)(void))CRYPTO_zalloc }, diff --git a/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c index 546c204094..96c73f7e66 100644 --- a/crypto/rand/prov_seed.c +++ b/crypto/rand/prov_seed.c @@ -7,12 +7,14 @@ * https://www.openssl.org/source/license.html */ +#include "rand_local.h" #include "crypto/rand.h" #include "crypto/rand_pool.h" +#include "internal/core.h" #include #include -size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_entropy(ossl_unused OSSL_LIB_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len) { @@ -38,14 +40,46 @@ size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, return ret; } -void ossl_rand_cleanup_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + unsigned char *buf; + EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx); + size_t ret; + + if (rng == NULL) + return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len); + + /* Determine how many bytes to generate */ + ret = entropy > 0 ? (size_t)(7 + entropy) / 8 : min_len; + if (ret < min_len) + ret = min_len; + else if (ret > max_len) + ret = max_len; + + /* Allocate the return buffer */ + if ((buf = OPENSSL_secure_malloc(ret)) == NULL) + return 0; + + /* Fill the buffer */ + if (!EVP_RAND_generate(rng, buf, ret, entropy, 0, NULL, 0)) { + OPENSSL_free(buf); + return 0; + } + *pout = buf; + return ret; +} + +void ossl_rand_cleanup_entropy(ossl_unused OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len) { OPENSSL_secure_clear_free(buf, len); } -size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, - unsigned char **pout, size_t min_len, size_t max_len, +size_t ossl_rand_get_nonce(ossl_unused OSSL_LIB_CTX *ctx, + unsigned char **pout, + size_t min_len, ossl_unused size_t max_len, const void *salt, size_t salt_len) { size_t ret = 0; @@ -69,7 +103,29 @@ size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, return ret; } -void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + unsigned char *buf; + EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx); + + if (rng == NULL) + return ossl_rand_get_nonce(ctx, pout, min_len, max_len, salt, salt_len); + + if ((buf = OPENSSL_malloc(min_len)) == NULL) + return 0; + + if (!EVP_RAND_generate(rng, buf, min_len, 0, 0, salt, salt_len)) { + OPENSSL_free(buf); + return 0; + } + *pout = buf; + return min_len; +} + +void ossl_rand_cleanup_nonce(ossl_unused OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len) { OPENSSL_clear_free(buf, len); diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 4630f19da0..46e294a378 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -30,6 +30,7 @@ # include "crypto/rand_pool.h" # include "prov/seeding.h" # include "internal/e_os.h" +# include "internal/property.h" # ifndef OPENSSL_NO_ENGINE /* non-NULL if default_RAND_meth is ENGINE-provided */ @@ -345,8 +346,6 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif - if (num < 0) - return 0; rand = RAND_get0_private(ctx); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -356,6 +355,8 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, int RAND_priv_bytes(unsigned char *buf, int num) { + if (num < 0) + return 0; return RAND_priv_bytes_ex(NULL, buf, (size_t)num, 0); } @@ -374,8 +375,6 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif - if (num < 0) - return 0; rand = RAND_get0_public(ctx); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -385,6 +384,8 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, int RAND_bytes(unsigned char *buf, int num) { + if (num < 0) + return 0; return RAND_bytes_ex(NULL, buf, (size_t)num, 0); } @@ -534,29 +535,104 @@ static EVP_RAND_CTX *rand_new_seed(OSSL_LIB_CTX *libctx) { EVP_RAND *rand; RAND_GLOBAL *dgbl = rand_get_global(libctx); - EVP_RAND_CTX *ctx; - char *name; + EVP_RAND_CTX *ctx = NULL; + const char *propq = dgbl->seed_propq; + char *name, *props = NULL; + size_t props_len; + OSSL_PROPERTY_LIST *pl1, *pl2, *pl3 = NULL; if (dgbl == NULL) return NULL; - name = dgbl->seed_name != NULL ? dgbl->seed_name : "SEED-SRC"; - rand = EVP_RAND_fetch(libctx, name, dgbl->seed_propq); + if (dgbl->seed_name != NULL) { + name = dgbl->seed_name; + } else { + /* + * Default to our internal seed source. This isn't part of the FIPS + * provider so we need to override any FIPS properties. + */ + if (propq == NULL || *propq == '\0') { + propq = "-fips"; + } else { + pl1 = ossl_parse_query(libctx, propq, 1); + if (pl1 == NULL) { + ERR_raise(ERR_LIB_RAND, RAND_R_INVALID_PROPERTY_QUERY); + return NULL; + } + pl2 = ossl_parse_query(libctx, "-fips", 1); + if (pl2 == NULL) { + ossl_property_free(pl1); + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + return NULL; + } + pl3 = ossl_property_merge(pl2, pl1); + ossl_property_free(pl1); + ossl_property_free(pl2); + if (pl3 == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + return NULL; + } + props_len = ossl_property_list_to_string(libctx, pl3, NULL, 0); + if (props_len == 0) { + /* Shouldn't happen since we added a query element */ + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + goto err; + } else { + props = OPENSSL_malloc(props_len); + if (props == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + goto err; + } + if (ossl_property_list_to_string(libctx, pl3, + props, props_len) == 0) { + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + goto err; + } + ossl_property_free(pl3); + pl3 = NULL; + propq = props; + } + } + name = "SEED-SRC"; + } + + rand = EVP_RAND_fetch(libctx, name, propq); if (rand == NULL) { ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG); - return NULL; + goto err; } ctx = EVP_RAND_CTX_new(rand, NULL); EVP_RAND_free(rand); if (ctx == NULL) { ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG); - return NULL; + goto err; } if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, NULL)) { ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG); EVP_RAND_CTX_free(ctx); - return NULL; + goto err; } + OPENSSL_free(props); return ctx; + err: + EVP_RAND_CTX_free(ctx); + ossl_property_free(pl3); + OPENSSL_free(props); + return NULL; +} + +EVP_RAND_CTX *ossl_rand_get0_seed_noncreating(OSSL_LIB_CTX *ctx) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + EVP_RAND_CTX *ret; + + if (dgbl == NULL) + return NULL; + + if (!CRYPTO_THREAD_read_lock(dgbl->lock)) + return NULL; + ret = dgbl->seed; + CRYPTO_THREAD_unlock(dgbl->lock); + return ret; } #endif @@ -882,7 +958,7 @@ int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed, if (dgbl == NULL) return 0; - if (dgbl->primary != NULL) { + if (dgbl->seed != NULL) { ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED); return 0; } diff --git a/doc/internal/man3/ossl_rand_get_entropy.pod b/doc/internal/man3/ossl_rand_get_entropy.pod index 4da3f1f4d9..48343b6fe0 100644 --- a/doc/internal/man3/ossl_rand_get_entropy.pod +++ b/doc/internal/man3/ossl_rand_get_entropy.pod @@ -2,8 +2,8 @@ =head1 NAME -ossl_rand_get_entropy, ossl_rand_cleanup_entropy, -ossl_rand_get_nonce, ossl_rand_cleanup_nonce +ossl_rand_get_entropy, ossl_rand_get_user_entropy, ossl_rand_cleanup_entropy, +ossl_rand_get_nonce, ossl_rand_get_user_nonce, ossl_rand_cleanup_nonce - get seed material from the operating system =head1 SYNOPSIS @@ -13,11 +13,17 @@ ossl_rand_get_nonce, ossl_rand_cleanup_nonce size_t ossl_rand_get_entropy(OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); + size_t ossl_rand_get_user_entropy(OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); void ossl_rand_cleanup_entropy(OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); size_t ossl_rand_get_nonce(OSSL_CORE_HANDLE *handle, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len); + size_t ossl_rand_get_user_nonce(OSSL_CORE_HANDLE *handle, unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len); void ossl_rand_cleanup_nonce(OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); @@ -29,9 +35,14 @@ stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length is returned to the caller. +ossl_rand_get_user_entropy() is the same as ossl_rand_get_entropy() +except that it retrieves the seeding material from the library context's +DRBG seed source. By default this is the operating system but it can +be changed by calling L. + ossl_rand_cleanup_entropy() cleanses and frees any storage allocated by -ossl_rand_get_entropy(). The seeding buffer is pointed to by I and is -of length I bytes. +ossl_rand_get_entropy() or ossl_rand_get_user_entropy(). The entropy +buffer is pointed to by I and is of length I bytes. ossl_rand_get_nonce() retrieves a nonce using the passed I parameter of length I and operating system specific information. @@ -41,18 +52,34 @@ The output is stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length returned to the caller. +ossl_rand_get_user_nonce() is the same as ossl_rand_get_nonce() except +that it retrieves the seeding material from the library context's DRBG +seed source. By default this is the operating system but it can be +changed by calling L. + ossl_rand_cleanup_nonce() cleanses and frees any storage allocated by -ossl_rand_get_nonce(). The nonce buffer is pointed to by I and is -of length I bytes. +ossl_rand_get_nonce() or ossl_rand_get_user_nonce(). The nonce buffer +is pointed to by I and is of length I bytes. + +=head1 NOTES + +FIPS providers 3.0.0, 3.0.8 and 3.0.9 incorrectly pass a provider +internal pointer to ossl_rand_get_entropy(), ossl_rand_cleanup_entropy(), +ossl_rand_get_nonce() and ossl_rand_cleanup_nonce(). This pointer cannot +be safely dereferenced. =head1 RETURN VALUES -ossl_rand_get_entropy() and ossl_rand_get_nonce() return the number of bytes -in I<*pout> or 0 on error. +ossl_rand_get_entropy(), ossl_rand_get_user_entropy(), +ossl_rand_get_nonce() and ossl_rand_get_user_nonce() return the number +of bytes in I<*pout> or 0 on error. =head1 HISTORY -The functions described here were all added in OpenSSL 3.0. +The functions ossl_rand_get_user_entropy() and ossl_rand_get_user_nonce() +were added in OpenSSL 3.0.12, 3.1.4 and 3.2.0. + +The remaining functions described here were all added in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/doc/man7/EVP_RAND-TEST-RAND.pod b/doc/man7/EVP_RAND-TEST-RAND.pod index ff5207565c..feab01431d 100644 --- a/doc/man7/EVP_RAND-TEST-RAND.pod +++ b/doc/man7/EVP_RAND-TEST-RAND.pod @@ -60,6 +60,13 @@ If there are insufficient data present to satisfy a call, an error is returned. Sets the bytes returned when the test generator is sent a nonce request. Each nonce request will return all of the bytes. +=item "generate" (B) + +If this parameter is zero, it will only emit the nonce and entropy data +supplied via the aforementioned parameters. Otherwise, low quality +non-cryptographic pseudorandom output is produced. This parameter defaults +to zero. + =back =head1 NOTES diff --git a/doc/man7/provider-base.pod b/doc/man7/provider-base.pod index 33d7fe7f55..eb9e8d3575 100644 --- a/doc/man7/provider-base.pod +++ b/doc/man7/provider-base.pod @@ -76,11 +76,17 @@ provider-base size_t get_entropy(const OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); + size_t get_user_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); void cleanup_entropy(const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); size_t get_nonce(const OSSL_CORE_HANDLE *handle, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len); + size_t get_user_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, size_t min_len, size_t max_len, + const void *salt, size_t salt_len); void cleanup_nonce(const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); @@ -171,8 +177,10 @@ provider): OPENSSL_cleanse OSSL_FUNC_OPENSSL_CLEANSE OSSL_SELF_TEST_set_callback OSSL_FUNC_SELF_TEST_CB ossl_rand_get_entropy OSSL_FUNC_GET_ENTROPY + ossl_rand_get_user_entropy OSSL_FUNC_GET_USER_ENTROPY ossl_rand_cleanup_entropy OSSL_FUNC_CLEANUP_ENTROPY ossl_rand_get_nonce OSSL_FUNC_GET_NONCE + ossl_rand_get_user_nonce OSSL_FUNC_GET_USER_NONCE ossl_rand_cleanup_nonce OSSL_FUNC_CLEANUP_NONCE provider_register_child_cb OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB provider_deregister_child_cb OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB @@ -302,9 +310,14 @@ output will have at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length is returned to the caller. On error, zero is returned. +get_user_entropy() is the same as get_entropy() except that it will +attempt to gather seed material via the seed source specified by a call to +L or via L. + cleanup_entropy() is used to clean up and free the buffer returned by -get_entropy(). The entropy pointer returned by get_entropy() is passed in -B and its length in B. +get_entropy() or get_user_entropy(). The entropy pointer returned by +get_entropy() or get_user_entropy() is passed in B and its length +in B. get_nonce() retrieves a nonce using the passed I parameter of length I and operating system specific information. @@ -314,9 +327,14 @@ The output is stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length returned to the caller. On error, zero is returned. -cleanup_nonce() is used to clean up and free the buffer returned by -get_nonce(). The nonce pointer returned by get_nonce() is passed in -B and its length in B. +get_user_nonce() is the same as get_nonce() except that it will attempt +to gather seed material via the seed source specified by a call to +L or via L. + +cleanup_nonce() is used to clean up and free the buffer returned +by get_nonce() or get_user_nonce(). The nonce pointer returned by +get_nonce() or get_user_nonce() is passed in B and its length +in B. provider_register_child_cb() registers callbacks for being informed about the loading and unloading of providers in the application's library context. diff --git a/include/crypto/rand.h b/include/crypto/rand.h index 7345bf625f..730be8b5d0 100644 --- a/include/crypto/rand.h +++ b/include/crypto/rand.h @@ -108,15 +108,21 @@ void ossl_random_add_conf_module(void); /* * Get and cleanup random seed material. */ -size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_entropy(OSSL_LIB_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len); -void ossl_rand_cleanup_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); +void ossl_rand_cleanup_entropy(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len); -size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_nonce(OSSL_LIB_CTX *ctx, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len); -void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx, unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len); +void ossl_rand_cleanup_nonce(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len); /* @@ -127,6 +133,7 @@ int ossl_pool_add_nonce_data(RAND_POOL *pool); # ifdef FIPS_MODULE EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx); +# else +EVP_RAND_CTX *ossl_rand_get0_seed_noncreating(OSSL_LIB_CTX *ctx); # endif - #endif diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 73f040285c..6c952f18aa 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -176,6 +176,10 @@ OSSL_CORE_MAKE_FUNC(int, BIO_vsnprintf, OSSL_CORE_MAKE_FUNC(int, BIO_ctrl, (OSSL_CORE_BIO *bio, int cmd, long num, void *ptr)) +/* New seeding functions prototypes with the 101-104 series */ +#define OSSL_FUNC_GET_USER_ENTROPY 98 +#define OSSL_FUNC_GET_USER_NONCE 99 + #define OSSL_FUNC_SELF_TEST_CB 100 OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK **cb, void **cbarg)) @@ -188,12 +192,19 @@ OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK ** OSSL_CORE_MAKE_FUNC(size_t, get_entropy, (const OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len)) +OSSL_CORE_MAKE_FUNC(size_t, get_user_entropy, (const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len)) OSSL_CORE_MAKE_FUNC(void, cleanup_entropy, (const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len)) OSSL_CORE_MAKE_FUNC(size_t, get_nonce, (const OSSL_CORE_HANDLE *handle, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len)) +OSSL_CORE_MAKE_FUNC(size_t, get_user_nonce, (const OSSL_CORE_HANDLE *handle, + unsigned char **pout, size_t min_len, + size_t max_len, const void *salt, + size_t salt_len)) OSSL_CORE_MAKE_FUNC(void, cleanup_nonce, (const OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len)) diff --git a/providers/baseprov.c b/providers/baseprov.c index 2e5dbe410f..6b8de7cb36 100644 --- a/providers/baseprov.c +++ b/providers/baseprov.c @@ -19,6 +19,7 @@ #include "prov/providercommon.h" #include "prov/implementations.h" #include "prov/provider_util.h" +#include "prov/names.h" /* * Forward declarations to ensure that interface functions are correctly @@ -90,6 +91,11 @@ static const OSSL_ALGORITHM base_store[] = { #undef STORE }; +static const OSSL_ALGORITHM base_rands[] = { + { PROV_NAMES_SEED_SRC, "provider=base", ossl_seed_src_functions }, + { NULL, NULL, NULL } +}; + static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id, int *no_cache) { @@ -101,6 +107,8 @@ static const OSSL_ALGORITHM *base_query(void *provctx, int operation_id, return base_decoder; case OSSL_OP_STORE: return base_store; + case OSSL_OP_RAND: + return base_rands; } return NULL; } diff --git a/providers/common/provider_seeding.c b/providers/common/provider_seeding.c index d67ddf7b13..f6463f8ada 100644 --- a/providers/common/provider_seeding.c +++ b/providers/common/provider_seeding.c @@ -9,12 +9,33 @@ #include #include "prov/seeding.h" +#include "prov/providercommon.h" static OSSL_FUNC_get_entropy_fn *c_get_entropy = NULL; +static OSSL_FUNC_get_user_entropy_fn *c_get_user_entropy = NULL; static OSSL_FUNC_cleanup_entropy_fn *c_cleanup_entropy = NULL; static OSSL_FUNC_get_nonce_fn *c_get_nonce = NULL; +static OSSL_FUNC_get_user_nonce_fn *c_get_user_nonce = NULL; static OSSL_FUNC_cleanup_nonce_fn *c_cleanup_nonce = NULL; +#ifdef FIPS_MODULE +/* + * The FIPS provider uses an internal library context which is what the + * passed provider context references. Since the seed source is external + * to the FIPS provider, this is the wrong one. We need to convert this + * to the correct core handle before up-calling libcrypto. + */ +# define CORE_HANDLE(provctx) \ + FIPS_get_core_handle(ossl_prov_ctx_get0_libctx(provctx)) +#else +/* + * The non-FIPS path *should* be unused because the full DRBG chain including + * seed source is instantiated. However, that might not apply for third + * party providers, so this is retained for compatibility. + */ +# define CORE_HANDLE(provctx) ossl_prov_ctx_get0_handle(provctx) +#endif + int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns) { for (; fns->function_id != 0; fns++) { @@ -29,12 +50,18 @@ int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns) case OSSL_FUNC_GET_ENTROPY: set_func(c_get_entropy, OSSL_FUNC_get_entropy(fns)); break; + case OSSL_FUNC_GET_USER_ENTROPY: + set_func(c_get_user_entropy, OSSL_FUNC_get_user_entropy(fns)); + break; case OSSL_FUNC_CLEANUP_ENTROPY: set_func(c_cleanup_entropy, OSSL_FUNC_cleanup_entropy(fns)); break; case OSSL_FUNC_GET_NONCE: set_func(c_get_nonce, OSSL_FUNC_get_nonce(fns)); break; + case OSSL_FUNC_GET_USER_NONCE: + set_func(c_get_user_nonce, OSSL_FUNC_get_user_nonce(fns)); + break; case OSSL_FUNC_CLEANUP_NONCE: set_func(c_cleanup_nonce, OSSL_FUNC_cleanup_nonce(fns)); break; @@ -47,31 +74,37 @@ int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns) size_t ossl_prov_get_entropy(PROV_CTX *prov_ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len) { - if (c_get_entropy == NULL) - return 0; - return c_get_entropy(ossl_prov_ctx_get0_handle(prov_ctx), - pout, entropy, min_len, max_len); + const OSSL_CORE_HANDLE *handle = CORE_HANDLE(prov_ctx); + + if (c_get_user_entropy != NULL) + return c_get_user_entropy(handle, pout, entropy, min_len, max_len); + if (c_get_entropy != NULL) + return c_get_entropy(handle, pout, entropy, min_len, max_len); + return 0; } void ossl_prov_cleanup_entropy(PROV_CTX *prov_ctx, unsigned char *buf, size_t len) { if (c_cleanup_entropy != NULL) - c_cleanup_entropy(ossl_prov_ctx_get0_handle(prov_ctx), buf, len); + c_cleanup_entropy(CORE_HANDLE(prov_ctx), buf, len); } size_t ossl_prov_get_nonce(PROV_CTX *prov_ctx, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len) { - if (c_get_nonce == NULL) - return 0; - return c_get_nonce(ossl_prov_ctx_get0_handle(prov_ctx), pout, - min_len, max_len, salt, salt_len); + const OSSL_CORE_HANDLE *handle = CORE_HANDLE(prov_ctx); + + if (c_get_user_nonce != NULL) + return c_get_user_nonce(handle, pout, min_len, max_len, salt, salt_len); + if (c_get_nonce != NULL) + return c_get_nonce(handle, pout, min_len, max_len, salt, salt_len); + return 0; } void ossl_prov_cleanup_nonce(PROV_CTX *prov_ctx, unsigned char *buf, size_t len) { if (c_cleanup_nonce != NULL) - c_cleanup_nonce(ossl_prov_ctx_get0_handle(prov_ctx), buf, len); + c_cleanup_nonce(CORE_HANDLE(prov_ctx), buf, len); } -- Gitee From 1f4e3ca5c2a0418b6eae5e73d2f1c80d50ae1228 Mon Sep 17 00:00:00 2001 From: Pauli Date: Fri, 22 Sep 2023 08:46:31 +1000 Subject: [PATCH 14/16] evp_test: recondition cipher dupctx FIPS version check. Until the cipher dupctx is properly implemented in 3.1 and 3.0 the check is wrong. This should be reverted once the implemenation has been done. Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- test/evp_test.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index 309ab94c21..bd1a7cc122 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -739,9 +739,7 @@ static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign, int ok = 0, tmplen, chunklen, tmpflen, i; EVP_CIPHER_CTX *ctx_base = NULL; EVP_CIPHER_CTX *ctx = NULL, *duped; - int fips_dupctx_supported = (fips_provider_version_ge(libctx, 3, 0, 12) - && fips_provider_version_lt(libctx, 3, 1, 0)) - || fips_provider_version_ge(libctx, 3, 1, 4); + int fips_dupctx_supported = fips_provider_version_ge(libctx, 3, 2, 0); t->err = "TEST_FAILURE"; if (!TEST_ptr(ctx_base = EVP_CIPHER_CTX_new())) -- Gitee From e1fb99b774075c0bab227a386463d3aef5aad5da Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Mon, 25 Sep 2023 16:44:47 +0100 Subject: [PATCH 15/16] Fix a mem leak when the FIPS provider is used in a different thread We were neglecting to register the main thread to receive thread stop notifications. This is important if the thread that starts the FIPS provider is not the same one that is used when OPENSSL_cleanup() is called. Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/21964) Signed-off-by: fly2x --- crypto/initthread.c | 22 ++++++++++++++++++++-- include/crypto/context.h | 1 + providers/fips/fipsprov.c | 9 +++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/crypto/initthread.c b/crypto/initthread.c index 54a33c3286..23ad0a0739 100644 --- a/crypto/initthread.c +++ b/crypto/initthread.c @@ -249,6 +249,15 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx) #else +static void ossl_arg_thread_stop(void *arg); + +/* Register the current thread so that we are informed if it gets stopped */ +int ossl_thread_register_fips(OSSL_LIB_CTX *libctx) +{ + return c_thread_start(FIPS_get_core_handle(libctx), ossl_arg_thread_stop, + libctx); +} + void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx) { THREAD_EVENT_HANDLER **hands = NULL; @@ -268,6 +277,16 @@ void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx) if (!CRYPTO_THREAD_set_local(tlocal, hands)) goto err; + /* + * We should ideally call ossl_thread_register_fips() here. This function + * is called during the startup of the FIPS provider and we need to ensure + * that the main thread is registered to receive thread callbacks in order + * to free |hands| that we allocated above. However we are too early in + * the FIPS provider initialisation that FIPS_get_core_handle() doesn't work + * yet. So we defer this to the main provider OSSL_provider_init_int() + * function. + */ + return tlocal; err: OPENSSL_free(hands); @@ -379,8 +398,7 @@ int ossl_init_thread_start(const void *index, void *arg, * libcrypto to tell us about later thread stop events. c_thread_start * is a callback to libcrypto defined in fipsprov.c */ - if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_arg_thread_stop, - ctx)) + if (!ossl_thread_register_fips(ctx)) return 0; } #endif diff --git a/include/crypto/context.h b/include/crypto/context.h index 56c68f4ec1..af81e15e1d 100644 --- a/include/crypto/context.h +++ b/include/crypto/context.h @@ -21,6 +21,7 @@ void *ossl_child_prov_ctx_new(OSSL_LIB_CTX *); void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *); void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *); void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *); +int ossl_thread_register_fips(OSSL_LIB_CTX *); void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *); void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *); #if defined(OPENSSL_THREADS) diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 607ee11763..7ec409710b 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -705,6 +705,15 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, fgbl->handle = handle; + /* + * We need to register this thread to receive thread lifecycle callbacks. + * This wouldn't matter if the current thread is also the same thread that + * closes the FIPS provider down. But if that happens on a different thread + * then memory leaks could otherwise occur. + */ + if (!ossl_thread_register_fips(libctx)) + goto err; + /* * We did initial set up of selftest_params in a local copy, because we * could not create fgbl until c_CRYPTO_zalloc was defined in the loop -- Gitee From f1827489f95baa4d7bab52ce6051fcc5566faed9 Mon Sep 17 00:00:00 2001 From: "Randall S. Becker" Date: Sat, 23 Sep 2023 15:38:13 +0100 Subject: [PATCH 16/16] Move e_os2.h up in quictestlib.c to allow symbol definition consistency. Fixes: #22178 Signed-of-by: Randall S. Becker Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22179) Signed-off-by: fly2x --- test/helpers/quictestlib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index 17da14766f..8d71d6002f 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -10,6 +10,7 @@ #include #include #include +#include "internal/e_os.h" /* For struct timeval */ #include "quictestlib.h" #include "ssltestlib.h" #include "../testutil.h" -- Gitee