From 85e3440a27a55359f5da53837e463a6f5476ea76 Mon Sep 17 00:00:00 2001 From: openssl-machine Date: Tue, 9 Jun 2026 11:54:36 +0000 Subject: [PATCH 001/189] Prepare for 3.5.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Neil Horman Reviewed-by: Saša Nedvědický MergeDate: Tue Jun 9 11:54:39 2026 Release: yes --- CHANGES.md | 4 ++++ NEWS.md | 4 ++++ VERSION.dat | 6 +++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c1c29eb55f04c..cda2afee32127 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,6 +28,10 @@ OpenSSL Releases OpenSSL 3.5 ----------- +### Changes between 3.5.7 and 3.5.8 [xx XXX xxxx] + + * none yet + ### Changes between 3.5.6 and 3.5.7 [9 Jun 2026] * Fixed heap use-after-free in `PKCS7_verify()`. diff --git a/NEWS.md b/NEWS.md index 04d0bd72c7f53..ef65780d2702b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,6 +23,10 @@ OpenSSL Releases OpenSSL 3.5 ----------- +### Major changes between OpenSSL 3.5.7 and OpenSSL 3.5.8 [under development] + + * none + ### Major changes between OpenSSL 3.5.6 and OpenSSL 3.5.7 [9 Jun 2026] OpenSSL 3.5.7 is a security patch release. The most severe CVE fixed diff --git a/VERSION.dat b/VERSION.dat index a297eee91e171..c675e8bc3b8e4 100644 --- a/VERSION.dat +++ b/VERSION.dat @@ -1,7 +1,7 @@ MAJOR=3 MINOR=5 -PATCH=7 -PRE_RELEASE_TAG= +PATCH=8 +PRE_RELEASE_TAG=dev BUILD_METADATA= -RELEASE_DATE="9 Jun 2026" +RELEASE_DATE="" SHLIB_VERSION=3 From 5709e1395d820ab9cd2827c992d1efb702915604 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 23 Oct 2025 21:26:51 +0200 Subject: [PATCH 002/189] cmp_vfy.c: small fixes on content and layout of diagnostics on failure validating signature-based protection of CMP messages Reviewed-by: Daniel Kubec Reviewed-by: Milan Broz Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jun 10 06:38:59 2026 (Merged from https://github.com/openssl/openssl/pull/28986) (cherry picked from commit 0a6b6664a48f0e499fc14aeafd9cb408b261f1ad) --- crypto/cmp/cmp_vfy.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index eaa700d139d13..1a58fa59b3e89 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -64,8 +64,10 @@ static int verify_signature(const OSSL_CMP_CTX *cmp_ctx, sig_err: res = ossl_x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS); ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_SIGNATURE); - if (res) - ERR_add_error_mem_bio("\n", bio); + if (res) { + ERR_add_error_txt(NULL, "\n"); + ERR_add_error_mem_bio(NULL, bio); + } res = 0; end: @@ -387,7 +389,7 @@ static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs, int i; if (sk_X509_num(certs) <= 0) { - ossl_cmp_log1(WARN, ctx, "no %s", desc); + ossl_cmp_log1(INFO, ctx, "no %s", desc); return 0; } @@ -407,7 +409,7 @@ static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs, } } if (in_extraCerts && n_acceptable_certs == 0) - ossl_cmp_warn(ctx, "no acceptable cert in extraCerts"); + ossl_cmp_log1(WARN, ctx, "no acceptable %s", desc); return 0; } From 557353f40ad252cb2e7c033c0dda5b67c946fb4a Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 23 Oct 2025 21:27:43 +0200 Subject: [PATCH 003/189] cmp_vfy.c: prevent needless and confusing duplication of diagnostic output on failure validating CMP messages Reviewed-by: Daniel Kubec Reviewed-by: Milan Broz Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jun 10 06:39:00 2026 (Merged from https://github.com/openssl/openssl/pull/28986) (cherry picked from commit b6eb715075c1e7d005e543122d82946dc7cc3b08) --- crypto/cmp/cmp_vfy.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 1a58fa59b3e89..28dd74f73066f 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -504,14 +504,14 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) res = check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */) || check_msg_all_certs(ctx, msg, 1 /* 3gpp */); - ctx->log_cb = backup_log_cb; - if (res) { - /* discard any diagnostic information on trying to use certs */ - (void)ERR_pop_to_mark(); + + ctx->log_cb = backup_log_cb; /* re-enable logging */ + /* discard any previous diagnostic information on trying to use certs */ + (void)ERR_pop_to_mark(); + + if (res) goto end; - } /* failed finding a sender cert that verifies the message signature */ - (void)ERR_clear_last_mark(); sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0); skid_str = skid == NULL ? NULL : i2s_ASN1_OCTET_STRING(NULL, skid); From 77b49b2a6192680aa417a9b01dff30b4cf4ca81d Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 31 Jul 2025 17:13:58 +0200 Subject: [PATCH 004/189] http_lib.c: fix parsing 'scheme' part in OSSL_parse_url() Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Wed Jun 10 07:15:38 2026 (Merged from https://github.com/openssl/openssl/pull/31267) (cherry picked from commit 6e3627d50ddb8866c96c255bad3a42dd5a81a348) --- crypto/http/http_lib.c | 25 +++++++++++++++---------- test/http_test.c | 24 +++++++++++++++++++----- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/crypto/http/http_lib.c b/crypto/http/http_lib.c index 05bf4be78856a..1f70b96e62451 100644 --- a/crypto/http/http_lib.c +++ b/crypto/http/http_lib.c @@ -21,6 +21,7 @@ #define NI_MAXHOST 255 #endif #include "crypto/ctype.h" /* for ossl_isspace() */ +#define OSSL_URL_SCHEME_SUFFIX "://" static void init_pstring(char **pstr) { @@ -79,16 +80,20 @@ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost, return 0; } - /* check for optional prefix "://" */ - scheme = scheme_end = url; - p = strstr(url, "://"); - if (p == NULL) { - p = url; - } else { - scheme_end = p; - if (scheme_end == scheme) - goto parse_err; - p += strlen("://"); + /* check for optional prefix "://" as per RFC 3986: */ + scheme = scheme_end = p = url; + if (ossl_isalpha(*p)) { + while (*p != '\0' + && (ossl_isalpha(*p) + || ossl_isdigit(*p) + || strchr("+-.", *p) != NULL)) + p++; + if (HAS_PREFIX(p, OSSL_URL_SCHEME_SUFFIX)) { + scheme_end = p; + p += sizeof(OSSL_URL_SCHEME_SUFFIX) - 1; + } else { + p = url; + } } /* parse optional "userinfo@" */ diff --git a/test/http_test.c b/test/http_test.c index 76d0d4348587a..8ce889d9bc7f9 100644 --- a/test/http_test.c +++ b/test/http_test.c @@ -287,8 +287,8 @@ static int test_http_keep_alive(char version, int keep_alive, int kept_alive) return res; } -static int test_http_url_ok(const char *url, int exp_ssl, const char *exp_host, - const char *exp_port, const char *exp_path) +static int test_http_url_frag_ok(const char *url, int exp_ssl, const char *exp_host, + const char *exp_port, const char *exp_path, const char *exp_frag) { char *user, *host, *port, *path, *query, *frag; int exp_num, num, ssl; @@ -305,8 +305,8 @@ static int test_http_url_ok(const char *url, int exp_ssl, const char *exp_host, && TEST_int_eq(ssl, exp_ssl); if (res && *user != '\0') res = TEST_str_eq(user, "user:pass"); - if (res && *frag != '\0') - res = TEST_str_eq(frag, "fr"); + if (res) + res = TEST_str_eq(frag, exp_frag); if (res && *query != '\0') res = TEST_str_eq(query, "q"); OPENSSL_free(user); @@ -318,6 +318,12 @@ static int test_http_url_ok(const char *url, int exp_ssl, const char *exp_host, return res; } +static int test_http_url_ok(const char *url, int exp_ssl, const char *exp_host, + const char *exp_port, const char *exp_path) +{ + return test_http_url_frag_ok(url, exp_ssl, exp_host, exp_port, exp_path, ""); +} + static int test_http_url_path_query_ok(const char *url, const char *exp_path_qu) { char *host, *path; @@ -349,6 +355,11 @@ static int test_http_url_dns(void) return test_http_url_ok("host:65535/path", 0, "host", "65535", "/path"); } +static int test_http_url_ip(void) +{ + return test_http_url_ok("1.2.3.4:5678//blahblablah", 0, "1.2.3.4", "5678", "//blahblablah"); +} + static int test_http_url_timestamp(void) { return test_http_url_ok("host/p/2017-01-03T00:00:00", 0, "host", "80", @@ -368,7 +379,9 @@ static int test_http_url_path_query(void) static int test_http_url_userinfo_query_fragment(void) { - return test_http_url_ok("user:pass@host/p?q#fr", 0, "host", "80", "/p"); + return test_http_url_frag_ok("user:pass@host/p?q#fr", 0, "host", "80", "/p", "fr") + && test_http_url_frag_ok("host.example.org/some/path#://not-a-scheme/not.a.host:404", 0, + "host.example.org", "80", "/some/path", "://not-a-scheme/not.a.host:404"); } static int test_http_url_at_sign_outside_authority(void) @@ -652,6 +665,7 @@ int setup_tests(void) return 0; ADD_TEST(test_http_url_dns); + ADD_TEST(test_http_url_ip); ADD_TEST(test_http_url_timestamp); ADD_TEST(test_http_url_path_query); ADD_TEST(test_http_url_userinfo_query_fragment); From dc5d961f36fce689cf0470fa287e4603b0e4434f Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Wed, 8 Apr 2026 08:27:35 +0200 Subject: [PATCH 005/189] http_lib.c: add check that host_end is not past authority_end Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Wed Jun 10 07:15:39 2026 (Merged from https://github.com/openssl/openssl/pull/31267) (cherry picked from commit 58ebe685bd0276f18338ca4df2593c4d161bfa65) --- crypto/http/http_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/http/http_lib.c b/crypto/http/http_lib.c index 1f70b96e62451..d7227f5df2480 100644 --- a/crypto/http/http_lib.c +++ b/crypto/http/http_lib.c @@ -110,7 +110,7 @@ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost, /* parse hostname/address as far as needed here */ if (host[0] == '[') { /* IPv6 literal, which may include ':' */ - host_end = strchr(host + 1, ']'); + host_end = memchr(host + 1, ']', authority_end - host - 1); if (host_end == NULL) goto parse_err; p = ++host_end; From 0d8c4fd042dde08350aff2e9502e4d7f854b2c43 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Mon, 1 Jun 2026 19:58:09 +0530 Subject: [PATCH 006/189] pvkfmt: check keylen before copying the BLOBHEADER Reviewed-by: Daniel Kubec Reviewed-by: Neil Horman MergeDate: Wed Jun 10 11:13:28 2026 (Merged from https://github.com/openssl/openssl/pull/31352) --- crypto/pem/pvkfmt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c index 9bfbb01e430aa..31b46183a4043 100644 --- a/crypto/pem/pvkfmt.c +++ b/crypto/pem/pvkfmt.c @@ -893,13 +893,13 @@ static void *do_PVK_body_key(const unsigned char **in, (unsigned char *)psbuf, inlen, libctx, propq)) goto err; p += saltlen; - /* Copy BLOBHEADER across, decrypt rest */ - memcpy(enctmp, p, 8); - p += 8; if (keylen < 8) { ERR_raise(ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT); goto err; } + /* Copy BLOBHEADER across, decrypt rest */ + memcpy(enctmp, p, 8); + p += 8; inlen = keylen - 8; q = enctmp + 8; if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL) From 9ad3030f4028dca56363e9d5d0e86d04713544cd Mon Sep 17 00:00:00 2001 From: sucloudflare Date: Sat, 6 Jun 2026 17:40:23 -0300 Subject: [PATCH 007/189] crypto/evp: align exchange.c cleanup with kem/sig/asymcipher pattern Commit a21f77d added explicit null assignments after EVP_KEYMGMT_free() calls at the err:, legacy:, and success exit paths in kem.c, asymcipher.c and signature.c. The identical exit paths in evp_keyexch_init() (crypto/evp/exchange.c) were not updated at the same time, leaving exchange.c as the only outlier in the family without these null assignments. This patch brings exchange.c into consistency with its sibling files by adding exchange = NULL and tmp_keymgmt = NULL after each free at the exit paths, matching the established pattern from a21f77d. No functional change intended. Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz MergeDate: Wed Jun 10 11:21:26 2026 (Merged from https://github.com/openssl/openssl/pull/31394) --- crypto/evp/exchange.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index 088d2fdc6e731..5820e3e877def 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -287,7 +287,9 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) * iteration we're on. */ EVP_KEYEXCH_free(exchange); + exchange = NULL; EVP_KEYMGMT_free(tmp_keymgmt); + tmp_keymgmt = NULL; switch (iter) { case 1: From d01e152f969e38ebc4535124682773bb0be9c782 Mon Sep 17 00:00:00 2001 From: Nikolas Gauder Date: Fri, 29 May 2026 14:56:39 +0200 Subject: [PATCH 008/189] quic: add lhash insert error checks Reviewed-by: Nikola Pajkovsky Reviewed-by: Neil Horman MergeDate: Wed Jun 10 11:28:41 2026 (Merged from https://github.com/openssl/openssl/pull/31333) --- ssl/quic/quic_impl.c | 5 +++++ ssl/quic/quic_stream_map.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 97efa4908a496..801e37d410c63 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -4915,6 +4915,11 @@ int ossl_quic_set_peer_token(SSL_CTX *ctx, BIO_ADDR *peer, ossl_quic_free_peer_token(old); } lh_QUIC_TOKEN_insert(c->cache, tok); + if (lh_QUIC_TOKEN_error(c->cache)) { + ossl_quic_free_peer_token(tok); + ossl_crypto_mutex_unlock(c->mutex); + return 0; + } ossl_crypto_mutex_unlock(c->mutex); return 1; diff --git a/ssl/quic/quic_stream_map.c b/ssl/quic/quic_stream_map.c index 84ac6b714e382..da53d4b8054fa 100644 --- a/ssl/quic/quic_stream_map.c +++ b/ssl/quic/quic_stream_map.c @@ -168,6 +168,10 @@ QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm, s->send_final_size = UINT64_MAX; lh_QUIC_STREAM_insert(qsm->map, s); + if (lh_QUIC_STREAM_error(qsm->map)) { + OPENSSL_free(s); + return NULL; + } return s; } From 107739f0d422e9f1d9c72d38a4bcb1a5acee5257 Mon Sep 17 00:00:00 2001 From: Bob Beck Date: Wed, 27 May 2026 08:41:53 -0600 Subject: [PATCH 009/189] Let's attempt to make real documentation for X509_verify_cert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I am doing this because I have need to add information that really does belong here, and the current stuff is less documentation than more or less some hand waving about how it works without any details So to summarize the changes: 1) This documents the current way that X509_verify_cert goes about building and verifying a chain, identifying the relevant flags that can affect how this happens today, and cross references the correct page to find the rest of the exhaustive list of verification flags and what they do. 2) This documents the verification callback and how it can be used to affect the verification outcome, This includes warning potential users of the callback of what returning values from it means, the common ways to end up unintentionaly doing things you did not expect with the callback, and that it depends upon internals and should not be relied upon. Reviewed-by: Saša Nedvědický Reviewed-by: Neil Horman MergeDate: Wed Jun 10 11:33:13 2026 (Merged from https://github.com/openssl/openssl/pull/31314) (cherry picked from commit b2a133ed7739986750bc63220f1bdee8e49cc519) --- doc/man3/X509_verify_cert.pod | 499 +++++++++++++++++++++++++++++----- 1 file changed, 433 insertions(+), 66 deletions(-) diff --git a/doc/man3/X509_verify_cert.pod b/doc/man3/X509_verify_cert.pod index 360e974812737..95f3404e27511 100644 --- a/doc/man3/X509_verify_cert.pod +++ b/doc/man3/X509_verify_cert.pod @@ -2,89 +2,453 @@ =head1 NAME -X509_build_chain, X509_verify_cert, -X509_STORE_CTX_verify - build and verify X509 certificate chain +X509_STORE_CTX_verify, +X509_build_chain - build and verify X509 certificate chain =head1 SYNOPSIS #include + int X509_verify_cert(X509_STORE_CTX *ctx); + int X509_STORE_CTX_verify(X509_STORE_CTX *ctx); STACK_OF(X509) *X509_build_chain(X509 *target, STACK_OF(X509) *certs, X509_STORE *store, int with_self_signed, OSSL_LIB_CTX *libctx, const char *propq); - int X509_verify_cert(X509_STORE_CTX *ctx); - int X509_STORE_CTX_verify(X509_STORE_CTX *ctx); =head1 DESCRIPTION -X509_build_chain() builds a certificate chain starting from I -using the optional list of intermediate CA certificates I. -If I is NULL it builds the chain as far down as possible, ignoring errors. -Else the chain must reach a trust anchor contained in I. -It internally uses a B structure associated with the library -context I and property query string I, both of which may be NULL. -In case there is more than one possibility for the chain, only one is taken. - -On success it returns a pointer to a new stack of (up_ref'ed) certificates -starting with I and followed by all available intermediate certificates. -A self-signed trust anchor is included only if I is the trust anchor -of I is 1. -If a non-NULL stack is returned the caller is responsible for freeing it. - -The X509_verify_cert() function attempts to discover and validate a -certificate chain based on parameters in I. -The verification context, of type B, can be constructed -using L and L. -It usually includes a target certificate to be verified, -a set of certificates serving as trust anchors, -a list of non-trusted certificates that may be helpful for chain construction, -flags such as X509_V_FLAG_X509_STRICT, and various other optional components -such as a callback function that allows customizing the verification outcome. -A complete description of the certificate verification process is contained in -the L manual page. - -Applications rarely call this function directly but it is used by -OpenSSL internally for certificate validation, in both the S/MIME and -SSL/TLS code. - -A negative return value from X509_verify_cert() can occur if it is invoked -incorrectly, such as with no certificate set in I, or when it is called -twice in succession without reinitialising I for the second call. -A negative return value can also happen due to internal resource problems -or because an internal inconsistency has been detected. -Applications must interpret any return value <= 0 as an error. - -The X509_STORE_CTX_verify() behaves like X509_verify_cert() except that its -target certificate is the first element of the list of untrusted certificates -in I unless a target certificate is set explicitly. - -When the verification target is a raw public key, rather than a certificate, -both functions validate the target raw public key. -In that case the number of possible checks is significantly reduced. -The raw public key can be authenticated only via DANE TLSA records, either -locally synthesised or obtained by the application from DNS. -Raw public key DANE TLSA records may be added via L or -L. +=head2 X509_verify_cert and X509_STORE_CTX_verify + +X509_verify_cert() attempts to build and validate a certificate chain for the +target certificate set in I. The verification context, of type +B, must first be constructed with L and +initialised with L. It carries the target certificate, +the trust store, an optional stack of untrusted certificates that may assist +chain construction, verification parameters such as flags and a verification +purpose, an optional verification callback, and, after a call, the verification +outcome. + +A B can be used for only one verification. Calling +X509_verify_cert() a second time on the same context without reinitialising it +fails with a negative return value, and L +subsequently returns B. + +When the target is a certificate, the function performs the following steps in +order. The first step that fails aborts verification, except where a +verification callback explicitly waives the error (see +L below): + +=over 4 + +=item 1. + +B Starting from the target certificate, the verification +machinery seeks an issuer for the certificate currently at the top of the +chain, drawing candidates from I's untrusted stack and from the trust +store. By default the search is untrusted-first: the untrusted stack is +examined before the trust store. Setting B on +I's verification parameters reverses this. When an untrusted-first +search fails to reach a trust anchor and B is not +set, the search is retried with progressively shorter untrusted prefixes in +an attempt to find an alternative trusted path. The chain length is bounded +by the configured depth limit (see L); +exceeding it yields B. If more than one +chain is possible, only one is taken. + +Failure to build a chain to a trust anchor yields an error such as +B, +B, +B, +B, or +B. + +=item 2. + +B per RFC 5280, including basic constraints, +key usage and the verification purpose set via +L. + +=item 3. + +B against the configured authentication level, covering +issuer key sizes (B) and signature algorithm +strength (B). The leaf key is checked separately +before chain construction begins (B). + +=item 4. + +B against any hostnames, email addresses or IP addresses +configured on the verification parameters +(L and related). + +=item 5. + +B via CRLs and, when configured, OCSP. The set of checks +performed is controlled by flags such as B and +B. + +=item 6. + +B on every certificate in the chain, +walking from the trust anchor down to the target. The signature on the +chain's terminating certificate is not verified: trust is taken from its +presence in the trust store rather than from its signature. This applies +both to a conventional self-signed trust anchor and, when +B is in effect, to a non-self-signed +intermediate promoted to anchor status. B +requests that the self-signature on a self-signed terminator be verified; +it has no effect when the terminator is a non-self-signed certificate. +Validity periods are checked on every certificate, including the +terminator. + +=item 7. + +B per RFC 5280 section 4.2.1.10. + +=item 8. + +B of AS-number and IP-address delegation +extensions, performed by default unless OpenSSL was built with +B. + +=item 9. + +B, performed only when +B is set. + +=back + +Several B values modify the behaviour of these checks; +representative ones are named at the relevant step above, but the list there +is not exhaustive. The complete set of verification flags, the effect each +one has, and the functions used to query and modify them are documented in +L. + +Applications rarely call X509_verify_cert() directly. It is invoked internally +by OpenSSL during S/MIME and CMS verification and during the TLS handshake. + +X509_STORE_CTX_verify() behaves identically to X509_verify_cert() except for +the selection of the target certificate: if no target has been set on I +(see L) and the untrusted stack is nonempty, the +first certificate in the untrusted stack is adopted as the target before +verification begins. If a target was set explicitly, X509_STORE_CTX_verify() +uses it and does not consult the untrusted stack for this purpose. + +=head2 Raw public key targets + +When the verification target is a raw public key rather than a certificate +(set via L), both functions validate the raw public +key instead of a certificate chain. The set of possible checks is significantly +reduced: there are no extensions, names, CRLs or signatures to verify. The raw +public key can be authenticated only via DANE TLSA records, either locally +synthesised or obtained by the application from DNS. Raw public key DANE TLSA +records may be added via L or L. + +=head2 X509_build_chain + +X509_build_chain() builds a certificate chain starting from I, using +the same chain-construction algorithm as X509_verify_cert() (see +L above). It internally uses a +B structure associated with the library context I +and property query string I, both of which may be NULL. The role of +I depends on I: + +=over 4 + +=item * + +If I is non-NULL, I is treated as an optional list of +B intermediate certificates that may help complete the chain, and +the chain must reach a trust anchor contained in I. If no chain to a +trust anchor can be built, the function fails and returns NULL. + +=item * + +If I is NULL, I is installed as the B stack for the +internal context (see L). In this mode +the function builds the chain as far as it can but does not require it to +reach an anchor: if chain construction fails partway, the partial chain built +so far is still returned. + +=back + +Because the internal B is allocated and freed inside +X509_build_chain(), search-policy flags such as B +and B and the configured depth limit always take +their default values, and the specific B code that caused +chain construction to fail is not reported back: the function signals only +success or failure through its return value (and, when I is NULL, may +also return a partial chain). + +On success the returned stack starts with a newly up-referenced I +followed by the issuer certificates that were found. A self-signed certificate +at the top of the chain is included in the returned stack when either +I is 1, or the chain consists solely of I (for +example because I itself is self-signed or no further issuer could +be found). When the chain has more than one element and I +is 0, the self-signed top is omitted from the result. + +The caller is responsible for freeing the returned stack. + +=head1 THE VERIFICATION CALLBACK + +Each B carries a I with the signature + + int (*verify_cb)(int ok, X509_STORE_CTX *ctx); + +This callback is invoked by X509_verify_cert() and X509_STORE_CTX_verify() +at multiple points during verification, both to B and to +B. It is installed by L +on the context, or it is inherited at L time from +the B (see L). If neither has +been set, a default callback is used which simply returns its I argument +unchanged, causing every error to abort verification. + +=head2 When the callback is called + +There are two distinct invocation patterns: + +=over 4 + +=item B (I = 0) + +The callback is called with I set to 0 each time a check fails. Before the +call, the verification machinery records the B code describing +the failure on I, and for certificate-level errors also records the +depth at which the error was detected and the certificate in question. The +callback inspects these via L, +L, and L. +CRL- and OCSP-related errors update only the error code; the depth and +current certificate retain their values from a preceding context. + +=item B (I = 1) + +During the signature-and-validity pass, after each certificate in the chain +has been checked successfully, the callback is called with I set to 1. +The current certificate, current issuer, and error depth (queryable +respectively via L, +L, and +L) describe the certificate that has just +been accepted. The callback may use this to log progress, but B return +a nonzero value, otherwise verification is aborted. + +=back + +The callback's return value controls subsequent verification: + +=over 4 + +=item * + +A nonzero return value causes verification to B. For an error +notification this constitutes B the error. + +=item * + +A zero return value causes verification to B immediately. The function +returns 0 to its caller in this case, regardless of whether the callback was +invoked with I = 0 or I = 1. + +=back + +=head2 Sticky errors + +When the callback waives an error by returning nonzero, the underlying check is +treated as passed for control-flow purposes, but the error code recorded on +I is B reset to B. A subsequent successful return from +X509_verify_cert() therefore does B imply that +L will return B: it may still hold +the last error code that was waived. This is intentional. Only the callback +itself is permitted to overwrite the error code, via +L, and only at its own risk. + +=head2 Dangers + +A verification callback that returns nonzero on an error notification has, by +definition, suppressed an authentication check that OpenSSL considered +necessary. Callers should treat installing a callback that waives errors as a +deliberate weakening of the security guarantees of X509_verify_cert(), to be +done only for specific, well-understood error codes. The following pitfalls are +common: + +=over 4 + +=item * + +B. A callback that returns 1 unconditionally turns +X509_verify_cert() into "accept anything" and is almost always wrong outside of +diagnostics. Inspect the error code via L and +waive only the specific codes you intend to. + +=item * + +B. Because the callback is also called with +I = 1, a callback that mistakenly returns 0 in that case causes +verification to fail even though every check passed. The caller cannot +distinguish this from a genuine failure based on the return value alone. + +=item * + +B. The sticky-error rule exists so that a waived +error remains visible to the caller after verification returns. A callback +that calls L with B hides this +information and can also mask a later error if the callback is invoked again +before verification completes. + +=item * + +B. The B is live during +the callback: the verification routines are actively reading its chain, +parameters, and other state. Calling context-mutating functions from within +the callback -- for example, replacing the verified chain via +L, swapping the trust store or +untrusted stack, or changing verification flags, depth, purpose, or target +-- can corrupt the in-progress verification, produce inconsistent behaviour +between later steps of the pipeline, or, in the case of the verified chain, +cause use-after-free. The only mutators reasonable from within a callback +are the error-related setters (L, +L, L), +and even those should be used sparingly (see L). + +=item * + +B. The callback is on the hot path of every +certificate check; expensive work performed there will slow every TLS handshake +or S/MIME verification that uses the surrounding context. + +=item * + +B. The error depth, from +L, records where an error was detected +during chain processing, not the position of the certificate in the final +chain. Always consult L in addition to +the depth when deciding whether to waive. + +=item * + +B. The set of errors the callback +observes, and the order in which it observes them, depends on the internal +order in which verification checks are performed. When a certificate has more +than one problem, only the first check to detect a problem causes the +callback to be invoked for that certificate; later checks are not reached +unless the callback waives the earlier error. This ordering is an +implementation detail and is not part of the stable API: a refactor that +reorders internal checks without altering the binary success/failure contract +of X509_verify_cert() may still change which B code the +callback sees, or whether a given code is reported at all. Callbacks that +branch on a specific error code being reported, or that assume earlier checks +have already filtered out certain conditions, can therefore change behaviour +silently across OpenSSL releases. Write callbacks defensively: re-fetch the +error code and the current certificate via L +and L afresh on each invocation, and +treat "this error code never appears" as an assumption that may be +invalidated. More fundamentally, because the set and order of error +notifications is not a stable contract, the callback cannot be relied upon to +observe any particular condition or sequence of conditions; that makes it an +unsound mechanism for enforcing or modifying security policy. Use of the +verification callback to alter verification outcomes -- to waive errors, to +inject conditional acceptance, or to gate behaviour on a specific +B code being reported -- is therefore discouraged in production +code. Reserve the callback for diagnostic and logging purposes, where future +changes in which errors appear, or in what order, are not security-relevant. + +=back + +The default callback waives nothing and is the safe choice; it is the right +behaviour for almost all production uses. =head1 RETURN VALUES -X509_build_chain() returns NULL on error, else a stack of certificates. +X509_verify_cert() and X509_STORE_CTX_verify() return: + +=over 4 + +=item B<1> + +if a complete chain has been built and every check either succeeded or was +waived by the verification callback. Note that the latter case does not +guarantee that L returns B; see +L. The return value is the authoritative success/failure +signal: callers do not need to additionally check that +L returns B to consider verification +successful. They may consult it to learn whether, and which, errors were +waived by the verification callback. + +=item B<0> + +if verification was rejected. This occurs when a check failed and the callback +did not waive the error, when a trust decision actively rejected the chain, or +when the verification callback returned 0 from a success notification (see +L). When a certificate would have failed more +than one check, the specific B code returned by +L reflects whichever check fired first; this +ordering is an implementation detail and is not stable across releases. +Callers must therefore treat the return value as the authoritative +success/failure signal, and treat the specific error code as diagnostic +information that may shift over time. + +=item A B value + +on a hard error that prevented verification from running to completion. The +documented cases are: I is NULL; I has no target certificate set; +I has already been used for a previous verification; memory allocation +failed; the trust store lookup function returned an error; or an internal +invariant was violated. In these cases L +returns an appropriate B value (B, +B, B or +B). + +=back + +In all failure modes, additional information can be obtained from +L and the related accessors. Applications must +treat any return value E= 0 as verification not having succeeded. + +X509_build_chain() returns NULL on error. Otherwise it returns a newly +allocated stack of certificates that the caller must free; the stack may +represent only a partial chain when I is NULL. + +=head1 BUGS + +Several aspects of chain construction depart from the recommendations of +RFC 4158 (Certification Path Building) and from strict RFC 5280 path +validation. Callers should be aware of the following: -Both X509_verify_cert() and X509_STORE_CTX_verify() -return 1 if a complete chain can be built and validated, -otherwise they return 0, and in exceptional circumstances (such as malloc -failure and internal errors) they can also return a negative code. +The chain search is not optimised in the manner described by RFC 4158 +sections 3.1 to 3.5. Candidate issuers are not scored against the set of +heuristics RFC 4158 recommends; at each step the first viable candidate +is committed to, with the only preference being for a candidate whose +validity period covers the current time. There is no tree-traversal +backtracking: when an initial chain does not reach a trust anchor, the +search is retried with progressively shorter untrusted prefixes (unless +B is set), but different candidate issuers at +intermediate positions of the same chain are not tried. In simple +hierarchical PKIs this is rarely an issue. In cross-certified or bridged +PKI environments X509_verify_cert() may fail to find a valid certification +path even when one demonstrably exists in the available certificate set. -If a complete chain can be built and validated both functions return 1. -If the certificate must be rejected on the basis of the data available -or any required certificate status data is not available they return 0. -If no definite answer possible they usually return a negative code. +Issuer key usage is not enforced during chain construction. RFC 5280 +section 6.1.4(n) and RFC 4158 section 3.5.3 call for verifying that an +issuer candidate's keyUsage extension permits certificate signing +(B) before that candidate is selected. OpenSSL defers this +check to the later extension-validation pass: if two candidate issuers +exist for a certificate, and the one lacking B happens to be +selected first, verification fails on the extension check rather than +backing off and trying the other candidate. The misuse is ultimately +caught, but a chain that would have validated through the alternative +issuer is not built. -On error or failure additional error information can be obtained by -examining I using, for example, L. Even if -verification indicated success, the stored error code may be different from -X509_V_OK, likely because a verification callback function has waived the error. +B relaxes the trust-anchor requirement from +the one defined by RFC 5280 section 6.1.1(d). With the flag set, any +certificate in the trust store is acceptable as the terminator of the +chain, even if it is not a self-signed root. This is an intentional and +now-common deviation that supports modern practices such as pinning trust +to a specific intermediate, or shortening chains by treating a +sufficiently-trusted intermediate as the trust point and eliding the root +above it. Callers should nevertheless be aware that the chain returned in +this mode does not necessarily terminate at an RFC 5280-style trust +anchor. =head1 SEE ALSO @@ -94,7 +458,10 @@ L, L, L, L, -L +L, +L, +L, +L =head1 HISTORY From e2b5cd3d61b56bfafacb099a0342988293235d5c Mon Sep 17 00:00:00 2001 From: Andrew Dinh Date: Tue, 9 Jun 2026 17:11:49 +0700 Subject: [PATCH 010/189] Remove crypto/aes/aes_x86core.c because it's dead code Reviewed-by: Milan Broz Reviewed-by: Bob Beck Reviewed-by: Eugene Syromiatnikov Reviewed-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs MergeDate: Wed Jun 10 12:46:55 2026 (Merged from https://github.com/openssl/openssl/pull/31424) --- crypto/aes/aes_x86core.c | 867 --------------------------------------- 1 file changed, 867 deletions(-) delete mode 100644 crypto/aes/aes_x86core.c diff --git a/crypto/aes/aes_x86core.c b/crypto/aes/aes_x86core.c deleted file mode 100644 index 0fa994871b279..0000000000000 --- a/crypto/aes/aes_x86core.c +++ /dev/null @@ -1,867 +0,0 @@ -/* - * Copyright 2006-2016 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 is experimental x86[_64] derivative. It assumes little-endian - * byte order and expects CPU to sustain unaligned memory references. - * It is used as playground for cache-time attack mitigations and - * serves as reference C implementation for x86[_64] as well as some - * other assembly modules. - */ - -/** - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include -#include -#include "aes_local.h" - -/* - * These two parameters control which table, 256-byte or 2KB, is - * referenced in outer and respectively inner rounds. - */ -#define AES_COMPACT_IN_OUTER_ROUNDS -#ifdef AES_COMPACT_IN_OUTER_ROUNDS -/* AES_COMPACT_IN_OUTER_ROUNDS costs ~30% in performance, while - * adding AES_COMPACT_IN_INNER_ROUNDS reduces benchmark *further* - * by factor of ~2. */ -#undef AES_COMPACT_IN_INNER_ROUNDS -#endif - -#if 1 -static void prefetch256(const void *table) -{ - volatile unsigned long *t = (void *)table, ret; - unsigned long sum; - int i; - - /* 32 is common least cache-line size */ - for (sum = 0, i = 0; i < 256 / sizeof(t[0]); i += 32 / sizeof(t[0])) - sum ^= t[i]; - - ret = sum; -} -#else -#define prefetch256(t) -#endif - -#undef GETU32 -#define GETU32(p) (*((u32 *)(p))) - -#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) -#define U64(C) C##UI64 -#elif defined(__arch64__) -#define U64(C) C##UL -#else -#define U64(C) C##ULL -#endif - -#undef ROTATE -#if defined(_MSC_VER) -#define ROTATE(a, n) _lrotl(a, n) -#elif defined(__ICC) -#define ROTATE(a, n) _rotl(a, n) -#elif defined(__GNUC__) && __GNUC__ >= 2 -#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) -#define ROTATE(a, n) ({ \ - register unsigned int ret; \ - asm( \ - "roll %1,%0" \ - : "=r"(ret) \ - : "I"(n), "0"(a) \ - : "cc"); \ - ret; \ -}) -#endif -#endif -/*- -Te [x] = S [x].[02, 01, 01, 03, 02, 01, 01, 03]; -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -*/ -#define Te0 (u32)((u64 *)((u8 *)Te + 0)) -#define Te1 (u32)((u64 *)((u8 *)Te + 3)) -#define Te2 (u32)((u64 *)((u8 *)Te + 2)) -#define Te3 (u32)((u64 *)((u8 *)Te + 1)) -/*- -Td [x] = Si[x].[0e, 09, 0d, 0b, 0e, 09, 0d, 0b]; -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01]; -*/ -#define Td0 (u32)((u64 *)((u8 *)Td + 0)) -#define Td1 (u32)((u64 *)((u8 *)Td + 3)) -#define Td2 (u32)((u64 *)((u8 *)Td + 2)) -#define Td3 (u32)((u64 *)((u8 *)Td + 1)) - -static const u64 Te[256] = { - U64(0xa56363c6a56363c6), U64(0x847c7cf8847c7cf8), - U64(0x997777ee997777ee), U64(0x8d7b7bf68d7b7bf6), - U64(0x0df2f2ff0df2f2ff), U64(0xbd6b6bd6bd6b6bd6), - U64(0xb16f6fdeb16f6fde), U64(0x54c5c59154c5c591), - U64(0x5030306050303060), U64(0x0301010203010102), - U64(0xa96767cea96767ce), U64(0x7d2b2b567d2b2b56), - U64(0x19fefee719fefee7), U64(0x62d7d7b562d7d7b5), - U64(0xe6abab4de6abab4d), U64(0x9a7676ec9a7676ec), - U64(0x45caca8f45caca8f), U64(0x9d82821f9d82821f), - U64(0x40c9c98940c9c989), U64(0x877d7dfa877d7dfa), - U64(0x15fafaef15fafaef), U64(0xeb5959b2eb5959b2), - U64(0xc947478ec947478e), U64(0x0bf0f0fb0bf0f0fb), - U64(0xecadad41ecadad41), U64(0x67d4d4b367d4d4b3), - U64(0xfda2a25ffda2a25f), U64(0xeaafaf45eaafaf45), - U64(0xbf9c9c23bf9c9c23), U64(0xf7a4a453f7a4a453), - U64(0x967272e4967272e4), U64(0x5bc0c09b5bc0c09b), - U64(0xc2b7b775c2b7b775), U64(0x1cfdfde11cfdfde1), - U64(0xae93933dae93933d), U64(0x6a26264c6a26264c), - U64(0x5a36366c5a36366c), U64(0x413f3f7e413f3f7e), - U64(0x02f7f7f502f7f7f5), U64(0x4fcccc834fcccc83), - U64(0x5c3434685c343468), U64(0xf4a5a551f4a5a551), - U64(0x34e5e5d134e5e5d1), U64(0x08f1f1f908f1f1f9), - U64(0x937171e2937171e2), U64(0x73d8d8ab73d8d8ab), - U64(0x5331316253313162), U64(0x3f15152a3f15152a), - U64(0x0c0404080c040408), U64(0x52c7c79552c7c795), - U64(0x6523234665232346), U64(0x5ec3c39d5ec3c39d), - U64(0x2818183028181830), U64(0xa1969637a1969637), - U64(0x0f05050a0f05050a), U64(0xb59a9a2fb59a9a2f), - U64(0x0907070e0907070e), U64(0x3612122436121224), - U64(0x9b80801b9b80801b), U64(0x3de2e2df3de2e2df), - U64(0x26ebebcd26ebebcd), U64(0x6927274e6927274e), - U64(0xcdb2b27fcdb2b27f), U64(0x9f7575ea9f7575ea), - U64(0x1b0909121b090912), U64(0x9e83831d9e83831d), - U64(0x742c2c58742c2c58), U64(0x2e1a1a342e1a1a34), - U64(0x2d1b1b362d1b1b36), U64(0xb26e6edcb26e6edc), - U64(0xee5a5ab4ee5a5ab4), U64(0xfba0a05bfba0a05b), - U64(0xf65252a4f65252a4), U64(0x4d3b3b764d3b3b76), - U64(0x61d6d6b761d6d6b7), U64(0xceb3b37dceb3b37d), - U64(0x7b2929527b292952), U64(0x3ee3e3dd3ee3e3dd), - U64(0x712f2f5e712f2f5e), U64(0x9784841397848413), - U64(0xf55353a6f55353a6), U64(0x68d1d1b968d1d1b9), - U64(0x0000000000000000), U64(0x2cededc12cededc1), - U64(0x6020204060202040), U64(0x1ffcfce31ffcfce3), - U64(0xc8b1b179c8b1b179), U64(0xed5b5bb6ed5b5bb6), - U64(0xbe6a6ad4be6a6ad4), U64(0x46cbcb8d46cbcb8d), - U64(0xd9bebe67d9bebe67), U64(0x4b3939724b393972), - U64(0xde4a4a94de4a4a94), U64(0xd44c4c98d44c4c98), - U64(0xe85858b0e85858b0), U64(0x4acfcf854acfcf85), - U64(0x6bd0d0bb6bd0d0bb), U64(0x2aefefc52aefefc5), - U64(0xe5aaaa4fe5aaaa4f), U64(0x16fbfbed16fbfbed), - U64(0xc5434386c5434386), U64(0xd74d4d9ad74d4d9a), - U64(0x5533336655333366), U64(0x9485851194858511), - U64(0xcf45458acf45458a), U64(0x10f9f9e910f9f9e9), - U64(0x0602020406020204), U64(0x817f7ffe817f7ffe), - U64(0xf05050a0f05050a0), U64(0x443c3c78443c3c78), - U64(0xba9f9f25ba9f9f25), U64(0xe3a8a84be3a8a84b), - U64(0xf35151a2f35151a2), U64(0xfea3a35dfea3a35d), - U64(0xc0404080c0404080), U64(0x8a8f8f058a8f8f05), - U64(0xad92923fad92923f), U64(0xbc9d9d21bc9d9d21), - U64(0x4838387048383870), U64(0x04f5f5f104f5f5f1), - U64(0xdfbcbc63dfbcbc63), U64(0xc1b6b677c1b6b677), - U64(0x75dadaaf75dadaaf), U64(0x6321214263212142), - U64(0x3010102030101020), U64(0x1affffe51affffe5), - U64(0x0ef3f3fd0ef3f3fd), U64(0x6dd2d2bf6dd2d2bf), - U64(0x4ccdcd814ccdcd81), U64(0x140c0c18140c0c18), - U64(0x3513132635131326), U64(0x2fececc32fececc3), - U64(0xe15f5fbee15f5fbe), U64(0xa2979735a2979735), - U64(0xcc444488cc444488), U64(0x3917172e3917172e), - U64(0x57c4c49357c4c493), U64(0xf2a7a755f2a7a755), - U64(0x827e7efc827e7efc), U64(0x473d3d7a473d3d7a), - U64(0xac6464c8ac6464c8), U64(0xe75d5dbae75d5dba), - U64(0x2b1919322b191932), U64(0x957373e6957373e6), - U64(0xa06060c0a06060c0), U64(0x9881811998818119), - U64(0xd14f4f9ed14f4f9e), U64(0x7fdcdca37fdcdca3), - U64(0x6622224466222244), U64(0x7e2a2a547e2a2a54), - U64(0xab90903bab90903b), U64(0x8388880b8388880b), - U64(0xca46468cca46468c), U64(0x29eeeec729eeeec7), - U64(0xd3b8b86bd3b8b86b), U64(0x3c1414283c141428), - U64(0x79dedea779dedea7), U64(0xe25e5ebce25e5ebc), - U64(0x1d0b0b161d0b0b16), U64(0x76dbdbad76dbdbad), - U64(0x3be0e0db3be0e0db), U64(0x5632326456323264), - U64(0x4e3a3a744e3a3a74), U64(0x1e0a0a141e0a0a14), - U64(0xdb494992db494992), U64(0x0a06060c0a06060c), - U64(0x6c2424486c242448), U64(0xe45c5cb8e45c5cb8), - U64(0x5dc2c29f5dc2c29f), U64(0x6ed3d3bd6ed3d3bd), - U64(0xefacac43efacac43), U64(0xa66262c4a66262c4), - U64(0xa8919139a8919139), U64(0xa4959531a4959531), - U64(0x37e4e4d337e4e4d3), U64(0x8b7979f28b7979f2), - U64(0x32e7e7d532e7e7d5), U64(0x43c8c88b43c8c88b), - U64(0x5937376e5937376e), U64(0xb76d6ddab76d6dda), - U64(0x8c8d8d018c8d8d01), U64(0x64d5d5b164d5d5b1), - U64(0xd24e4e9cd24e4e9c), U64(0xe0a9a949e0a9a949), - U64(0xb46c6cd8b46c6cd8), U64(0xfa5656acfa5656ac), - U64(0x07f4f4f307f4f4f3), U64(0x25eaeacf25eaeacf), - U64(0xaf6565caaf6565ca), U64(0x8e7a7af48e7a7af4), - U64(0xe9aeae47e9aeae47), U64(0x1808081018080810), - U64(0xd5baba6fd5baba6f), U64(0x887878f0887878f0), - U64(0x6f25254a6f25254a), U64(0x722e2e5c722e2e5c), - U64(0x241c1c38241c1c38), U64(0xf1a6a657f1a6a657), - U64(0xc7b4b473c7b4b473), U64(0x51c6c69751c6c697), - U64(0x23e8e8cb23e8e8cb), U64(0x7cdddda17cdddda1), - U64(0x9c7474e89c7474e8), U64(0x211f1f3e211f1f3e), - U64(0xdd4b4b96dd4b4b96), U64(0xdcbdbd61dcbdbd61), - U64(0x868b8b0d868b8b0d), U64(0x858a8a0f858a8a0f), - U64(0x907070e0907070e0), U64(0x423e3e7c423e3e7c), - U64(0xc4b5b571c4b5b571), U64(0xaa6666ccaa6666cc), - U64(0xd8484890d8484890), U64(0x0503030605030306), - U64(0x01f6f6f701f6f6f7), U64(0x120e0e1c120e0e1c), - U64(0xa36161c2a36161c2), U64(0x5f35356a5f35356a), - U64(0xf95757aef95757ae), U64(0xd0b9b969d0b9b969), - U64(0x9186861791868617), U64(0x58c1c19958c1c199), - U64(0x271d1d3a271d1d3a), U64(0xb99e9e27b99e9e27), - U64(0x38e1e1d938e1e1d9), U64(0x13f8f8eb13f8f8eb), - U64(0xb398982bb398982b), U64(0x3311112233111122), - U64(0xbb6969d2bb6969d2), U64(0x70d9d9a970d9d9a9), - U64(0x898e8e07898e8e07), U64(0xa7949433a7949433), - U64(0xb69b9b2db69b9b2d), U64(0x221e1e3c221e1e3c), - U64(0x9287871592878715), U64(0x20e9e9c920e9e9c9), - U64(0x49cece8749cece87), U64(0xff5555aaff5555aa), - U64(0x7828285078282850), U64(0x7adfdfa57adfdfa5), - U64(0x8f8c8c038f8c8c03), U64(0xf8a1a159f8a1a159), - U64(0x8089890980898909), U64(0x170d0d1a170d0d1a), - U64(0xdabfbf65dabfbf65), U64(0x31e6e6d731e6e6d7), - U64(0xc6424284c6424284), U64(0xb86868d0b86868d0), - U64(0xc3414182c3414182), U64(0xb0999929b0999929), - U64(0x772d2d5a772d2d5a), U64(0x110f0f1e110f0f1e), - U64(0xcbb0b07bcbb0b07b), U64(0xfc5454a8fc5454a8), - U64(0xd6bbbb6dd6bbbb6d), U64(0x3a16162c3a16162c) -}; - -static const u8 Te4[256] = { - 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, - 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, - 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, - 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, - 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, - 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U, - 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, - 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, - 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, - 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U, - 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, - 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, - 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, - 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U, - 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, - 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, - 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, - 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U, - 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, - 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, - 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, - 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U, - 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, - 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, - 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, - 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, - 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, - 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU, - 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, - 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, - 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, - 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U -}; - -static const u64 Td[256] = { - U64(0x50a7f45150a7f451), U64(0x5365417e5365417e), - U64(0xc3a4171ac3a4171a), U64(0x965e273a965e273a), - U64(0xcb6bab3bcb6bab3b), U64(0xf1459d1ff1459d1f), - U64(0xab58faacab58faac), U64(0x9303e34b9303e34b), - U64(0x55fa302055fa3020), U64(0xf66d76adf66d76ad), - U64(0x9176cc889176cc88), U64(0x254c02f5254c02f5), - U64(0xfcd7e54ffcd7e54f), U64(0xd7cb2ac5d7cb2ac5), - U64(0x8044352680443526), U64(0x8fa362b58fa362b5), - U64(0x495ab1de495ab1de), U64(0x671bba25671bba25), - U64(0x980eea45980eea45), U64(0xe1c0fe5de1c0fe5d), - U64(0x02752fc302752fc3), U64(0x12f04c8112f04c81), - U64(0xa397468da397468d), U64(0xc6f9d36bc6f9d36b), - U64(0xe75f8f03e75f8f03), U64(0x959c9215959c9215), - U64(0xeb7a6dbfeb7a6dbf), U64(0xda595295da595295), - U64(0x2d83bed42d83bed4), U64(0xd3217458d3217458), - U64(0x2969e0492969e049), U64(0x44c8c98e44c8c98e), - U64(0x6a89c2756a89c275), U64(0x78798ef478798ef4), - U64(0x6b3e58996b3e5899), U64(0xdd71b927dd71b927), - U64(0xb64fe1beb64fe1be), U64(0x17ad88f017ad88f0), - U64(0x66ac20c966ac20c9), U64(0xb43ace7db43ace7d), - U64(0x184adf63184adf63), U64(0x82311ae582311ae5), - U64(0x6033519760335197), U64(0x457f5362457f5362), - U64(0xe07764b1e07764b1), U64(0x84ae6bbb84ae6bbb), - U64(0x1ca081fe1ca081fe), U64(0x942b08f9942b08f9), - U64(0x5868487058684870), U64(0x19fd458f19fd458f), - U64(0x876cde94876cde94), U64(0xb7f87b52b7f87b52), - U64(0x23d373ab23d373ab), U64(0xe2024b72e2024b72), - U64(0x578f1fe3578f1fe3), U64(0x2aab55662aab5566), - U64(0x0728ebb20728ebb2), U64(0x03c2b52f03c2b52f), - U64(0x9a7bc5869a7bc586), U64(0xa50837d3a50837d3), - U64(0xf2872830f2872830), U64(0xb2a5bf23b2a5bf23), - U64(0xba6a0302ba6a0302), U64(0x5c8216ed5c8216ed), - U64(0x2b1ccf8a2b1ccf8a), U64(0x92b479a792b479a7), - U64(0xf0f207f3f0f207f3), U64(0xa1e2694ea1e2694e), - U64(0xcdf4da65cdf4da65), U64(0xd5be0506d5be0506), - U64(0x1f6234d11f6234d1), U64(0x8afea6c48afea6c4), - U64(0x9d532e349d532e34), U64(0xa055f3a2a055f3a2), - U64(0x32e18a0532e18a05), U64(0x75ebf6a475ebf6a4), - U64(0x39ec830b39ec830b), U64(0xaaef6040aaef6040), - U64(0x069f715e069f715e), U64(0x51106ebd51106ebd), - U64(0xf98a213ef98a213e), U64(0x3d06dd963d06dd96), - U64(0xae053eddae053edd), U64(0x46bde64d46bde64d), - U64(0xb58d5491b58d5491), U64(0x055dc471055dc471), - U64(0x6fd406046fd40604), U64(0xff155060ff155060), - U64(0x24fb981924fb9819), U64(0x97e9bdd697e9bdd6), - U64(0xcc434089cc434089), U64(0x779ed967779ed967), - U64(0xbd42e8b0bd42e8b0), U64(0x888b8907888b8907), - U64(0x385b19e7385b19e7), U64(0xdbeec879dbeec879), - U64(0x470a7ca1470a7ca1), U64(0xe90f427ce90f427c), - U64(0xc91e84f8c91e84f8), U64(0x0000000000000000), - U64(0x8386800983868009), U64(0x48ed2b3248ed2b32), - U64(0xac70111eac70111e), U64(0x4e725a6c4e725a6c), - U64(0xfbff0efdfbff0efd), U64(0x5638850f5638850f), - U64(0x1ed5ae3d1ed5ae3d), U64(0x27392d3627392d36), - U64(0x64d90f0a64d90f0a), U64(0x21a65c6821a65c68), - U64(0xd1545b9bd1545b9b), U64(0x3a2e36243a2e3624), - U64(0xb1670a0cb1670a0c), U64(0x0fe757930fe75793), - U64(0xd296eeb4d296eeb4), U64(0x9e919b1b9e919b1b), - U64(0x4fc5c0804fc5c080), U64(0xa220dc61a220dc61), - U64(0x694b775a694b775a), U64(0x161a121c161a121c), - U64(0x0aba93e20aba93e2), U64(0xe52aa0c0e52aa0c0), - U64(0x43e0223c43e0223c), U64(0x1d171b121d171b12), - U64(0x0b0d090e0b0d090e), U64(0xadc78bf2adc78bf2), - U64(0xb9a8b62db9a8b62d), U64(0xc8a91e14c8a91e14), - U64(0x8519f1578519f157), U64(0x4c0775af4c0775af), - U64(0xbbdd99eebbdd99ee), U64(0xfd607fa3fd607fa3), - U64(0x9f2601f79f2601f7), U64(0xbcf5725cbcf5725c), - U64(0xc53b6644c53b6644), U64(0x347efb5b347efb5b), - U64(0x7629438b7629438b), U64(0xdcc623cbdcc623cb), - U64(0x68fcedb668fcedb6), U64(0x63f1e4b863f1e4b8), - U64(0xcadc31d7cadc31d7), U64(0x1085634210856342), - U64(0x4022971340229713), U64(0x2011c6842011c684), - U64(0x7d244a857d244a85), U64(0xf83dbbd2f83dbbd2), - U64(0x1132f9ae1132f9ae), U64(0x6da129c76da129c7), - U64(0x4b2f9e1d4b2f9e1d), U64(0xf330b2dcf330b2dc), - U64(0xec52860dec52860d), U64(0xd0e3c177d0e3c177), - U64(0x6c16b32b6c16b32b), U64(0x99b970a999b970a9), - U64(0xfa489411fa489411), U64(0x2264e9472264e947), - U64(0xc48cfca8c48cfca8), U64(0x1a3ff0a01a3ff0a0), - U64(0xd82c7d56d82c7d56), U64(0xef903322ef903322), - U64(0xc74e4987c74e4987), U64(0xc1d138d9c1d138d9), - U64(0xfea2ca8cfea2ca8c), U64(0x360bd498360bd498), - U64(0xcf81f5a6cf81f5a6), U64(0x28de7aa528de7aa5), - U64(0x268eb7da268eb7da), U64(0xa4bfad3fa4bfad3f), - U64(0xe49d3a2ce49d3a2c), U64(0x0d9278500d927850), - U64(0x9bcc5f6a9bcc5f6a), U64(0x62467e5462467e54), - U64(0xc2138df6c2138df6), U64(0xe8b8d890e8b8d890), - U64(0x5ef7392e5ef7392e), U64(0xf5afc382f5afc382), - U64(0xbe805d9fbe805d9f), U64(0x7c93d0697c93d069), - U64(0xa92dd56fa92dd56f), U64(0xb31225cfb31225cf), - U64(0x3b99acc83b99acc8), U64(0xa77d1810a77d1810), - U64(0x6e639ce86e639ce8), U64(0x7bbb3bdb7bbb3bdb), - U64(0x097826cd097826cd), U64(0xf418596ef418596e), - U64(0x01b79aec01b79aec), U64(0xa89a4f83a89a4f83), - U64(0x656e95e6656e95e6), U64(0x7ee6ffaa7ee6ffaa), - U64(0x08cfbc2108cfbc21), U64(0xe6e815efe6e815ef), - U64(0xd99be7bad99be7ba), U64(0xce366f4ace366f4a), - U64(0xd4099fead4099fea), U64(0xd67cb029d67cb029), - U64(0xafb2a431afb2a431), U64(0x31233f2a31233f2a), - U64(0x3094a5c63094a5c6), U64(0xc066a235c066a235), - U64(0x37bc4e7437bc4e74), U64(0xa6ca82fca6ca82fc), - U64(0xb0d090e0b0d090e0), U64(0x15d8a73315d8a733), - U64(0x4a9804f14a9804f1), U64(0xf7daec41f7daec41), - U64(0x0e50cd7f0e50cd7f), U64(0x2ff691172ff69117), - U64(0x8dd64d768dd64d76), U64(0x4db0ef434db0ef43), - U64(0x544daacc544daacc), U64(0xdf0496e4df0496e4), - U64(0xe3b5d19ee3b5d19e), U64(0x1b886a4c1b886a4c), - U64(0xb81f2cc1b81f2cc1), U64(0x7f5165467f516546), - U64(0x04ea5e9d04ea5e9d), U64(0x5d358c015d358c01), - U64(0x737487fa737487fa), U64(0x2e410bfb2e410bfb), - U64(0x5a1d67b35a1d67b3), U64(0x52d2db9252d2db92), - U64(0x335610e9335610e9), U64(0x1347d66d1347d66d), - U64(0x8c61d79a8c61d79a), U64(0x7a0ca1377a0ca137), - U64(0x8e14f8598e14f859), U64(0x893c13eb893c13eb), - U64(0xee27a9ceee27a9ce), U64(0x35c961b735c961b7), - U64(0xede51ce1ede51ce1), U64(0x3cb1477a3cb1477a), - U64(0x59dfd29c59dfd29c), U64(0x3f73f2553f73f255), - U64(0x79ce141879ce1418), U64(0xbf37c773bf37c773), - U64(0xeacdf753eacdf753), U64(0x5baafd5f5baafd5f), - U64(0x146f3ddf146f3ddf), U64(0x86db447886db4478), - U64(0x81f3afca81f3afca), U64(0x3ec468b93ec468b9), - U64(0x2c3424382c342438), U64(0x5f40a3c25f40a3c2), - U64(0x72c31d1672c31d16), U64(0x0c25e2bc0c25e2bc), - U64(0x8b493c288b493c28), U64(0x41950dff41950dff), - U64(0x7101a8397101a839), U64(0xdeb30c08deb30c08), - U64(0x9ce4b4d89ce4b4d8), U64(0x90c1566490c15664), - U64(0x6184cb7b6184cb7b), U64(0x70b632d570b632d5), - U64(0x745c6c48745c6c48), U64(0x4257b8d04257b8d0) -}; -static const u8 Td4[256] = { - 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, - 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, - 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, - 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, - 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, - 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, - 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, - 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, - 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, - 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, - 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, - 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, - 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, - 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, - 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, - 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, - 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, - 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, - 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, - 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, - 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, - 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, - 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, - 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, - 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, - 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, - 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, - 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, - 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, - 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, - 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, - 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU -}; - -static const u32 rcon[] = { - 0x00000001U, - 0x00000002U, - 0x00000004U, - 0x00000008U, - 0x00000010U, - 0x00000020U, - 0x00000040U, - 0x00000080U, - 0x0000001bU, - 0x00000036U, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; - -/** - * Expand the cipher key into the encryption key schedule. - */ -int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key) -{ - - u32 *rk; - int i = 0; - u32 temp; - - if (!userKey || !key) - return -1; - if (bits != 128 && bits != 192 && bits != 256) - return -2; - - rk = key->rd_key; - - if (bits == 128) - key->rounds = 10; - else if (bits == 192) - key->rounds = 12; - else - key->rounds = 14; - - rk[0] = GETU32(userKey); - rk[1] = GETU32(userKey + 4); - rk[2] = GETU32(userKey + 8); - rk[3] = GETU32(userKey + 12); - if (bits == 128) { - while (1) { - temp = rk[3]; - rk[4] = rk[0] ^ ((u32)Te4[(temp >> 8) & 0xff]) ^ ((u32)Te4[(temp >> 16) & 0xff] << 8) ^ ((u32)Te4[(temp >> 24)] << 16) ^ ((u32)Te4[(temp) & 0xff] << 24) ^ rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) { - return 0; - } - rk += 4; - } - } - rk[4] = GETU32(userKey + 16); - rk[5] = GETU32(userKey + 20); - if (bits == 192) { - while (1) { - temp = rk[5]; - rk[6] = rk[0] ^ ((u32)Te4[(temp >> 8) & 0xff]) ^ ((u32)Te4[(temp >> 16) & 0xff] << 8) ^ ((u32)Te4[(temp >> 24)] << 16) ^ ((u32)Te4[(temp) & 0xff] << 24) ^ rcon[i]; - rk[7] = rk[1] ^ rk[6]; - rk[8] = rk[2] ^ rk[7]; - rk[9] = rk[3] ^ rk[8]; - if (++i == 8) { - return 0; - } - rk[10] = rk[4] ^ rk[9]; - rk[11] = rk[5] ^ rk[10]; - rk += 6; - } - } - rk[6] = GETU32(userKey + 24); - rk[7] = GETU32(userKey + 28); - if (bits == 256) { - while (1) { - temp = rk[7]; - rk[8] = rk[0] ^ ((u32)Te4[(temp >> 8) & 0xff]) ^ ((u32)Te4[(temp >> 16) & 0xff] << 8) ^ ((u32)Te4[(temp >> 24)] << 16) ^ ((u32)Te4[(temp) & 0xff] << 24) ^ rcon[i]; - rk[9] = rk[1] ^ rk[8]; - rk[10] = rk[2] ^ rk[9]; - rk[11] = rk[3] ^ rk[10]; - if (++i == 7) { - return 0; - } - temp = rk[11]; - rk[12] = rk[4] ^ ((u32)Te4[(temp) & 0xff]) ^ ((u32)Te4[(temp >> 8) & 0xff] << 8) ^ ((u32)Te4[(temp >> 16) & 0xff] << 16) ^ ((u32)Te4[(temp >> 24)] << 24); - rk[13] = rk[5] ^ rk[12]; - rk[14] = rk[6] ^ rk[13]; - rk[15] = rk[7] ^ rk[14]; - - rk += 8; - } - } - return 0; -} - -/** - * Expand the cipher key into the decryption key schedule. - */ -int AES_set_decrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key) -{ - - u32 *rk; - int i, j, status; - u32 temp; - - /* first, start with an encryption schedule */ - status = AES_set_encrypt_key(userKey, bits, key); - if (status < 0) - return status; - - rk = key->rd_key; - - /* invert the order of the round keys: */ - for (i = 0, j = 4 * (key->rounds); i < j; i += 4, j -= 4) { - temp = rk[i]; - rk[i] = rk[j]; - rk[j] = temp; - temp = rk[i + 1]; - rk[i + 1] = rk[j + 1]; - rk[j + 1] = temp; - temp = rk[i + 2]; - rk[i + 2] = rk[j + 2]; - rk[j + 2] = temp; - temp = rk[i + 3]; - rk[i + 3] = rk[j + 3]; - rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - for (i = 1; i < (key->rounds); i++) { - rk += 4; -#if 1 - for (j = 0; j < 4; j++) { - u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; - - tp1 = rk[j]; - m = tp1 & 0x80808080; - tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - m = tp2 & 0x80808080; - tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - m = tp4 & 0x80808080; - tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - tp9 = tp8 ^ tp1; - tpb = tp9 ^ tp2; - tpd = tp9 ^ tp4; - tpe = tp8 ^ tp4 ^ tp2; -#if defined(ROTATE) - rk[j] = tpe ^ ROTATE(tpd, 16) ^ ROTATE(tp9, 8) ^ ROTATE(tpb, 24); -#else - rk[j] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ (tp9 >> 24) ^ (tp9 << 8) ^ (tpb >> 8) ^ (tpb << 24); -#endif - } -#else - rk[0] = Td0[Te2[(rk[0]) & 0xff] & 0xff] ^ Td1[Te2[(rk[0] >> 8) & 0xff] & 0xff] ^ Td2[Te2[(rk[0] >> 16) & 0xff] & 0xff] ^ Td3[Te2[(rk[0] >> 24)] & 0xff]; - rk[1] = Td0[Te2[(rk[1]) & 0xff] & 0xff] ^ Td1[Te2[(rk[1] >> 8) & 0xff] & 0xff] ^ Td2[Te2[(rk[1] >> 16) & 0xff] & 0xff] ^ Td3[Te2[(rk[1] >> 24)] & 0xff]; - rk[2] = Td0[Te2[(rk[2]) & 0xff] & 0xff] ^ Td1[Te2[(rk[2] >> 8) & 0xff] & 0xff] ^ Td2[Te2[(rk[2] >> 16) & 0xff] & 0xff] ^ Td3[Te2[(rk[2] >> 24)] & 0xff]; - rk[3] = Td0[Te2[(rk[3]) & 0xff] & 0xff] ^ Td1[Te2[(rk[3] >> 8) & 0xff] & 0xff] ^ Td2[Te2[(rk[3] >> 16) & 0xff] & 0xff] ^ Td3[Te2[(rk[3] >> 24)] & 0xff]; -#endif - } - return 0; -} - -/* - * Encrypt a single block - * in and out can overlap - */ -void AES_encrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key) -{ - - const u32 *rk; - u32 s0, s1, s2, s3, t[4]; - int r; - - assert(in && out && key); - rk = key->rd_key; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(in) ^ rk[0]; - s1 = GETU32(in + 4) ^ rk[1]; - s2 = GETU32(in + 8) ^ rk[2]; - s3 = GETU32(in + 12) ^ rk[3]; - -#if defined(AES_COMPACT_IN_OUTER_ROUNDS) - prefetch256(Te4); - - t[0] = (u32)Te4[(s0) & 0xff] ^ (u32)Te4[(s1 >> 8) & 0xff] << 8 ^ (u32)Te4[(s2 >> 16) & 0xff] << 16 ^ (u32)Te4[(s3 >> 24)] << 24; - t[1] = (u32)Te4[(s1) & 0xff] ^ (u32)Te4[(s2 >> 8) & 0xff] << 8 ^ (u32)Te4[(s3 >> 16) & 0xff] << 16 ^ (u32)Te4[(s0 >> 24)] << 24; - t[2] = (u32)Te4[(s2) & 0xff] ^ (u32)Te4[(s3 >> 8) & 0xff] << 8 ^ (u32)Te4[(s0 >> 16) & 0xff] << 16 ^ (u32)Te4[(s1 >> 24)] << 24; - t[3] = (u32)Te4[(s3) & 0xff] ^ (u32)Te4[(s0 >> 8) & 0xff] << 8 ^ (u32)Te4[(s1 >> 16) & 0xff] << 16 ^ (u32)Te4[(s2 >> 24)] << 24; - - /* now do the linear transform using words */ - { - int i; - u32 r0, r1, r2; - - for (i = 0; i < 4; i++) { - r0 = t[i]; - r1 = r0 & 0x80808080; - r2 = ((r0 & 0x7f7f7f7f) << 1) ^ ((r1 - (r1 >> 7)) & 0x1b1b1b1b); -#if defined(ROTATE) - t[i] = r2 ^ ROTATE(r2, 24) ^ ROTATE(r0, 24) ^ ROTATE(r0, 16) ^ ROTATE(r0, 8); -#else - t[i] = r2 ^ ((r2 ^ r0) << 24) ^ ((r2 ^ r0) >> 8) ^ (r0 << 16) ^ (r0 >> 16) ^ (r0 << 8) ^ (r0 >> 24); -#endif - t[i] ^= rk[4 + i]; - } - } -#else - t[0] = Te0[(s0) & 0xff] ^ Te1[(s1 >> 8) & 0xff] ^ Te2[(s2 >> 16) & 0xff] ^ Te3[(s3 >> 24)] ^ rk[4]; - t[1] = Te0[(s1) & 0xff] ^ Te1[(s2 >> 8) & 0xff] ^ Te2[(s3 >> 16) & 0xff] ^ Te3[(s0 >> 24)] ^ rk[5]; - t[2] = Te0[(s2) & 0xff] ^ Te1[(s3 >> 8) & 0xff] ^ Te2[(s0 >> 16) & 0xff] ^ Te3[(s1 >> 24)] ^ rk[6]; - t[3] = Te0[(s3) & 0xff] ^ Te1[(s0 >> 8) & 0xff] ^ Te2[(s1 >> 16) & 0xff] ^ Te3[(s2 >> 24)] ^ rk[7]; -#endif - s0 = t[0]; - s1 = t[1]; - s2 = t[2]; - s3 = t[3]; - - /* - * Nr - 2 full rounds: - */ - for (rk += 8, r = key->rounds - 2; r > 0; rk += 4, r--) { -#if defined(AES_COMPACT_IN_INNER_ROUNDS) - t[0] = (u32)Te4[(s0) & 0xff] ^ (u32)Te4[(s1 >> 8) & 0xff] << 8 ^ (u32)Te4[(s2 >> 16) & 0xff] << 16 ^ (u32)Te4[(s3 >> 24)] << 24; - t[1] = (u32)Te4[(s1) & 0xff] ^ (u32)Te4[(s2 >> 8) & 0xff] << 8 ^ (u32)Te4[(s3 >> 16) & 0xff] << 16 ^ (u32)Te4[(s0 >> 24)] << 24; - t[2] = (u32)Te4[(s2) & 0xff] ^ (u32)Te4[(s3 >> 8) & 0xff] << 8 ^ (u32)Te4[(s0 >> 16) & 0xff] << 16 ^ (u32)Te4[(s1 >> 24)] << 24; - t[3] = (u32)Te4[(s3) & 0xff] ^ (u32)Te4[(s0 >> 8) & 0xff] << 8 ^ (u32)Te4[(s1 >> 16) & 0xff] << 16 ^ (u32)Te4[(s2 >> 24)] << 24; - - /* now do the linear transform using words */ - { - int i; - u32 r0, r1, r2; - - for (i = 0; i < 4; i++) { - r0 = t[i]; - r1 = r0 & 0x80808080; - r2 = ((r0 & 0x7f7f7f7f) << 1) ^ ((r1 - (r1 >> 7)) & 0x1b1b1b1b); -#if defined(ROTATE) - t[i] = r2 ^ ROTATE(r2, 24) ^ ROTATE(r0, 24) ^ ROTATE(r0, 16) ^ ROTATE(r0, 8); -#else - t[i] = r2 ^ ((r2 ^ r0) << 24) ^ ((r2 ^ r0) >> 8) ^ (r0 << 16) ^ (r0 >> 16) ^ (r0 << 8) ^ (r0 >> 24); -#endif - t[i] ^= rk[i]; - } - } -#else - t[0] = Te0[(s0) & 0xff] ^ Te1[(s1 >> 8) & 0xff] ^ Te2[(s2 >> 16) & 0xff] ^ Te3[(s3 >> 24)] ^ rk[0]; - t[1] = Te0[(s1) & 0xff] ^ Te1[(s2 >> 8) & 0xff] ^ Te2[(s3 >> 16) & 0xff] ^ Te3[(s0 >> 24)] ^ rk[1]; - t[2] = Te0[(s2) & 0xff] ^ Te1[(s3 >> 8) & 0xff] ^ Te2[(s0 >> 16) & 0xff] ^ Te3[(s1 >> 24)] ^ rk[2]; - t[3] = Te0[(s3) & 0xff] ^ Te1[(s0 >> 8) & 0xff] ^ Te2[(s1 >> 16) & 0xff] ^ Te3[(s2 >> 24)] ^ rk[3]; -#endif - s0 = t[0]; - s1 = t[1]; - s2 = t[2]; - s3 = t[3]; - } - /* - * apply last round and - * map cipher state to byte array block: - */ -#if defined(AES_COMPACT_IN_OUTER_ROUNDS) - prefetch256(Te4); - - *(u32 *)(out + 0) = (u32)Te4[(s0) & 0xff] ^ (u32)Te4[(s1 >> 8) & 0xff] << 8 ^ (u32)Te4[(s2 >> 16) & 0xff] << 16 ^ (u32)Te4[(s3 >> 24)] << 24 ^ rk[0]; - *(u32 *)(out + 4) = (u32)Te4[(s1) & 0xff] ^ (u32)Te4[(s2 >> 8) & 0xff] << 8 ^ (u32)Te4[(s3 >> 16) & 0xff] << 16 ^ (u32)Te4[(s0 >> 24)] << 24 ^ rk[1]; - *(u32 *)(out + 8) = (u32)Te4[(s2) & 0xff] ^ (u32)Te4[(s3 >> 8) & 0xff] << 8 ^ (u32)Te4[(s0 >> 16) & 0xff] << 16 ^ (u32)Te4[(s1 >> 24)] << 24 ^ rk[2]; - *(u32 *)(out + 12) = (u32)Te4[(s3) & 0xff] ^ (u32)Te4[(s0 >> 8) & 0xff] << 8 ^ (u32)Te4[(s1 >> 16) & 0xff] << 16 ^ (u32)Te4[(s2 >> 24)] << 24 ^ rk[3]; -#else - *(u32 *)(out + 0) = (Te2[(s0) & 0xff] & 0x000000ffU) ^ (Te3[(s1 >> 8) & 0xff] & 0x0000ff00U) ^ (Te0[(s2 >> 16) & 0xff] & 0x00ff0000U) ^ (Te1[(s3 >> 24)] & 0xff000000U) ^ rk[0]; - *(u32 *)(out + 4) = (Te2[(s1) & 0xff] & 0x000000ffU) ^ (Te3[(s2 >> 8) & 0xff] & 0x0000ff00U) ^ (Te0[(s3 >> 16) & 0xff] & 0x00ff0000U) ^ (Te1[(s0 >> 24)] & 0xff000000U) ^ rk[1]; - *(u32 *)(out + 8) = (Te2[(s2) & 0xff] & 0x000000ffU) ^ (Te3[(s3 >> 8) & 0xff] & 0x0000ff00U) ^ (Te0[(s0 >> 16) & 0xff] & 0x00ff0000U) ^ (Te1[(s1 >> 24)] & 0xff000000U) ^ rk[2]; - *(u32 *)(out + 12) = (Te2[(s3) & 0xff] & 0x000000ffU) ^ (Te3[(s0 >> 8) & 0xff] & 0x0000ff00U) ^ (Te0[(s1 >> 16) & 0xff] & 0x00ff0000U) ^ (Te1[(s2 >> 24)] & 0xff000000U) ^ rk[3]; -#endif -} - -/* - * Decrypt a single block - * in and out can overlap - */ -void AES_decrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key) -{ - - const u32 *rk; - u32 s0, s1, s2, s3, t[4]; - int r; - - assert(in && out && key); - rk = key->rd_key; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(in) ^ rk[0]; - s1 = GETU32(in + 4) ^ rk[1]; - s2 = GETU32(in + 8) ^ rk[2]; - s3 = GETU32(in + 12) ^ rk[3]; - -#if defined(AES_COMPACT_IN_OUTER_ROUNDS) - prefetch256(Td4); - - t[0] = (u32)Td4[(s0) & 0xff] ^ (u32)Td4[(s3 >> 8) & 0xff] << 8 ^ (u32)Td4[(s2 >> 16) & 0xff] << 16 ^ (u32)Td4[(s1 >> 24)] << 24; - t[1] = (u32)Td4[(s1) & 0xff] ^ (u32)Td4[(s0 >> 8) & 0xff] << 8 ^ (u32)Td4[(s3 >> 16) & 0xff] << 16 ^ (u32)Td4[(s2 >> 24)] << 24; - t[2] = (u32)Td4[(s2) & 0xff] ^ (u32)Td4[(s1 >> 8) & 0xff] << 8 ^ (u32)Td4[(s0 >> 16) & 0xff] << 16 ^ (u32)Td4[(s3 >> 24)] << 24; - t[3] = (u32)Td4[(s3) & 0xff] ^ (u32)Td4[(s2 >> 8) & 0xff] << 8 ^ (u32)Td4[(s1 >> 16) & 0xff] << 16 ^ (u32)Td4[(s0 >> 24)] << 24; - - /* now do the linear transform using words */ - { - int i; - u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; - - for (i = 0; i < 4; i++) { - tp1 = t[i]; - m = tp1 & 0x80808080; - tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - m = tp2 & 0x80808080; - tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - m = tp4 & 0x80808080; - tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - tp9 = tp8 ^ tp1; - tpb = tp9 ^ tp2; - tpd = tp9 ^ tp4; - tpe = tp8 ^ tp4 ^ tp2; -#if defined(ROTATE) - t[i] = tpe ^ ROTATE(tpd, 16) ^ ROTATE(tp9, 8) ^ ROTATE(tpb, 24); -#else - t[i] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ (tp9 >> 24) ^ (tp9 << 8) ^ (tpb >> 8) ^ (tpb << 24); -#endif - t[i] ^= rk[4 + i]; - } - } -#else - t[0] = Td0[(s0) & 0xff] ^ Td1[(s3 >> 8) & 0xff] ^ Td2[(s2 >> 16) & 0xff] ^ Td3[(s1 >> 24)] ^ rk[4]; - t[1] = Td0[(s1) & 0xff] ^ Td1[(s0 >> 8) & 0xff] ^ Td2[(s3 >> 16) & 0xff] ^ Td3[(s2 >> 24)] ^ rk[5]; - t[2] = Td0[(s2) & 0xff] ^ Td1[(s1 >> 8) & 0xff] ^ Td2[(s0 >> 16) & 0xff] ^ Td3[(s3 >> 24)] ^ rk[6]; - t[3] = Td0[(s3) & 0xff] ^ Td1[(s2 >> 8) & 0xff] ^ Td2[(s1 >> 16) & 0xff] ^ Td3[(s0 >> 24)] ^ rk[7]; -#endif - s0 = t[0]; - s1 = t[1]; - s2 = t[2]; - s3 = t[3]; - - /* - * Nr - 2 full rounds: - */ - for (rk += 8, r = key->rounds - 2; r > 0; rk += 4, r--) { -#if defined(AES_COMPACT_IN_INNER_ROUNDS) - t[0] = (u32)Td4[(s0) & 0xff] ^ (u32)Td4[(s3 >> 8) & 0xff] << 8 ^ (u32)Td4[(s2 >> 16) & 0xff] << 16 ^ (u32)Td4[(s1 >> 24)] << 24; - t[1] = (u32)Td4[(s1) & 0xff] ^ (u32)Td4[(s0 >> 8) & 0xff] << 8 ^ (u32)Td4[(s3 >> 16) & 0xff] << 16 ^ (u32)Td4[(s2 >> 24)] << 24; - t[2] = (u32)Td4[(s2) & 0xff] ^ (u32)Td4[(s1 >> 8) & 0xff] << 8 ^ (u32)Td4[(s0 >> 16) & 0xff] << 16 ^ (u32)Td4[(s3 >> 24)] << 24; - t[3] = (u32)Td4[(s3) & 0xff] ^ (u32)Td4[(s2 >> 8) & 0xff] << 8 ^ (u32)Td4[(s1 >> 16) & 0xff] << 16 ^ (u32)Td4[(s0 >> 24)] << 24; - - /* now do the linear transform using words */ - { - int i; - u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; - - for (i = 0; i < 4; i++) { - tp1 = t[i]; - m = tp1 & 0x80808080; - tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - m = tp2 & 0x80808080; - tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - m = tp4 & 0x80808080; - tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ ((m - (m >> 7)) & 0x1b1b1b1b); - tp9 = tp8 ^ tp1; - tpb = tp9 ^ tp2; - tpd = tp9 ^ tp4; - tpe = tp8 ^ tp4 ^ tp2; -#if defined(ROTATE) - t[i] = tpe ^ ROTATE(tpd, 16) ^ ROTATE(tp9, 8) ^ ROTATE(tpb, 24); -#else - t[i] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ (tp9 >> 24) ^ (tp9 << 8) ^ (tpb >> 8) ^ (tpb << 24); -#endif - t[i] ^= rk[i]; - } - } -#else - t[0] = Td0[(s0) & 0xff] ^ Td1[(s3 >> 8) & 0xff] ^ Td2[(s2 >> 16) & 0xff] ^ Td3[(s1 >> 24)] ^ rk[0]; - t[1] = Td0[(s1) & 0xff] ^ Td1[(s0 >> 8) & 0xff] ^ Td2[(s3 >> 16) & 0xff] ^ Td3[(s2 >> 24)] ^ rk[1]; - t[2] = Td0[(s2) & 0xff] ^ Td1[(s1 >> 8) & 0xff] ^ Td2[(s0 >> 16) & 0xff] ^ Td3[(s3 >> 24)] ^ rk[2]; - t[3] = Td0[(s3) & 0xff] ^ Td1[(s2 >> 8) & 0xff] ^ Td2[(s1 >> 16) & 0xff] ^ Td3[(s0 >> 24)] ^ rk[3]; -#endif - s0 = t[0]; - s1 = t[1]; - s2 = t[2]; - s3 = t[3]; - } - /* - * apply last round and - * map cipher state to byte array block: - */ - prefetch256(Td4); - - *(u32 *)(out + 0) = ((u32)Td4[(s0) & 0xff]) ^ ((u32)Td4[(s3 >> 8) & 0xff] << 8) ^ ((u32)Td4[(s2 >> 16) & 0xff] << 16) ^ ((u32)Td4[(s1 >> 24)] << 24) ^ rk[0]; - *(u32 *)(out + 4) = ((u32)Td4[(s1) & 0xff]) ^ ((u32)Td4[(s0 >> 8) & 0xff] << 8) ^ ((u32)Td4[(s3 >> 16) & 0xff] << 16) ^ ((u32)Td4[(s2 >> 24)] << 24) ^ rk[1]; - *(u32 *)(out + 8) = ((u32)Td4[(s2) & 0xff]) ^ ((u32)Td4[(s1 >> 8) & 0xff] << 8) ^ ((u32)Td4[(s0 >> 16) & 0xff] << 16) ^ ((u32)Td4[(s3 >> 24)] << 24) ^ rk[2]; - *(u32 *)(out + 12) = ((u32)Td4[(s3) & 0xff]) ^ ((u32)Td4[(s2 >> 8) & 0xff] << 8) ^ ((u32)Td4[(s1 >> 16) & 0xff] << 16) ^ ((u32)Td4[(s0 >> 24)] << 24) ^ rk[3]; -} From f6b5c45636f6294926b9c081716d67f42dc01ff3 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Mon, 18 May 2026 20:41:54 +1000 Subject: [PATCH 011/189] x509: check inner/outer signatureAlgorithm match in X509_CRL_verify RFC 5280 section 5.1.1.2 requires the signatureAlgorithm in the outer CertificateList wrapper to be identical to the signature field inside the signed TBSCertList. def_crl_verify() did not enforce this, unlike X509_verify() and X509_ACERT_verify() which both carry an X509_ALGOR_cmp guard. Add the same guard to def_crl_verify(). A mismatch raises X509_R_CRL_SIGNATURE_ALGORITHM_MISMATCH. No known attack results from the missing check; this is a conformance and hardening fix only. Add a regression test: a CRL with a valid RSA-SHA256 signature over a TBSCertList whose inner signatureAlgorithm claims ecdsaWithSHA256 is now rejected. Reviewed-by: Neil Horman Reviewed-by: Norbert Pocs MergeDate: Thu Jun 11 08:51:03 2026 (Merged from https://github.com/openssl/openssl/pull/31213) --- crypto/err/openssl.txt | 1 + crypto/x509/x509_err.c | 2 + crypto/x509/x_crl.c | 4 ++ include/openssl/x509err.h | 1 + test/crltest.c | 95 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 5b2ea1c4a4e67..be65c1767ec6a 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1861,6 +1861,7 @@ X509_R_CANT_CHECK_DH_KEY:114:can't check dh key X509_R_CERTIFICATE_VERIFICATION_FAILED:139:certificate verification failed X509_R_CERT_ALREADY_IN_HASH_TABLE:101:cert already in hash table X509_R_CRL_ALREADY_DELTA:127:crl already delta +X509_R_CRL_SIGNATURE_ALGORITHM_MISMATCH:147:crl signature algorithm mismatch X509_R_CRL_VERIFY_FAILURE:131:crl verify failure X509_R_DUPLICATE_ATTRIBUTE:140:duplicate attribute X509_R_ERROR_GETTING_MD_BY_NID:141:error getting md by nid diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index 3d6e8768f8bf9..90fdc60f25a61 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -26,6 +26,8 @@ static const ERR_STRING_DATA X509_str_reasons[] = { { ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE), "cert already in hash table" }, { ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "crl already delta" }, + { ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_SIGNATURE_ALGORITHM_MISMATCH), + "crl signature algorithm mismatch" }, { ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE), "crl verify failure" }, { ERR_PACK(ERR_LIB_X509, 0, X509_R_DUPLICATE_ATTRIBUTE), diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c index 4a93abb8ca3f9..b320b6ca2c230 100644 --- a/crypto/x509/x_crl.c +++ b/crypto/x509/x_crl.c @@ -404,6 +404,10 @@ int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r) { + if (X509_ALGOR_cmp(&crl->sig_alg, &crl->crl.sig_alg) != 0) { + ERR_raise(ERR_LIB_X509, X509_R_CRL_SIGNATURE_ALGORITHM_MISMATCH); + return 0; + } return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_CRL_INFO), &crl->sig_alg, &crl->signature, &crl->crl, NULL, r, crl->libctx, crl->propq); diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h index 7123a725e8254..53d3a540f2746 100644 --- a/include/openssl/x509err.h +++ b/include/openssl/x509err.h @@ -27,6 +27,7 @@ #define X509_R_CERTIFICATE_VERIFICATION_FAILED 139 #define X509_R_CERT_ALREADY_IN_HASH_TABLE 101 #define X509_R_CRL_ALREADY_DELTA 127 +#define X509_R_CRL_SIGNATURE_ALGORITHM_MISMATCH 147 #define X509_R_CRL_VERIFY_FAILURE 131 #define X509_R_DUPLICATE_ATTRIBUTE 140 #define X509_R_ERROR_GETTING_MD_BY_NID 141 diff --git a/test/crltest.c b/test/crltest.c index b89bef9c67357..274278addd0dd 100644 --- a/test/crltest.c +++ b/test/crltest.c @@ -329,6 +329,52 @@ static X509 *X509_from_strings(const char **pem) return x; } +/* + * A well-formed CRL issued by kRoot (sha256WithRSAEncryption, inner and + * outer signatureAlgorithm identical), used as the positive test case in + * test_crl_sigalg_mismatch. + */ +static const char *kCrlRootCA[] = { + "-----BEGIN X509 CRL-----\n", + "MIIB2jCBwwIBATANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMCVVMxEzARBgNV\n", + "BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFTATBgNVBAoM\n", + "DEV4YW1wbGUgQ29ycDEeMBwGA1UECwwVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR0w\n", + "GwYDVQQDDBRFeGFtcGxlIENvcnAgUm9vdCBDQRcNMjYwMTAxMDAwMDAwWhcNMjcw\n", + "MTAxMDAwMDAwWjANBgkqhkiG9w0BAQsFAAOCAQEAjLDGYBswRZpuaRh9qVXrP4i0\n", + "wttPikYZkkUk07/KU1zN6pS21Dqx1sEofrkqwRnKXq/hsoCz3sd7QFIv30v2iZwM\n", + "ioaksAjcGnaLqe8vuKVtIyiOpDSJR89l84BZr2I9+6osTYnPgroMHQ/7OUt+PKdE\n", + "1VAkA137tLMRw2qGPELdCyHA7LXr0gI6jeyLPLtb1blQrMzznp3y/trNWa+DKq6h\n", + "SflQrixmLeXTMBD/DDUd8Kj9HHmejbJNAsgaNHv9mtIhUVEspRM0020b3AeJyfTP\n", + "3oN/y4fgQ8q5v9i8lDbe8moCo+W0rS4ksWvB6SuYYj/NkUE4EtoIreSVtcz8JA==\n", + "-----END X509 CRL-----\n", + NULL +}; + +/* + * kCrlMismatchedSigAlg is issued by kRoot with a deliberately inconsistent + * pair of signatureAlgorithm fields: the inner (signed) copy inside + * TBSCertList claims ecdsaWithSHA256, while the outer wrapper carries + * sha256WithRSAEncryption -- and the actual signature is a valid RSA-SHA256 + * signature over that TBSCertList. Without the inner/outer comparison, + * X509_CRL_verify() would accept this CRL because the RSA signature checks + * out. RFC 5280 section 5.1.1.2 requires the two fields to be identical. + */ +static const char *kCrlMismatchedSigAlg[] = { + "-----BEGIN X509 CRL-----\n", + "MIIB1zCBwAIBATAKBggqhkjOPQQDAjCBkDELMAkGA1UEBhMCVVMxEzARBgNVBAgM\n", + "CkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFTATBgNVBAoMDEV4\n", + "YW1wbGUgQ29ycDEeMBwGA1UECwwVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR0wGwYD\n", + "VQQDDBRFeGFtcGxlIENvcnAgUm9vdCBDQRcNMjYwMTAxMDAwMDAwWhcNMjcwMTAx\n", + "MDAwMDAwWjANBgkqhkiG9w0BAQsFAAOCAQEAcle5SUuN1XIx5amjddTqDPyEm9pP\n", + "sNeBwR+TQi19pWHtQ5anr6PBIAxHC5uxhVpZDScZu0TlodWigo+1bfAJRyrIm/6+\n", + "AbmAyNC4txpNsOHgCFGW7q9T8OutaOhUw+jC6i3bxUQZ64L1sXuy2nZMzU19+Aro\n", + "TxSWYkIJg65SKwM/8ggyd5G7TXkv7w19+W/7Y9JV0c+kPueUZSgEGUG/GJF/Nrrc\n", + "TRfvqz7Qs9H9+hUiQl5K7tF9gj6aU3p1s1IZKR2x0lv4wDRUUgIjrvRzfQSGjhgf\n", + "6rBILI3EIxPN/PoZ3mHLYkhH5IyNj9R2GlMle52isNdW8BiNlePLx0/Jzg==\n", + "-----END X509 CRL-----\n", + NULL +}; + /* * Verify |leaf| certificate (chained up to |root|). |crls| if * not NULL, is a list of CRLs to include in the verification. It is @@ -615,6 +661,53 @@ static int test_get_crl_fn_score(void) return status == X509_V_OK; } +/* + * Check that X509_CRL_verify() rejects a CRL where the outer + * signatureAlgorithm does not match the inner copy inside TBSCertList. + * RFC 5280 section 5.1.1.2 requires the two to be identical; X509_verify() + * and X509_ACERT_verify() enforce this, and so must X509_CRL_verify(). + * + * Both CRLs are issued by kRoot (RSA-2048). kCrlMismatchedSigAlg carries a + * valid RSA-SHA256 signature over a TBSCertList whose inner signatureAlgorithm + * claims ecdsaWithSHA256, while the outer wrapper carries the correct + * sha256WithRSAEncryption. Without the inner/outer comparison the signature + * would verify and the CRL would be accepted. + */ +static int test_crl_sigalg_mismatch(void) +{ + X509 *root = X509_from_strings(kRoot); + X509_CRL *good = CRL_from_strings(kCrlRootCA); + X509_CRL *bad = CRL_from_strings(kCrlMismatchedSigAlg); + EVP_PKEY *pkey = NULL; + int ret = 0; + + if (!TEST_ptr(root) || !TEST_ptr(good) || !TEST_ptr(bad)) + goto end; + + pkey = X509_get0_pubkey(root); + if (!TEST_ptr(pkey)) + goto end; + + /* Well-formed CRL: inner and outer algorithms match; verify succeeds. */ + if (!TEST_int_eq(X509_CRL_verify(good, pkey), 1)) + goto end; + + /* + * Mismatched CRL: inner signatureAlgorithm is ecdsaWithSHA256, outer is + * sha256WithRSAEncryption, RSA signature is valid. X509_ALGOR_cmp() + * must catch the mismatch before the signature is checked. + */ + if (!TEST_int_eq(X509_CRL_verify(bad, pkey), 0)) + goto end; + + ret = 1; +end: + X509_CRL_free(good); + X509_CRL_free(bad); + X509_free(root); + return ret; +} + int setup_tests(void) { if (!TEST_ptr(test_root = X509_from_strings(kCRLTestRoot)) @@ -631,6 +724,8 @@ int setup_tests(void) ADD_TEST(test_get_crl_fn_score); ADD_ALL_TESTS(test_unknown_critical_crl, OSSL_NELEM(unknown_critical_crls)); ADD_ALL_TESTS(test_reuse_crl, 6); + ADD_TEST(test_crl_sigalg_mismatch); + return 1; } From bc7283334f74caf59800af5980feea4ab52bfb16 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Wed, 3 Jun 2026 23:58:39 +0530 Subject: [PATCH 012/189] uni2utf8: reject negative length like uni2asc Reviewed-by: Alicja Kario Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Thu Jun 11 08:57:14 2026 (Merged from https://github.com/openssl/openssl/pull/31378) --- crypto/pkcs12/p12_utl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c index a6f3248c554c9..f252fd1a0061a 100644 --- a/crypto/pkcs12/p12_utl.c +++ b/crypto/pkcs12/p12_utl.c @@ -186,6 +186,8 @@ char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen) /* string must contain an even number of bytes */ if (unilen & 1) return NULL; + if (unilen < 0) + return NULL; for (asclen = 0, i = 0; i < unilen;) { j = bmp_to_utf8(NULL, uni + i, unilen - i); From 96c192eafe1af2970d8d51ea19c05a085991ca2f Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 11 Jun 2026 12:08:45 +0200 Subject: [PATCH 013/189] crltest.c: Add missing root certificate Fixes c2ef9e10dc9627243e1a47f76423edc30667b150 Reviewed-by: Richard Levitte Reviewed-by: Norbert Pocs MergeDate: Thu Jun 11 10:30:02 2026 (Merged from https://github.com/openssl/openssl/pull/31453) (cherry picked from commit d6ecc304f4302f0a655487d9ff8a65283c152894) --- test/crltest.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/crltest.c b/test/crltest.c index 274278addd0dd..904cf089440ba 100644 --- a/test/crltest.c +++ b/test/crltest.c @@ -26,6 +26,34 @@ * https://github.com/openssl/openssl/issues/27506 are used. */ +static const char *kRoot[] = { + "-----BEGIN CERTIFICATE-----\n", + "MIIEFjCCAv6gAwIBAgIUQR1kHB+/IzJcfAT/HHVPp+wPmxwwDQYJKoZIhvcNAQEL\n", + "BQAwgZAxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH\n", + "DA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKDAxFeGFtcGxlIENvcnAxHjAcBgNVBAsM\n", + "FUNlcnRpZmljYXRlIEF1dGhvcml0eTEdMBsGA1UEAwwURXhhbXBsZSBDb3JwIFJv\n", + "b3QgQ0EwHhcNMjYwMzEwMTEzMDUzWhcNMzYwMzA3MTEzMDUzWjCBkDELMAkGA1UE\n", + "BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lz\n", + "Y28xFTATBgNVBAoMDEV4YW1wbGUgQ29ycDEeMBwGA1UECwwVQ2VydGlmaWNhdGUg\n", + "QXV0aG9yaXR5MR0wGwYDVQQDDBRFeGFtcGxlIENvcnAgUm9vdCBDQTCCASIwDQYJ\n", + "KoZIhvcNAQEBBQADggEPADCCAQoCggEBALm21ITU+2o6ZHWukCyBw9H270fSABYT\n", + "rl8lhPCcTXynW9tBeHAaV50WMiOxBl+thfv1fGS3t8BbyjEjP3I5LAkBS9dTUI7F\n", + "PSQnngBgKvKrpsnsiJXVhNOISm6GfT/EXj1NWKLXR3MXGIGfiVud5ln9CQxzaq3e\n", + "TzW8X8zsdv6WGaeRIBm48QYe8TkK/TDmvoYZ7fD9lPMk3AUoNasZfuPeGpzh1cBR\n", + "bfvOYEHJQ31+GFzrJFldqoaq/k0If/khwVgjOdmF+R25OCF0jsrMjmZ42Qr2cNrd\n", + "VYEIjQL2R1grCVCGaIagzQuyN0Qvvl5BXsHKI51TpDQlq9SFkCOvRckCAwEAAaNm\n", + "MGQwHQYDVR0OBBYEFP4UDhMbCWfLSg1L2k/z75C1Q9szMB8GA1UdIwQYMBaAFP4U\n", + "DhMbCWfLSg1L2k/z75C1Q9szMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/\n", + "BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQBcYi8b4tetG18ElSqF/CJkjm93xS6k\n", + "tk4jia0k+79FSAvy/TlcarBAe3PwlLA7GcLYDUmmM7GCiEMf91+c6dOmKkIdbw1B\n", + "FILQBnghZ9s+xl0+n1P0775dDWc0msXhXci/wcRK3HFqxEOXQUkDYZwrq1gXBESr\n", + "6yjpYe2RFKQUdnW+yrMlY1QyGNhelV7//BbSG8fD1esU7VaBE0wF/b8Ly2ykK5QE\n", + "d6XUwqTT6sIlcyxVGUgEMVj7kSZUQJ2LS/ze/r+a1FeC2I0UljD78UB+I40FafZe\n", + "pLLvkABIXRqtOiZ5YkdEK3Z4xI0yqSZC3og4jHsoCrfWbXasRieYR7dT\n", + "-----END CERTIFICATE-----\n", + NULL +}; + #define PARAM_TIME 1474934400 /* Sep 27th, 2016 */ #define PARAM_TIME2 1753284700 /* July 23th, 2025 */ From 24cf73167057fa7802ca9641976e01a84a9ffb36 Mon Sep 17 00:00:00 2001 From: Jon Spillett Date: Fri, 5 Jun 2026 06:23:07 +1000 Subject: [PATCH 014/189] Fix up mismatched error reason codes Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs Reviewed-by: Milan Broz Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz MergeDate: Thu Jun 11 16:06:41 2026 (Merged from https://github.com/openssl/openssl/pull/31390) (cherry picked from commit 6c90156f3e506f443e92b4a20ece685b7680e211) --- crypto/ct/ct_b64.c | 6 +++--- crypto/dh/dh_backend.c | 2 +- crypto/x509/x_pubkey.c | 2 +- providers/implementations/macs/cmac_prov.c | 2 +- providers/implementations/rands/test_rng.c | 2 +- providers/implementations/signature/rsa_sig.c | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c index e7eb9740ee08b..f863ff716c48c 100644 --- a/crypto/ct/ct_b64.c +++ b/crypto/ct/ct_b64.c @@ -84,7 +84,7 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, declen = ct_base64_decode(logid_base64, &dec); if (declen < 0) { - ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR); + ERR_raise(ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR); goto err; } if (!SCT_set0_log_id(sct, dec, declen)) @@ -93,7 +93,7 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, declen = ct_base64_decode(extensions_base64, &dec); if (declen < 0) { - ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR); + ERR_raise(ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR); goto err; } SCT_set0_extensions(sct, dec, declen); @@ -101,7 +101,7 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, declen = ct_base64_decode(signature_base64, &dec); if (declen < 0) { - ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR); + ERR_raise(ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR); goto err; } diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c index f68429862cd56..5844c3556062f 100644 --- a/crypto/dh/dh_backend.c +++ b/crypto/dh/dh_backend.c @@ -232,7 +232,7 @@ DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, goto done; decerr: - ERR_raise(ERR_LIB_DH, EVP_R_DECODE_ERROR); + ERR_raise(ERR_LIB_DH, DH_R_DECODE_ERROR); dherr: DH_free(dh); dh = NULL; diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 03f532ab9cb37..8e0ee3a2197ff 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -224,7 +224,7 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval, * bytes. */ ERR_clear_last_mark(); - ERR_raise(ERR_LIB_ASN1, EVP_R_DECODE_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR); goto end; } } diff --git a/providers/implementations/macs/cmac_prov.c b/providers/implementations/macs/cmac_prov.c index 58a842776233c..72e73834d8397 100644 --- a/providers/implementations/macs/cmac_prov.c +++ b/providers/implementations/macs/cmac_prov.c @@ -275,7 +275,7 @@ static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) && !EVP_CIPHER_is_a(cipher, "AES-192-CBC") && !EVP_CIPHER_is_a(cipher, "AES-128-CBC") && !EVP_CIPHER_is_a(cipher, "DES-EDE3-CBC")) { - ERR_raise(ERR_LIB_PROV, EVP_R_UNSUPPORTED_CIPHER); + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CIPHER); return 0; } } diff --git a/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c index 7942537879f1e..01f35702da467 100644 --- a/providers/implementations/rands/test_rng.c +++ b/providers/implementations/rands/test_rng.c @@ -305,7 +305,7 @@ static int test_rng_enable_locking(void *vtest) if (t != NULL && t->lock == NULL) { t->lock = CRYPTO_THREAD_lock_new(); if (t->lock == NULL) { - ERR_raise(ERR_LIB_PROV, RAND_R_FAILED_TO_CREATE_LOCK); + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK); return 0; } } diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c index 28f3e15b59856..6790264a4705d 100644 --- a/providers/implementations/signature/rsa_sig.c +++ b/providers/implementations/signature/rsa_sig.c @@ -591,7 +591,7 @@ rsa_signverify_init(PROV_RSA_CTX *prsactx, void *vrsa, break; default: - ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ERR_raise(ERR_LIB_PROV, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return 0; } @@ -1947,7 +1947,7 @@ static int rsa_sigalg_signverify_init(void *vprsactx, void *vrsa, /* PSS is currently not supported as a sigalg */ if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) { - ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ERR_raise(ERR_LIB_PROV, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return 0; } From e4fccf6909d8a2849aef9e036441f5f66857c9d8 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 12 Jun 2026 08:17:17 +0200 Subject: [PATCH 015/189] test_rng.c: Include proverr.h Fixes a1d19889c19d924b32a3c89578e0310cf261523d Reviewed-by: Richard Levitte Reviewed-by: Milan Broz MergeDate: Fri Jun 12 06:34:54 2026 (Merged from https://github.com/openssl/openssl/pull/31475) (cherry picked from commit 00fddc9afe7d593c8baf3ab530717215220351f4) --- providers/implementations/rands/test_rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c index 01f35702da467..d7dff7fd414de 100644 --- a/providers/implementations/rands/test_rng.c +++ b/providers/implementations/rands/test_rng.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "prov/securitycheck.h" #include "prov/providercommon.h" #include "prov/provider_ctx.h" From 23b03960e099e26226546018bcedd02028988cc1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 12 Jun 2026 08:04:52 +0200 Subject: [PATCH 016/189] Replace missing reason code with another one There is no PROV_R_INVALID_CIPHER on 3.6 use PROV_R_NOT_SUPPORTED instead. Fixes 73807b38a355ffb2b4cebcb938b0a452166474b7 Reviewed-by: Richard Levitte Reviewed-by: Milan Broz MergeDate: Fri Jun 12 06:34:15 2026 (Merged from https://github.com/openssl/openssl/pull/31474) (cherry picked from commit 0217baf4674b0c4c8e67ae9d1e3886796754ed03) --- providers/implementations/macs/cmac_prov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/implementations/macs/cmac_prov.c b/providers/implementations/macs/cmac_prov.c index 72e73834d8397..8cf8ab0342981 100644 --- a/providers/implementations/macs/cmac_prov.c +++ b/providers/implementations/macs/cmac_prov.c @@ -275,7 +275,7 @@ static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) && !EVP_CIPHER_is_a(cipher, "AES-192-CBC") && !EVP_CIPHER_is_a(cipher, "AES-128-CBC") && !EVP_CIPHER_is_a(cipher, "DES-EDE3-CBC")) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CIPHER); + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return 0; } } From b7246a65100337621ef8078decd1d80fe743c359 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Sun, 14 Jun 2026 19:04:46 +0200 Subject: [PATCH 017/189] ci: Switch to VS 2026 for windows-2025 image GitHub no longer supports Visual Studio 2022 on windows-2025 image, switch to VS 2026. Reviewed-by: Nikola Pajkovsky Reviewed-by: Tomas Mraz MergeDate: Mon Jun 15 07:23:17 2026 (Merged from https://github.com/openssl/openssl/pull/31497) (cherry picked from commit 164c156750ed9aee61df1c9631f6fa05038a51cc) --- .github/workflows/os-zoo.yml | 2 +- .github/workflows/windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/os-zoo.yml b/.github/workflows/os-zoo.yml index 74208d01029fd..bd5d641ec8a60 100644 --- a/.github/workflows/os-zoo.yml +++ b/.github/workflows/os-zoo.yml @@ -137,7 +137,7 @@ jobs: - os: windows-2022 vcvars: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - os: windows-2025 - vcvars: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + vcvars: C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v6 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a3449c74bfe2a..858f80c683474 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -25,7 +25,7 @@ jobs: - arch: amd64 os: windows-2025 config: enable-fips no-thread-pool no-quic - vcvars: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + vcvars: C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat - arch: x86 os: windows-2022 config: no-fips From 11fb223813931724096c1b3f704c290b5231ef31 Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Tue, 9 Jun 2026 10:58:52 +0200 Subject: [PATCH 018/189] Fix use-after-free issue in radix test framework for QUIC. The test for client_hello and new_pending connection should be using its own dedicated SSL context. The thing is we should not be arming (and testing) those callbacks for every listener the RADIX test framework creates. This changeset moves the test from test/radix/quic_ops.c to test/radix/quic_tests.c. The test uses check_ctx_cbks RADIX script now. Reviewed-by: Tom Cosgrove Reviewed-by: Tomas Mraz MergeDate: Mon Jun 15 07:29:02 2026 (Merged from https://github.com/openssl/openssl/pull/31421) (cherry picked from commit 461b6886285afe174a2a7385541a1ac98c08e35f) --- test/radix/quic_ops.c | 59 ----------------- test/radix/quic_tests.c | 141 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 59 deletions(-) diff --git a/test/radix/quic_ops.c b/test/radix/quic_ops.c index 4475f91803232..88b8b0e371a27 100644 --- a/test/radix/quic_ops.c +++ b/test/radix/quic_ops.c @@ -142,45 +142,6 @@ static int ssl_attach_bio_dgram(SSL *ssl, return 1; } -/* - * Test to make sure that SSL_accept_connection returns the same ssl object - * that is used in the various TLS callbacks - * - * Unlike TCP, QUIC processes new connections independently from their - * acceptance, and so we need to pre-allocate tls objects to return during - * connection acceptance via the user_ssl. This is just a quic test to validate - * that: - * 1) The new callback to inform the user of a new pending ssl acceptance works - * properly - * 2) That the object returned from SSL_accept_connection matches the one passed - * to various callbacks - * - * It would be better as its own test, but currently the tserver used in the - * other quic_tests doesn't actually accept connections (it pre-creates them - * and fixes them up in place), so testing there is not feasible at the moment - * - * For details on this issue see: - * https://github.com/openssl/project/issues/918 - */ -static SSL *pending_ssl_obj = NULL; -static SSL *client_hello_ssl_obj = NULL; -static int check_pending_match = 0; -static int pending_cb_called = 0; -static int hello_cb_called = 0; -static int new_pending_cb(SSL_CTX *ctx, SSL *new_ssl, void *arg) -{ - pending_ssl_obj = new_ssl; - pending_cb_called = 1; - return 1; -} - -static int client_hello_cb(SSL *s, int *al, void *arg) -{ - client_hello_ssl_obj = s; - hello_cb_called = 1; - return 1; -} - DEF_FUNC(hf_new_ssl) { int ok = 0; @@ -215,9 +176,6 @@ DEF_FUNC(hf_new_ssl) goto err; } else if (is_server) { - SSL_CTX_set_new_pending_conn_cb(ctx, new_pending_cb, NULL); - SSL_CTX_set_client_hello_cb(ctx, client_hello_cb, NULL); - check_pending_match = 1; if (!TEST_ptr(ssl = SSL_new_listener(ctx, 0))) goto err; } else { @@ -351,23 +309,6 @@ DEF_FUNC(hf_accept_conn) goto err; } - if (check_pending_match) { - if (!pending_cb_called || !hello_cb_called) { - TEST_info("Callbacks not called, skipping user_ssl check\n"); - } else { - if (!TEST_ptr_eq(pending_ssl_obj, client_hello_ssl_obj)) { - SSL_free(conn); - goto err; - } - if (!TEST_ptr_eq(pending_ssl_obj, conn)) { - SSL_free(conn); - goto err; - } - } - pending_ssl_obj = client_hello_ssl_obj = NULL; - check_pending_match = 0; - pending_cb_called = hello_cb_called = 0; - } ok = 1; err: return ok; diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c index d6f0a19077a2b..3008048aa43d1 100644 --- a/test/radix/quic_tests.c +++ b/test/radix/quic_tests.c @@ -476,6 +476,146 @@ DEF_SCRIPT(check_pc_flood, "check path challenge flood") OP_FUNC(check_flood_stats); } +/* + * Test to make sure that SSL_accept_connection returns the same ssl object + * that is used in the various TLS callbacks + * + * Unlike TCP, QUIC processes new connections independently from their + * acceptance, and so we need to pre-allocate tls objects to return during + * connection acceptance via the user_ssl. This is just a quic test to validate + * that: + * 1) The new callback to inform the user of a new pending ssl acceptance works + * properly + * 2) That the object returned from SSL_accept_connection matches the one passed + * to various callbacks + * + * It would be better as its own test, but currently the tserver used in the + * other quic_tests doesn't actually accept connections (it pre-creates them + * and fixes them up in place), so testing there is not feasible at the moment + * + * For details on this issue see: + * https://github.com/openssl/project/issues/918 + */ +static SSL *pending_ssl_obj = NULL; +static SSL *client_hello_ssl_obj = NULL; +static int check_pending_match = 0; +static int pending_cb_called = 0; +static int hello_cb_called = 0; + +static int new_pending_cb(SSL_CTX *ctx, SSL *new_ssl, void *arg) +{ + pending_ssl_obj = new_ssl; + pending_cb_called = 1; + return 1; +} + +static int client_hello_cb(SSL *s, int *al, void *arg) +{ + client_hello_ssl_obj = s; + hello_cb_called = 1; + return 1; +} + +DEF_FUNC(init_pending_test) +{ + pending_ssl_obj = NULL; + client_hello_ssl_obj = NULL; + check_pending_match = 0; + pending_cb_called = 0; + hello_cb_called = 0; + + return 1; +} + +DEF_FUNC(check_pending) +{ + int ok = 0; + SSL *conn; + + REQUIRE_SSL(conn); + + if (check_pending_match) { + if (!TEST_true(pending_cb_called)) + goto err; + + if (!TEST_true(hello_cb_called)) + goto err; + + if (!TEST_ptr_eq(pending_ssl_obj, client_hello_ssl_obj)) + goto err; + + if (!TEST_ptr_eq(pending_ssl_obj, conn)) + goto err; + + pending_ssl_obj = client_hello_ssl_obj = NULL; + check_pending_match = 0; + pending_cb_called = hello_cb_called = 0; + } + + ok = 1; +err: + return ok; +} + +DEF_FUNC(new_listener) +{ + int ok = 0; + SSL_CTX *ctx = NULL; + SSL *listener; + const char *name; + + F_POP(name); + + if (!TEST_ptr(ctx = SSL_CTX_new(OSSL_QUIC_server_method()))) + goto err; + +#if defined(OPENSSL_THREADS) + if (!TEST_true(SSL_CTX_set_domain_flags(ctx, + SSL_DOMAIN_FLAG_MULTI_THREAD + | SSL_DOMAIN_FLAG_BLOCKING))) + goto err; +#endif + + if (!TEST_true(ssl_ctx_configure(ctx, 1))) + goto err; + + SSL_CTX_set_new_pending_conn_cb(ctx, new_pending_cb, NULL); + SSL_CTX_set_client_hello_cb(ctx, client_hello_cb, NULL); + check_pending_match = 1; + if (!TEST_ptr(listener = SSL_new_listener(ctx, 0))) + goto err; + + if (!TEST_true(ssl_attach_bio_dgram(listener, 0, NULL))) { + SSL_free(listener); + goto err; + } + + if (!TEST_true(RADIX_PROCESS_set_ssl(RP(), name, listener))) { + SSL_free(listener); + goto err; + } + + ok = 1; +err: + /* SSL object will hold ref, we don't need it */ + SSL_CTX_free(ctx); + return ok; +} + +DEF_SCRIPT(check_ctx_cbks, "Check new_pending and client_hello callbacks") +{ + OP_FUNC(init_pending_test); + OP_PUSH_PZ("L"); + OP_FUNC(new_listener); + OP_LISTEN(L); + OP_NEW_SSL_C(C); + OP_SET_PEER_ADDR_FROM(C, L); + OP_CONNECT_WAIT(C); + OP_ACCEPT_CONN_WAIT(L, S, 0); + OP_SELECT_SSL(0, S); + OP_FUNC(check_pending); +} + /* * List of Test Scripts * ============================================================================ @@ -486,4 +626,5 @@ static SCRIPT_INFO *const scripts[] = { USE(ssl_poll), USE(check_cwm), USE(check_pc_flood), + USE(check_ctx_cbks), }; From 9dd0977a53ff3b7add83d110a034a766f32e30da Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 11 Jun 2026 17:37:31 +0200 Subject: [PATCH 019/189] test: Invert bad TEST() condition calls False result of a TEST_xxx() call should always indicate erroneous condition. Fix such calls. Also fix some calls which treated TEST_xxx() result as non-boolean. Reviewed-by: Paul Dale Reviewed-by: Richard Levitte Reviewed-by: Norbert Pocs MergeDate: Mon Jun 15 07:38:52 2026 (Merged from https://github.com/openssl/openssl/pull/31457) (cherry picked from commit 7c765bb6020b7c391dea8112f403e3b2109ff6dd) --- test/ca_internals_test.c | 4 ++-- test/evp_extra_test2.c | 2 +- test/hpke_test.c | 22 +++++++++------------- test/http_test.c | 4 ++-- test/pkcs12_api_test.c | 4 ++-- test/punycode_test.c | 2 +- test/radix/quic_tests.c | 4 ++-- test/secmemtest.c | 2 +- 8 files changed, 20 insertions(+), 24 deletions(-) diff --git a/test/ca_internals_test.c b/test/ca_internals_test.c index 0b0b2f3b70976..ed922a36dd28a 100644 --- a/test/ca_internals_test.c +++ b/test/ca_internals_test.c @@ -48,13 +48,13 @@ static int test_do_updatedb(void) testdate = test_get_argument(2); testdateutc = test_asn1_string_to_time_t(testdate); - if (TEST_time_t_lt(testdateutc, 0)) { + if (!TEST_time_t_ge(testdateutc, 0)) { return 0; } indexfile = test_get_argument(1); db = load_index(indexfile, NULL); - if (TEST_ptr_null(db)) { + if (!TEST_ptr(db)) { return 0; } diff --git a/test/evp_extra_test2.c b/test/evp_extra_test2.c index 4458f5b2426f1..b951b8c32d3aa 100644 --- a/test/evp_extra_test2.c +++ b/test/evp_extra_test2.c @@ -494,7 +494,7 @@ static int test_new_keytype(void) unsigned char *out = NULL, *secret = NULL, *secret2 = NULL; /* without tls-provider key should not be create-able */ - if (TEST_ptr(key = EVP_PKEY_Q_keygen(mainctx, NULL, "XOR"))) + if (!TEST_ptr_null(key = EVP_PKEY_Q_keygen(mainctx, NULL, "XOR"))) goto err; /* prepare & load tls-provider */ if (!TEST_true(OSSL_PROVIDER_add_builtin(mainctx, "tls-provider", diff --git a/test/hpke_test.c b/test/hpke_test.c index c7b30012ad2b4..df3f4574a0f06 100644 --- a/test/hpke_test.c +++ b/test/hpke_test.c @@ -949,10 +949,9 @@ static int test_hpke_modes_suites(void) hpke_suite.kem_id = kem_id; if (hpke_mode == OSSL_HPKE_MODE_AUTH || hpke_mode == OSSL_HPKE_MODE_PSKAUTH) { - if (TEST_true(OSSL_HPKE_keygen(hpke_suite, authpub, &authpublen, + if (!TEST_true(OSSL_HPKE_keygen(hpke_suite, authpub, &authpublen, &authpriv, NULL, 0, - testctx, NULL)) - != 1) { + testctx, NULL))) { overallresult = 0; } authpubp = authpub; @@ -1195,7 +1194,7 @@ static int test_hpke_suite_strs(void) for (aeadind = 0; aeadind != OSSL_NELEM(aead_str_list); aeadind++) { BIO_snprintf(sstr, 128, "%s,%s,%s", kem_str_list[kemind], kdf_str_list[kdfind], aead_str_list[aeadind]); - if (TEST_true(OSSL_HPKE_str2suite(sstr, &stirred)) != 1) { + if (!TEST_true(OSSL_HPKE_str2suite(sstr, &stirred))) { if (verbose) TEST_note("Unexpected str2suite fail for :%s", bogus_suite_strs[sind]); @@ -1205,9 +1204,8 @@ static int test_hpke_suite_strs(void) } } for (sind = 0; sind != OSSL_NELEM(bogus_suite_strs); sind++) { - if (TEST_false(OSSL_HPKE_str2suite(bogus_suite_strs[sind], - &stirred)) - != 1) { + if (!TEST_false(OSSL_HPKE_str2suite(bogus_suite_strs[sind], + &stirred))) { if (verbose) TEST_note("OSSL_HPKE_str2suite didn't fail for bogus[%d]:%s", sind, bogus_suite_strs[sind]); @@ -1250,20 +1248,18 @@ static int test_hpke_grease(void) /* GREASEing */ /* check too short for public value */ g_pub_len = 10; - if (TEST_false(OSSL_HPKE_get_grease_value(NULL, &g_suite, + if (!TEST_false(OSSL_HPKE_get_grease_value(NULL, &g_suite, g_pub, &g_pub_len, g_cipher, g_cipher_len, - testctx, NULL)) - != 1) { + testctx, NULL))) { overallresult = 0; } /* reset to work */ g_pub_len = OSSL_HPKE_TSTSIZE; - if (TEST_true(OSSL_HPKE_get_grease_value(NULL, &g_suite, + if (!TEST_true(OSSL_HPKE_get_grease_value(NULL, &g_suite, g_pub, &g_pub_len, g_cipher, g_cipher_len, - testctx, NULL)) - != 1) { + testctx, NULL))) { overallresult = 0; } /* expansion */ diff --git a/test/http_test.c b/test/http_test.c index 8ce889d9bc7f9..94c1171fb784e 100644 --- a/test/http_test.c +++ b/test/http_test.c @@ -586,7 +586,7 @@ static int test_http_resp_hdr_limit(size_t limit) int res = 0; OSSL_HTTP_REQ_CTX *rctx = NULL; - if (TEST_ptr(wbio) == 0 || TEST_ptr(rbio) == 0) + if (!TEST_ptr(wbio) || !TEST_ptr(rbio)) goto err; mock_args.txt = text1; @@ -598,7 +598,7 @@ static int test_http_resp_hdr_limit(size_t limit) BIO_set_callback_arg(wbio, (char *)&mock_args); rctx = OSSL_HTTP_REQ_CTX_new(wbio, rbio, 8192); - if (TEST_ptr(rctx) == 0) + if (!TEST_ptr(rctx)) goto err; if (!TEST_true(OSSL_HTTP_REQ_CTX_set_request_line(rctx, 0 /* GET */, diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c index 147d65bd665ab..b98343da86af3 100644 --- a/test/pkcs12_api_test.c +++ b/test/pkcs12_api_test.c @@ -175,7 +175,7 @@ static int pkcs12_create_ex2_test(int test) 0, 0, 0, testctx, NULL, NULL, NULL); - if (TEST_ptr(ptr)) + if (!TEST_ptr_null(ptr)) goto err; /* Can't proceed without a valid cert at least */ @@ -201,7 +201,7 @@ static int pkcs12_create_ex2_test(int test) testctx, NULL, pkcs12_create_cb, (void *)&cb_ret); /* PKCS12 not created */ - if (TEST_ptr(ptr)) + if (!TEST_ptr_null(ptr)) goto err; } else if (test == 2) { /* Specified call back called - return failure */ diff --git a/test/punycode_test.c b/test/punycode_test.c index 37f6056903c67..3591f0dc19a09 100644 --- a/test/punycode_test.c +++ b/test/punycode_test.c @@ -188,7 +188,7 @@ static int test_puny_overrun(void) unsigned int bsize = OSSL_NELEM(buf) - 1; if (!TEST_false(ossl_punycode_decode(in, strlen(in), buf, &bsize))) { - if (TEST_mem_eq(buf, bsize * sizeof(*buf), out, sizeof(out))) + if (!TEST_mem_ne(buf, bsize * sizeof(*buf), out, sizeof(out))) TEST_error("CRITICAL: buffer overrun detected!"); return 0; } diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c index 3008048aa43d1..49ffef5061ac6 100644 --- a/test/radix/quic_tests.c +++ b/test/radix/quic_tests.c @@ -455,9 +455,9 @@ DEF_FUNC(check_flood_stats) path_challenge_count = ossl_quic_channel_get_path_challenge_count(ch); path_response_count = ossl_quic_channel_get_path_response_count(ch); - if (TEST_uint64_t_ne(path_challenge_count, 16)) + if (!TEST_uint64_t_eq(path_challenge_count, 16)) goto err; - if (TEST_uint64_t_ne(path_response_count, 1)) + if (!TEST_uint64_t_eq(path_response_count, 1)) goto err; ok = 1; diff --git a/test/secmemtest.c b/test/secmemtest.c index 05b0bbc85796d..b0ac91a38f6a1 100644 --- a/test/secmemtest.c +++ b/test/secmemtest.c @@ -81,7 +81,7 @@ static int test_sec_mem(void) * If init fails, then initialized should be false, if not, this * could cause an infinite loop secure_malloc, but we don't test it */ - if (TEST_false(CRYPTO_secure_malloc_init(16, 16)) && !TEST_false(CRYPTO_secure_malloc_initialized())) { + if (!TEST_true(CRYPTO_secure_malloc_init(16, 16)) && !TEST_false(CRYPTO_secure_malloc_initialized())) { TEST_true(CRYPTO_secure_malloc_done()); goto end; } From 59f0bcd8f408983a59e6b6f9a824bc5b6b3878ee Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 15 Jun 2026 09:56:57 +0200 Subject: [PATCH 020/189] windows_comp.yml: windows-latest image uses VS-2026 now Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Mon Jun 15 08:16:26 2026 (Merged from https://github.com/openssl/openssl/pull/31505) (cherry picked from commit 5f8850204342c6a24b929f65cbc52819543c4a34) --- .github/workflows/windows_comp.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/windows_comp.yml b/.github/workflows/windows_comp.yml index bdc9ebbebee20..a35cd06352550 100644 --- a/.github/workflows/windows_comp.yml +++ b/.github/workflows/windows_comp.yml @@ -42,14 +42,14 @@ jobs: working-directory: _build shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat" perl ..\Configure enable-comp enable-zstd --with-zstd-include=C:\vcpkg\packages\zstd_x64-windows\include --with-zstd-lib=C:\vcpkg\packages\zstd_x64-windows\lib\zstd.lib no-makedepend -DOSSL_WINCTX=openssl VC-WIN64A perl configdata.pm --dump - name: build working-directory: _build shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat" nmake - name: Gather openssl version info working-directory: _build @@ -81,7 +81,7 @@ jobs: working-directory: _build shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat" nmake test VERBOSE_FAILURE=yes TESTS="-test_fuzz* -test_fipsload" HARNESS_JOBS=4 brotli: @@ -106,14 +106,14 @@ jobs: working-directory: _build shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat" perl ..\Configure enable-comp enable-brotli --with-brotli-include=C:\vcpkg\packages\brotli_x64-windows\include --with-brotli-lib=C:\vcpkg\packages\brotli_x64-windows\lib no-makedepend -DOSSL_WINCTX=openssl VC-WIN64A perl configdata.pm --dump - name: build working-directory: _build shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat" nmake - name: Gather openssl version info working-directory: _build @@ -145,5 +145,5 @@ jobs: working-directory: _build shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat" nmake test VERBOSE_FAILURE=yes TESTS="-test_fuzz* -test_fipsload" HARNESS_JOBS=4 From 36e5241f10048eaf3177ddbca24e66c8e693ffa2 Mon Sep 17 00:00:00 2001 From: XZ-X Date: Mon, 22 Jul 2024 03:12:04 -0400 Subject: [PATCH 021/189] apps/lib/apps.c: free retdb before return on OPENSSL_strdup() failure Fixes: c7d5ea2670c2 "Prepare to detect index changes in OCSP responder." Reviewed-by: Paul Dale Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Mon Jun 15 14:29:23 2026 (Merged from https://github.com/openssl/openssl/pull/24981) (cherry picked from commit e4e5c0538e8e758dc3704d4788e1f0dff53aedf5) --- apps/lib/apps.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/lib/apps.c b/apps/lib/apps.c index e5a2b162b4efa..1258f1ecdf1d9 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -1722,8 +1722,14 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) } retdb->dbfname = OPENSSL_strdup(dbfile); - if (retdb->dbfname == NULL) + if (retdb->dbfname == NULL) { + TXT_DB_free(retdb->db); + retdb->db = NULL; + OPENSSL_free(retdb); + retdb = NULL; + ERR_raise_data(ERR_LIB_SYS, errno, "Out of memory while copying filename: %s", dbfile); goto err; + } #ifndef OPENSSL_NO_POSIX_IO retdb->dbst = dbst; From 95be5b01fea4a42df338485d8c3fa9e18a4ff45c Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 7 May 2026 21:43:15 +0200 Subject: [PATCH 022/189] cmp_client_test.c: fix partly too generous total_timeout limit for IR session with polling This backports #31111 Reviewed-by: Norbert Pocs Reviewed-by: Nikola Pajkovsky Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jun 17 07:38:42 2026 (Merged from https://github.com/openssl/openssl/pull/31456) (cherry picked from commit f8f588cc77b70463e34cba698155b60fcc5c21ae) --- test/cmp_client_test.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/cmp_client_test.c b/test/cmp_client_test.c index c2072c1be25c2..2dbe8fc9dacc9 100644 --- a/test/cmp_client_test.c +++ b/test/cmp_client_test.c @@ -239,7 +239,9 @@ static int test_exec_REQ_ses_poll(int req_type, int check_after, return result; } -static int checkAfter = 1; +static const int checkAfter = 1; +static const int pollCount = 3; + static int test_exec_IR_ses_poll_ok(void) { return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, 2, 0, @@ -256,8 +258,8 @@ static int test_exec_IR_ses_poll_no_timeout(void) static int test_exec_IR_ses_poll_total_timeout(void) { - return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter + 1, - 3 /* pollCount */, checkAfter + 6, + return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, + pollCount, (pollCount - 1) * checkAfter, OSSL_CMP_PKISTATUS_trans); } @@ -466,8 +468,8 @@ static int test_exec_GENM_ses_poll_no_timeout(void) static int test_exec_GENM_ses_poll_total_timeout(void) { - return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter + 1, - 3 /* pollCount */, checkAfter + 2, + return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, + pollCount, (pollCount - 1) * checkAfter, OSSL_CMP_PKISTATUS_trans); } From 6cbbf4c167d92551d1d7fb5c7d2c404c5682d2dd Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 30 Apr 2026 20:46:41 +0900 Subject: [PATCH 023/189] Reject delta CRLs as complete CRL candidates get_crl_score() is used when selecting a complete/base CRL. Its delta CRL rejection was chained after the extended CRL and IDP reason handling, so it could be skipped when extended CRL support was disabled, or when an IDP onlySomeReasons branch was taken. As a result, a CRL with a Delta CRL Indicator could be scored as a complete/base CRL candidate. Since a delta CRL contains only changes relative to a base CRL, this could cause a previously revoked certificate to be accepted as valid when only the delta CRL is presented to the verifier. Reject CRLs with base_crl_number unconditionally in get_crl_score() before IDP reason filtering. Delta CRLs are still considered by get_delta_sk() after a complete CRL is selected and check_delta_base() confirms compatibility. Add verify recipe coverage for a delta CRL being rejected as a complete CRL, and for a delta CRL with IssuingDistributionPoint.onlySomeReasons being rejected under -extended_crl. Reported-by: jujerpig (GitHub issue #31040) Fixes #31040 Reviewed-by: Bob Beck Reviewed-by: Tomas Mraz MergeDate: Wed Jun 17 08:53:02 2026 (Merged from https://github.com/openssl/openssl/pull/31044) (cherry picked from commit 5a3723e2543684f86ad54ee8ae65db7556cbccd3) --- crypto/x509/x509_vfy.c | 9 +++-- test/certs/delta-crl-as-complete-ca.pem | 20 +++++++++++ .../delta-crl-as-complete-delta-reasons.pem | 12 +++++++ test/certs/delta-crl-as-complete-delta.pem | 12 +++++++ test/certs/delta-crl-as-complete-leaf.pem | 20 +++++++++++ test/recipes/25-test_verify.t | 34 ++++++++++++++++++- 6 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 test/certs/delta-crl-as-complete-ca.pem create mode 100644 test/certs/delta-crl-as-complete-delta-reasons.pem create mode 100644 test/certs/delta-crl-as-complete-delta.pem create mode 100644 test/certs/delta-crl-as-complete-leaf.pem diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 0994c32ca5336..b3df8c9b71e7e 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1364,6 +1364,12 @@ static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, /* Invalid IDP cannot be processed */ if ((crl->idp_flags & IDP_INVALID) != 0) return 0; + /* + * Reject delta CRLs unconditionally here. They are considered by + * get_delta_sk() after a base CRL is selected. + */ + if (crl->base_crl_number != NULL) + return 0; /* Reason codes or indirect CRLs need extended CRL support */ if ((ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT) == 0) { if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) @@ -1373,9 +1379,6 @@ static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, if ((crl->idp_reasons & ~tmp_reasons) == 0) return 0; } - /* Don't process deltas at this stage */ - else if (crl->base_crl_number != NULL) - return 0; /* If issuer name doesn't match certificate need indirect CRL */ if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl)) != 0) { if ((crl->idp_flags & IDP_INDIRECT) == 0) diff --git a/test/certs/delta-crl-as-complete-ca.pem b/test/certs/delta-crl-as-complete-ca.pem new file mode 100644 index 0000000000000..c7bade031a63e --- /dev/null +++ b/test/certs/delta-crl-as-complete-ca.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgIUP+A4l1Xr6j1/lQ/bRBdNebfmEHMwDQYJKoZIhvcNAQEL +BQAwKDEmMCQGA1UEAwwdRGVsdGEgQ1JMIGFzIENvbXBsZXRlIFRlc3QgQ0EwHhcN +MjYwNDMwMTQ0NjAyWhcNMzYwNDI3MTQ0NjAyWjAoMSYwJAYDVQQDDB1EZWx0YSBD +UkwgYXMgQ29tcGxldGUgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAJ6Wr3/CguoFSKWbeAE2Czjp6qFRdZ3xhhz27NuSdnHpoZE7xgzbt3Z2 +cNt+szZXZIgOyMzSOu0r8q0fKp4VJmR9M5KoMduTHRJpwvT79VhJdZED/1akKhgJ +7WttsvK5kNc+1he7gELY3ssuzfw7MmZv+vMpykjNhSSBKpmUy2t9lX/b1mJ+LK6v +gHQ09ntxdIGniRauzf027ugG72oSydk80YG0EHBlI19eYVhBJEWjLq4afLUYRbfm +0OYHJGq5TE0VTww4xa1IzLFt4NpqveYztYN4ujKd95vbHB6EzCs3R15uJwwm/1px +PXFhwp4MF/W422/XxcadU3+0zHDgEScCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMIh2AkMIUaBjaMHDAOEBAv33XzE +MB8GA1UdIwQYMBaAFMIh2AkMIUaBjaMHDAOEBAv33XzEMA0GCSqGSIb3DQEBCwUA +A4IBAQA6yelNaY6aVomoTwmvNXdfNqlU96HGmEFfKMMFL1CgF5KsBaz4ARCJ+83s +/A0+HufwFYOwUx+dkklatp791leaFjxkFSHmKrE6WVBnOoss7M4a+Hwei13Qrirx +vKFhQde45OFqh8zpl0fru/KdCnbRoM05KVhFqnXR+vyDvghvlIWDFEFdX7KOdVXz +s9v5ECR4kftEalZVq7WNVBS9afVPoQvYj3dcebMH8l8RL5+adV2NRvBKgUKo2kwy +TG6nqWKRr4xqsARLPxYFk1tHbKfIVWy1FrABb5lW8iMA/RZCv6Qzyqbr4nT0WDTa +g3OUp6sSDEhnLYhnW3bsLUdpgRfy +-----END CERTIFICATE----- diff --git a/test/certs/delta-crl-as-complete-delta-reasons.pem b/test/certs/delta-crl-as-complete-delta-reasons.pem new file mode 100644 index 0000000000000..d20bc63f53b55 --- /dev/null +++ b/test/certs/delta-crl-as-complete-delta-reasons.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIBxDCBrQIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1EZWx0YSBDUkwg +YXMgQ29tcGxldGUgVGVzdCBDQRcNMjYwNDMwMTQ0NjAzWhcNMzYwNDI3MTQ0NjAz +WqBRME8wHwYDVR0jBBgwFoAUwiHYCQwhRoGNowcMA4QEC/fdfMQwDQYDVR0bAQH/ +BAMCAQEwEAYDVR0cAQH/BAYwBIMCBWAwCwYDVR0UBAQCAjAAMA0GCSqGSIb3DQEB +CwUAA4IBAQB735x+EogYnkeL3DHwHBbTKXyWMp9UEdR9DVUVElNISNrLTuOy62Nr +N4OEWtDCESltII739hryz85lg0Jo1jBOYbRdGYIacRzm1WUvtk3aLfGt0gwifFtW +4AiiQZUz3jq0F2V9TythzE0nMQbIiXpG3ACc+HQ5/gwpFEvw9ABjXMp5SVU47fT5 +M2jRk12XR6N/MDJB13uh0EH814CD23Gqhvu2lVL3KSGiwImirbQX18egibBmIykR +jqwaH0giFa5ZbrMcOyBksyZJIZgAOpnzn4M5FlQb4s0AjxYSRjqQWV5qrBVfWT6b +Jy+lW3HgXMYyZt6Gqyayfu7N+6JbqhQ+ +-----END X509 CRL----- diff --git a/test/certs/delta-crl-as-complete-delta.pem b/test/certs/delta-crl-as-complete-delta.pem new file mode 100644 index 0000000000000..301a6b009a86e --- /dev/null +++ b/test/certs/delta-crl-as-complete-delta.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIBsjCBmwIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1EZWx0YSBDUkwg +YXMgQ29tcGxldGUgVGVzdCBDQRcNMjYwNDMwMTQ0NjAzWhcNMzYwNDI3MTQ0NjAz +WqA/MD0wHwYDVR0jBBgwFoAUwiHYCQwhRoGNowcMA4QEC/fdfMQwDQYDVR0bAQH/ +BAMCAQEwCwYDVR0UBAQCAiAAMA0GCSqGSIb3DQEBCwUAA4IBAQADs08Ab6TRWijd +dOsW3wBCzWVi/GYlyPhMZjcPTDuM939rpL7yOONM7OIgekP3BYM7g4Dvp6Q4Caul +yZTtJ87dxqP56e11Q7h5eVcBBWxc1dM7FwMffqXXSEApuKdkRqKNAqtXugkgozdM +YBNIuSP+gyLNt4vrxtQS26pBMYJnbCf7ye5dyJFK3G58o97VknNMrYewPrzj6LVG +abS3eJnDaGtiGkQ16pOsKNRTlQYlXBk/9NMq8N8ntsm2ri3LJ/JQHRIHxxSsKl+f +ZgKmOa160pz+xWNq7edIM0RpwGjLVViE7F22y2JH/VJcqXimsl506QykD9COCzH6 +Lnv//55C +-----END X509 CRL----- diff --git a/test/certs/delta-crl-as-complete-leaf.pem b/test/certs/delta-crl-as-complete-leaf.pem new file mode 100644 index 0000000000000..c8ffebdb646b5 --- /dev/null +++ b/test/certs/delta-crl-as-complete-leaf.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQDCCAiigAwIBAgIUXolrPqGDnGH9gUx2N5WFjfUkXHgwDQYJKoZIhvcNAQEL +BQAwKDEmMCQGA1UEAwwdRGVsdGEgQ1JMIGFzIENvbXBsZXRlIFRlc3QgQ0EwHhcN +MjYwNDMwMTQ0NjAzWhcNMzYwNDI3MTQ0NjAzWjAqMSgwJgYDVQQDDB9EZWx0YSBD +UkwgYXMgQ29tcGxldGUgVGVzdCBMZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA43iL7Otyb0SaPVDmOVBs39LnH9vlO2sV+ZPqV4o1a/JhCOzokMxg +NuPqCamMEufKctaKE8q/LKKEpu3QAG7H1vlsu2qfQLojFuHNKDnHM7RbsRNp9azE +DWpBWs0mXL96LUJzseioIIqFdSH9HkcTyrKXvr8iqaOUC96Vu9F03Ws59FmaTwK6 +JmKThfrIY2edSRyEO6tmVTh0XLW0PyNbSM/2eOKmh92RCbhKDjgCeNhPuJ0WRDAX +zNF+cgRO48epsl6ec03DdBSCFcwc5qL+TkzXjXIQbXhIsvl/OKNG0BUXDeYqH7ln +wEO6d556CF6wJlCd0DqzSzPsoVIo96asKwIDAQABo2AwXjAMBgNVHRMBAf8EAjAA +MA4GA1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQUFPI2A7WhMsPK15SsH1W+CiEKqA0w +HwYDVR0jBBgwFoAUwiHYCQwhRoGNowcMA4QEC/fdfMQwDQYJKoZIhvcNAQELBQAD +ggEBAGX7FpwNoq62mhlJbksgAJcaw5ci2m1CGFgNfh+f6pdA0mG3ywyM7eEZcr6h +GFslaDsG8m2O0l737Xs7mBpyq0ruxjpvk62VdgwTUkeZzz8gnuBIWg/+zrWyYCI7 +uDX4wKVMma9MF52YUHhNTdxvV0EE4wuUcYMAlWrCCzxkf4eNxyDJGBXli04xSpSj +cG9SsDRyjQKc9lFFqrQ9P/DVL4CDUSovE/2DWdZmS3RmsHjhNdGjpWtpoEsxBHdQ +5lyeGDp0fBf4RNWRsdr8RUsSiDFUproRibZ9/3uzH5yAfivZmWlVRUX/eyyjCrZD +VuW2H/npgPe+QSkwlUXYsZ1vqiM= +-----END CERTIFICATE----- diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t index ab8cdff23a212..f24ef21180add 100644 --- a/test/recipes/25-test_verify.t +++ b/test/recipes/25-test_verify.t @@ -30,7 +30,7 @@ sub verify { run(app([@args])); } -plan tests => 204; +plan tests => 206; # Canonical success ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), @@ -606,6 +606,38 @@ run(app(["openssl", "verify", ok(grep(/CRL is not yet valid/, do { open my $fh, '<', $cve_28388_stderr; <$fh> }), "CVE-2026-28388"); +# Delta CRLs must not be accepted as complete CRLs +my $delta_crl_as_complete_stderr = "delta-crl-as-complete.err"; +ok(!run(app(["openssl", "verify", "-auth_level", "1", + "-CAfile", + srctop_file(@certspath, "delta-crl-as-complete-ca.pem"), + "-no_check_time", "-crl_check", + "-CRLfile", + srctop_file(@certspath, "delta-crl-as-complete-delta.pem"), + srctop_file(@certspath, "delta-crl-as-complete-leaf.pem")], + stderr => $delta_crl_as_complete_stderr)) + && grep(/unable to get certificate CRL/, + do { open my $fh, '<', $delta_crl_as_complete_stderr; <$fh> }), + "Delta CRL is not accepted as complete CRL"); + +my $delta_crl_as_complete_reasons_stderr = + "delta-crl-as-complete-reasons.err"; +ok(!run(app(["openssl", "verify", "-auth_level", "1", + "-CAfile", + srctop_file(@certspath, "delta-crl-as-complete-ca.pem"), + "-no_check_time", "-crl_check", "-extended_crl", + "-CRLfile", + srctop_file(@certspath, + "delta-crl-as-complete-delta-reasons.pem"), + srctop_file(@certspath, "delta-crl-as-complete-leaf.pem")], + stderr => $delta_crl_as_complete_reasons_stderr)) + && grep(/unable to get certificate CRL/, + do { + open my $fh, '<', $delta_crl_as_complete_reasons_stderr; + <$fh> + }), + "Delta CRL with onlySomeReasons is not accepted as complete CRL"); + # CAstore option my $rootcertname = "root-cert"; my $rootcert = srctop_file(@certspath, "${rootcertname}.pem"); From 694ca5de8e4c5dbd1097c05432ec7ebe1ecd55dc Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Fri, 12 Jun 2026 00:17:10 +0900 Subject: [PATCH 024/189] Fix s_client Sieve STARTTLS response parsing Reviewed-by: Matt Caswell Reviewed-by: Nikola Pajkovsky MergeDate: Wed Jun 17 16:22:20 2026 (Merged from https://github.com/openssl/openssl/pull/31468) (cherry picked from commit 6ecdedbc65c9f2eca90a8ea7dc97e38372c48fe4) --- apps/s_client.c | 6 +- test/recipes/20-test_app_s_client.t | 110 ++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 test/recipes/20-test_app_s_client.t diff --git a/apps/s_client.c b/apps/s_client.c index 9b88d6dfbc86e..c83976c7516be 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -2846,11 +2846,9 @@ int s_client_main(int argc, char **argv) } /* * According to RFC 5804 § 2.2, response codes are case- - * insensitive, make it uppercase but preserve the response. + * insensitive. */ - strncpy(sbuf, mbuf, 2); - make_uppercase(sbuf); - if (!HAS_PREFIX(sbuf, "OK")) { + if (OPENSSL_strncasecmp(mbuf, "OK", 2) != 0) { BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf); goto shut; } diff --git a/test/recipes/20-test_app_s_client.t b/test/recipes/20-test_app_s_client.t new file mode 100644 index 0000000000000..162fb710dac2b --- /dev/null +++ b/test/recipes/20-test_app_s_client.t @@ -0,0 +1,110 @@ +#! /usr/bin/env perl +# Copyright 2026 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 strict; +use warnings; + +use IO::Socket::INET; +use OpenSSL::Test qw/:DEFAULT result_file with/; +use OpenSSL::Test::Utils; + +setup("test_app_s_client"); + +plan skip_all => "test_app_s_client needs sock enabled" + if disabled("sock"); +plan skip_all => "test_app_s_client needs IPv4" + unless have_IPv4(); +plan skip_all => "test_app_s_client needs fork" + if $^O =~ /^(VMS|MSWin32|msys)$/; + +plan tests => 5; + +my $timeout = 30; +local $SIG{ALRM} = sub { BAIL_OUT("s_client Sieve STARTTLS test timed out") }; +alarm($timeout); + +my $listener = IO::Socket::INET->new( + LocalAddr => "127.0.0.1", + LocalPort => 0, + Listen => 1, + Proto => "tcp", + ReuseAddr => 1, +) or BAIL_OUT("failed to create local Sieve listener: $!"); + +my $port = $listener->sockport(); +my $command_file = result_file("sieve-starttls-command.txt"); +my $stdout_file = result_file("s_client-stdout.txt"); +my $stderr_file = result_file("s_client-stderr.txt"); +my $server_pid = fork(); + +BAIL_OUT("failed to fork Sieve listener: $!") unless defined $server_pid; + +if ($server_pid == 0) { + eval { + local $SIG{ALRM} = sub { die "Sieve listener timed out\n" }; + alarm($timeout); + + my $server = $listener->accept() + or die "failed to accept s_client connection: $!"; + + $server->autoflush(1); + print $server "\"STARTTLS\"\r\nOK\r\n"; + + my $command = <$server>; + open my $fh, ">", $command_file + or die "failed to open command capture file: $!"; + print $fh $command if defined $command; + close $fh; + + # This stub only needs to drive s_client through the plaintext + # Sieve STARTTLS response parser. After sending an exact two-byte + # lowercase OK response, it closes instead of performing TLS. The + # resulting handshake failure is expected, but sanitizer failures + # before that are not. + print $server "ok"; + close $server; + alarm(0); + }; + warn $@ if $@; + exit($@ ? 1 : 0); +} + +close $listener; + +with({ exit_checker => sub { return shift() < 128; } }, + sub { + ok(run(app(["openssl", "s_client", "-brief", "-starttls", "sieve", + "-connect", "127.0.0.1:$port"], + stdin => undef, stdout => $stdout_file, + stderr => $stderr_file)), + "s_client exits without signal"); + }); + +waitpid($server_pid, 0); +is($?, 0, "Sieve listener completed"); + +my $command = ""; +if (open my $fh, "<", $command_file) { + local $/; + $command = <$fh>; + close $fh; +} +is($command, "STARTTLS\r\n", "s_client sends Sieve STARTTLS command"); + +my $stderr = ""; +if (open my $fh, "<", $stderr_file) { + local $/; + $stderr = <$fh>; + close $fh; +} +unlike($stderr, qr/STARTTLS not supported/, + "s_client accepts case-insensitive two-byte OK response"); +unlike($stderr, qr/AddressSanitizer/, + "s_client does not trigger AddressSanitizer"); + +alarm(0); From b0576dc5d422b5311dc2d94d4b9481812f40ba67 Mon Sep 17 00:00:00 2001 From: Abel Tom Date: Wed, 17 Jun 2026 09:56:46 +0200 Subject: [PATCH 025/189] Enforce RFC 8446 ticket lifetime limit for TLS 1.3 client Add client-side validation to check if session ticket lifetime hints exceeds 7 days in TLS1.3 connections and caps it to the maximum value of 7 days(604800 seconds). Modified `CHANGES.md` with the description of updated change. Resolves: #30808 Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz MergeDate: Thu Jun 18 12:25:33 2026 (Merged from https://github.com/openssl/openssl/pull/31174) (cherry picked from commit 5a85e4152d817749400b0e30ebbbcce738fbfbb5) --- CHANGES.md | 12 +++++++++++- ssl/statem/statem_clnt.c | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index cda2afee32127..1324b924e607b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,7 +30,17 @@ OpenSSL 3.5 ### Changes between 3.5.7 and 3.5.8 [xx XXX xxxx] - * none yet + * Add client-side validation for TLS 1.3 session ticket lifetimes. + + In accordance with [RFC 8446 Section 4.6.1](https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.1), + TLS 1.3 clients must not cache session tickets + for longer than 7 days (604800 seconds). + When processing a new session ticket message with a + `ticket_lifetime_hint` value greater than 7 days, + the client now caps the lifetime to the + maximum permitted value of 7 days (604800 seconds). + + *Abel Thomas* ### Changes between 3.5.6 and 3.5.7 [9 Jun 2026] diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index b317b9392435a..0279a62abd2ef 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2814,6 +2814,14 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL_CONNECTION *s, if (SSL_CONNECTION_IS_TLS13(s)) { PACKET extpkt; + /* + * Fulfilling RFC8446:4.6.1 requirement: Clients MUST NOT cache + * tickets for longer than 7 days. + */ + if (ticket_lifetime_hint > 604800) { + ticket_lifetime_hint = 604800; + } + if (!PACKET_as_length_prefixed_2(pkt, &extpkt) || PACKET_remaining(pkt) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH); From 316bb2015ed4a704f23e99b4db4485b6d0247909 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 10 Jun 2026 09:37:20 +0200 Subject: [PATCH 026/189] Fix failure checking on thread_local storage assignment in rand_lib The new malloc failure test caught an asan error in this code: Direct leak of 40 byte(s) in 1 object(s) allocated from: 2025-08-07T03:22:20.3655117Z #0 0x7fb88d8fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69 2025-08-07T03:22:20.3655796Z #1 0x5584f0e4670a in CRYPTO_malloc crypto/mem.c:211 2025-08-07T03:22:20.3656291Z #2 0x5584f0e4679d in CRYPTO_zalloc crypto/mem.c:231 2025-08-07T03:22:20.3657040Z #3 0x5584f11c4c10 in EVP_RAND_CTX_new crypto/evp/evp_rand.c:353 2025-08-07T03:22:20.3657656Z #4 0x5584f0e93b27 in rand_new_drbg crypto/rand/rand_lib.c:666 2025-08-07T03:22:20.3658289Z #5 0x5584f0e949d0 in rand_get0_public crypto/rand/rand_lib.c:843 2025-08-07T03:22:20.3658914Z #6 0x5584f0e9305b in RAND_bytes_ex crypto/rand/rand_lib.c:490 2025-08-07T03:22:20.3659486Z #7 0x5584f0b2405f in SSL_CTX_new_ex ssl/ssl_lib.c:4191 2025-08-07T03:22:20.3660183Z #8 0x5584f0ae313c in create_ssl_ctx_pair test/helpers/ssltestlib.c:958 2025-08-07T03:22:20.3660871Z #9 0x5584f0adeaf6 in do_handshake test/handshake-memfail.c:56 2025-08-07T03:22:20.3661539Z #10 0x5584f0adee50 in test_alloc_failures test/handshake-memfail.c:125 2025-08-07T03:22:20.3662161Z #11 0x5584f0cd9da8 in run_tests test/testutil/driver.c:342 2025-08-07T03:22:20.3662664Z #12 0x5584f0cda9e5 in main test/testutil/main.c:31 2025-08-07T03:22:20.3663450Z #13 0x7fb88d42a1c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 282c2c16e7b6600b0b22ea0c99010d2795752b5f) 2025-08-07T03:22:20.3664630Z #14 0x7fb88d42a28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 282c2c16e7b6600b0b22ea0c99010d2795752b5f) 2025-08-07T03:22:20.3666608Z #15 0x5584f0ade864 in _start (/home/runner/work/openssl/openssl/test/handshake-memfail+0x22a864) (BuildId: 19659a44d8bed2c082918d25425f77e3a98df534) It occurs because when rand_get0_public/rand_get0_private sets an EVP_RAND_CTX object in its thread local storage, it neglects to check the return code of the operation, which may fail when the associated sparse array is expanded. fix it by checking the return code and failing the get0_[public|private] operation so the failure is graceful. Fixes: https://github.com/openssl/openssl/issues/31375 Signed-off-by: Nikola Pajkovsky (cherry picked from commit 7f780be21608a2982cdf1c567e5afeb724b1e9a1) Reviewed-by: Norbert Pocs Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz MergeDate: Thu Jun 18 12:38:33 2026 (Merged from https://github.com/openssl/openssl/pull/31442) --- crypto/rand/rand_lib.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index f03bb2967c436..84455e229c23f 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -864,7 +864,10 @@ static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) return NULL; rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL, SECONDARY_RESEED_TIME_INTERVAL); - CRYPTO_THREAD_set_local(&dgbl->public, rand); + if (!CRYPTO_THREAD_set_local(&dgbl->public, rand)) { + EVP_RAND_CTX_free(rand); + rand = NULL; + } } return rand; } @@ -903,7 +906,10 @@ static EVP_RAND_CTX *rand_get0_private(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) return NULL; rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL, SECONDARY_RESEED_TIME_INTERVAL); - CRYPTO_THREAD_set_local(&dgbl->private, rand); + if (!CRYPTO_THREAD_set_local(&dgbl->private, rand)) { + EVP_RAND_CTX_free(rand); + rand = NULL; + } } return rand; } From bee8bc90050fcd3e0d2029a069a12e0d69a8ad5f Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 17 Jun 2026 11:18:12 +0100 Subject: [PATCH 027/189] Fix intermittent failure in check_pc_flood radix test check_flood_stats read the path challenge/response counters immediately after the client's write returned, but the flood is delivered over a real socket and processed by the connection's assist thread asynchronously. Spin until the counters reach their expected values, the same way check_rejected already does, instead of failing on the first observation. Observed failure: https://github.com/openssl/openssl/actions/runs/27669771673/job/81831310551?pr=31538 Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Nikola Pajkovsky Reviewed-by: Milan Broz MergeDate: Thu Jun 18 13:07:27 2026 (Merged from https://github.com/openssl/openssl/pull/31561) (cherry picked from commit 75f59968b838dabc3ff441ae2841c10e0df64b2b) --- test/radix/quic_tests.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c index 49ffef5061ac6..50ce9e1b4229e 100644 --- a/test/radix/quic_tests.c +++ b/test/radix/quic_tests.c @@ -455,6 +455,14 @@ DEF_FUNC(check_flood_stats) path_challenge_count = ossl_quic_channel_get_path_challenge_count(ch); path_response_count = ossl_quic_channel_get_path_response_count(ch); + /* + * The flood is delivered over a real socket and processed by the + * connection's assist thread asynchronously, so give it a chance to + * catch up rather than failing on the first observation. + */ + if (path_challenge_count < 16 || path_response_count < 1) + F_SPIN_AGAIN(); + if (!TEST_uint64_t_eq(path_challenge_count, 16)) goto err; if (!TEST_uint64_t_eq(path_response_count, 1)) From c1a0b7fd0c6d7bb481608766845f66c0bcb3e3c3 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 16 Jun 2026 16:47:49 +0200 Subject: [PATCH 028/189] pkcs11-provider: enable and update [3.5] The pkcs11-provider was disabled due to fixed issues in PQC sigalgs. This re-enables it and update provider to the latest version to also fix the TLS test has been failing due to changes in kryoptic introduced in https://github.com/latchset/kryoptic/pull/436 . This was a bug in pkcs11-provider that was fixed in https://github.com/openssl-projects/pkcs11-provider/pull/722 . Reviewed-by: Matt Caswell Reviewed-by: Nikola Pajkovsky MergeDate: Thu Jun 18 13:20:31 2026 (Merged from https://github.com/openssl/openssl/pull/31556) --- .github/workflows/ci.yml | 34 +++++++++++++++++++++++++++++++--- pkcs11-provider | 2 +- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed42020800d28..482235a1d974d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -714,9 +714,37 @@ jobs: ./util/opensslwrap.sh version -c - name: test external oqs-provider run: make test TESTS="test_external_oqsprovider" - # Disabled temporarily: https://github.com/latchset/pkcs11-provider/pull/525#discussion_r1982805969 - # - name: test external pkcs11-provider - # run: make test TESTS="test_external_pkcs11_provider" VERBOSE=1 + + external-tests-pkcs11-provider: + runs-on: ubuntu-latest + container: fedora:latest + steps: + - name: package installs + run: | + dnf install -y perl-FindBin perl-IPC-Cmd perl-File-Compare perl-File-Copy perl-Test-Simple perl-Test-Harness python3 make g++ perl git meson opensc expect kryoptic xxd + - uses: actions/checkout@v6 + with: + persist-credentials: false + - name: checkout fuzz/corpora and pkcs11-provider submodule + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + git submodule update --init --depth 1 fuzz/corpora + git submodule update --init --depth 1 pkcs11-provider + - name: config + run: ./config --strict-warnings --banner=Configured --debug enable-external-tests no-fips && perl configdata.pm --dump + - name: make + run: make -s -j4 + # Run all tests except external tests to make sure they work fine on Fedora because + # this is the only job running on Fedora, only then execute pkcs11-provider external + # test. + - name: test (except external tests) + run: make test TESTS="-test_external_*" + - name: test external pkcs11-provider + run: make test TESTS="test_external_pkcs11_provider" VERBOSE=1 + - name: get cpu info + run: | + cat /proc/cpuinfo + ./util/opensslwrap.sh version -c external-tests-pyca: runs-on: ubuntu-latest diff --git a/pkcs11-provider b/pkcs11-provider index 663dea335c80b..64fc325ac0f91 160000 --- a/pkcs11-provider +++ b/pkcs11-provider @@ -1 +1 @@ -Subproject commit 663dea335c80bec7fd96d544ff875af08d6461a9 +Subproject commit 64fc325ac0f91d03d76b3546df2998d3a38c525b From 03e7ed910075a4fdb27dc1db573bfe90d4f8d251 Mon Sep 17 00:00:00 2001 From: Loganaden Velvindron Date: Wed, 10 Jun 2026 17:18:19 +0400 Subject: [PATCH 029/189] ssl/quic/quic_ackm.c: fix use after free for apkt in ackm_on_pkts_acked() Store in_flight flag in a local variable for later use, as apkt->on_acked() may free apkt. Fixes: 427a02ad0a71 "QUIC ACKM: Don't record non-inflight packets in CC" Signed-off-by: Loganaden Velvindron Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Sun Jun 21 13:55:08 2026 (Merged from https://github.com/openssl/openssl/pull/31447) (cherry picked from commit 4d9e2a5797ec74a20426a6185df01d10a770ccc5) --- ssl/quic/quic_ackm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ssl/quic/quic_ackm.c b/ssl/quic/quic_ackm.c index 58318a123a858..24b72e42d902b 100644 --- a/ssl/quic/quic_ackm.c +++ b/ssl/quic/quic_ackm.c @@ -1003,6 +1003,7 @@ static void ackm_on_pkts_acked(OSSL_ACKM *ackm, const OSSL_ACKM_TX_PKT *apkt) const OSSL_ACKM_TX_PKT *anext; QUIC_PN last_pn_acked = 0; OSSL_CC_ACK_INFO ainfo = { 0 }; + unsigned int is_inflight; for (; apkt != NULL; apkt = anext) { if (apkt->is_inflight) { @@ -1027,10 +1028,11 @@ static void ackm_on_pkts_acked(OSSL_ACKM *ackm, const OSSL_ACKM_TX_PKT *apkt) ainfo.tx_time = apkt->time; ainfo.tx_size = apkt->num_bytes; + is_inflight = apkt->is_inflight; anext = apkt->anext; apkt->on_acked(apkt->cb_arg); /* may free apkt */ - if (apkt->is_inflight) + if (is_inflight) ackm->cc_method->on_data_acked(ackm->cc_data, &ainfo); } } From b4d5a321427d16c23fd62eee356c23ea98289238 Mon Sep 17 00:00:00 2001 From: Carlo Deutschmann Date: Thu, 18 Jun 2026 19:36:47 +0200 Subject: [PATCH 030/189] Fix spelling mistakes in documentation Correct a number of typos found in the man pages: * doc/man3/SSL_CTX_set1_curves.pod: attenion -> attention * doc/man3/CMS_EncryptedData_decrypt.pod: decypted -> decrypted * doc/man3/X509_get_default_cert_file.pod: delimeter -> delimiter * doc/man3/SSL_CTX_set_msg_callback.pod: diagostic -> diagnostic * doc/man7/openssl-core_dispatch.h.pod: dipatch -> dispatch * doc/man3/BIO_s_datagram.pod: hecause -> because * doc/man3/ASN1_aux_cb.pod: auxiliarly -> auxiliary CLA: trivial Fixes: 3d9d1ce52904 "Add documentation for newly added ASN1 functions" Fixes: 408622b73a18 "BIO_s_dgram: add documentation and hazard warnings" Fixes: e2f6960fc5fe "CMS: Export CMS_EnvelopedData and add CMS_EnvelopedData_decrypt()" Fixes: 85977e013f32 "Fix group tuple handling in DEFAULT expansion" Fixes: bfcf1356f9fd "Update the msg_callback documentation" Fixes: 606e0426a148 "Add support for loading root CAs from Windows crypto API" Fixes: 329b2a2cde48 "DOCS: add openssl-core_numbers.h(7)" Reviewed-by: Paul Dale Reviewed-by: Kurt Roeckx Reviewed-by: Tim Hudson Reviewed-by: Eugene Syromiatnikov MergeDate: Sun Jun 21 22:50:14 2026 (Merged from https://github.com/openssl/openssl/pull/31596) (cherry picked from commit 7a5476687ef1b1efd14fabb05f0a05ba494d1c1e) --- doc/man3/ASN1_aux_cb.pod | 2 +- doc/man3/BIO_s_datagram.pod | 2 +- doc/man3/CMS_EncryptedData_decrypt.pod | 2 +- doc/man3/SSL_CTX_set1_curves.pod | 2 +- doc/man3/SSL_CTX_set_msg_callback.pod | 2 +- doc/man3/X509_get_default_cert_file.pod | 2 +- doc/man7/openssl-core_dispatch.h.pod | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/man3/ASN1_aux_cb.pod b/doc/man3/ASN1_aux_cb.pod index 9963ea1350252..68b230ca1afe9 100644 --- a/doc/man3/ASN1_aux_cb.pod +++ b/doc/man3/ASN1_aux_cb.pod @@ -59,7 +59,7 @@ Arbitrary application data =item I -Flags which indicate the auxiliarly functionality supported. +Flags which indicate the auxiliary functionality supported. The B flag indicates that objects support reference counting. diff --git a/doc/man3/BIO_s_datagram.pod b/doc/man3/BIO_s_datagram.pod index 87d6fb34e7a29..ed2e6881ee17c 100644 --- a/doc/man3/BIO_s_datagram.pod +++ b/doc/man3/BIO_s_datagram.pod @@ -65,7 +65,7 @@ the underlying socket is configured and how it is to be used; see below. =item -Use of BIO_s_datagram() with an unconnected network socket is hazardous hecause +Use of BIO_s_datagram() with an unconnected network socket is hazardous because any successful call to BIO_read() results in the peer address used for any subsequent call to BIO_write() being set to the source address of the datagram received by that call to BIO_read(). Thus, unless the caller calls diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod index 80bbdcc95f35b..f7375f2c58b1b 100644 --- a/doc/man3/CMS_EncryptedData_decrypt.pod +++ b/doc/man3/CMS_EncryptedData_decrypt.pod @@ -46,7 +46,7 @@ are used when retrieving algorithms from providers. CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise returns 1. CMS_EnvelopedData_decrypt() returns NULL if an error occurred, -otherwise a BIO containing the decypted content. +otherwise a BIO containing the decrypted content. =head1 SEE ALSO diff --git a/doc/man3/SSL_CTX_set1_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod index 6fedad01b4d0a..3fc0b8f3309b0 100755 --- a/doc/man3/SSL_CTX_set1_curves.pod +++ b/doc/man3/SSL_CTX_set1_curves.pod @@ -113,7 +113,7 @@ levels, and can specify which predicted key shares should be sent by a client. Group tuples are used by OpenSSL TLS servers to decide whether to request a stronger keyshare than those predicted by sending a Hello Retry Request (B) even if some of the predicted groups are supported. -OpenSSL clients ignore tuple boundaries, and pay attenion only to the overall +OpenSSL clients ignore tuple boundaries, and pay attention only to the overall order of I elements and which groups are selected as predicted keyshares as described below. diff --git a/doc/man3/SSL_CTX_set_msg_callback.pod b/doc/man3/SSL_CTX_set_msg_callback.pod index f046c77b535b9..c1748bbd8a894 100644 --- a/doc/man3/SSL_CTX_set_msg_callback.pod +++ b/doc/man3/SSL_CTX_set_msg_callback.pod @@ -92,7 +92,7 @@ The SSL_trace() function can be used as a pre-written callback in a call to SSL_CTX_set_msg_callback() or SSL_set_msg_callback(). It requires a BIO to be set as the callback argument via SSL_CTX_set_msg_callback_arg() or SSL_set_msg_callback_arg(). Setting this callback will cause human readable -diagostic tracing information about an SSL/TLS/QUIC connection to be written to +diagnostic tracing information about an SSL/TLS/QUIC connection to be written to the BIO. =head1 NOTES diff --git a/doc/man3/X509_get_default_cert_file.pod b/doc/man3/X509_get_default_cert_file.pod index 1e65b227006d4..a604cf5571774 100644 --- a/doc/man3/X509_get_default_cert_file.pod +++ b/doc/man3/X509_get_default_cert_file.pod @@ -24,7 +24,7 @@ the default path when it is asked to load trusted CA certificates from a file and no other path is specified. If the file exists, CA certificates are loaded from the file. -The X509_get_default_cert_dir() function returns a default delimeter-separated +The X509_get_default_cert_dir() function returns a default delimiter-separated list of paths to a directories containing trusted CA certificates named in the hashed format. OpenSSL will use this as the default list of paths when it is asked to load trusted CA certificates from a directory and no other path is diff --git a/doc/man7/openssl-core_dispatch.h.pod b/doc/man7/openssl-core_dispatch.h.pod index a19e1331fa68b..7f99fe2a811bd 100644 --- a/doc/man7/openssl-core_dispatch.h.pod +++ b/doc/man7/openssl-core_dispatch.h.pod @@ -24,7 +24,7 @@ are named as follows: These macros have the form C>. -=item dipatch numbers +=item dispatch numbers These macros have the form C_I>, where C> is the same as in the macro for the operation this From ddc36ff2a1b9628515a103f4439b2a7a571ef315 Mon Sep 17 00:00:00 2001 From: Abel Tom Date: Thu, 18 Jun 2026 13:58:35 +0200 Subject: [PATCH 031/189] tls_common.c: prevent max_early_data overflow in rlayer_early_data_count_ok() Make the local max_early_data variable uint64_t so an overflow cannot occur if the max_early_data field in the record layer struct has the maximum value: UNT32_MAX (0xFFFFFFFF). Resolves: https://github.com/openssl/openssl/issues/31533 Reviewed-by: Eugene Syromiatnikov Reviewed-by: Frederik Wedel-Heinen Reviewed-by: Tim Hudson MergeDate: Sun Jun 21 23:50:02 2026 (Merged from https://github.com/openssl/openssl/pull/31538) (cherry picked from commit d41a9225196be4863e7b72a152769a93f9faf917) --- ssl/record/methods/tls_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c index 9f957b7cc656f..da3c6d850fbf8 100644 --- a/ssl/record/methods/tls_common.c +++ b/ssl/record/methods/tls_common.c @@ -497,7 +497,7 @@ static int tls_record_app_data_waiting(OSSL_RECORD_LAYER *rl) static int rlayer_early_data_count_ok(OSSL_RECORD_LAYER *rl, size_t length, size_t overhead, int send) { - uint32_t max_early_data = rl->max_early_data; + uint64_t max_early_data = rl->max_early_data; if (max_early_data == 0) { RLAYERfatal(rl, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, From 9ec9fa47403bcf2e32429350fe62f0b402a02149 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 18 Jun 2026 15:58:40 +0200 Subject: [PATCH 032/189] prov-compat-label.yml: Do not use enable-ssl3 It is removed on the master branch. Reviewed-by: Dmitry Belyavskiy Reviewed-by: Eugene Syromiatnikov MergeDate: Mon Jun 22 06:58:03 2026 (Merged from https://github.com/openssl/openssl/pull/31586) (cherry picked from commit 87d08d1e7df96f11555debf7595a62bd6987ed1f) --- .github/workflows/prov-compat-label.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prov-compat-label.yml b/.github/workflows/prov-compat-label.yml index 46c6eaf3b0bbf..ec6adc5f8e6c7 100644 --- a/.github/workflows/prov-compat-label.yml +++ b/.github/workflows/prov-compat-label.yml @@ -16,7 +16,7 @@ permissions: contents: read env: - opts: enable-rc5 enable-md2 enable-ssl3 enable-weak-ssl-ciphers enable-zlib + opts: enable-rc5 enable-md2 enable-weak-ssl-ciphers enable-zlib jobs: fips-releases: From 26108fb4a9eccfdcc4ce05906a37c0eb7b7b9673 Mon Sep 17 00:00:00 2001 From: Abel Tom Date: Wed, 17 Jun 2026 12:11:29 +0200 Subject: [PATCH 033/189] crypto/pkcs7/pk7_lib.c: fix return value in PKCS7_set_digest() Return 0 when the passed object to PKCS7_set_digest() is not of type PKCS7 digest. Fixes: c5a55463892d "Add support for digested data PKCS#7 type." Resolves: https://github.com/openssl/openssl/issues/31551 Reviewed-by: Matt Caswell Reviewed-by: Norbert Pocs Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tim Hudson MergeDate: Mon Jun 22 08:17:32 2026 (Merged from https://github.com/openssl/openssl/pull/31559) (cherry picked from commit 206ec55fec48d37960e01df1e12f0ed71a200c35) --- crypto/pkcs7/pk7_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index 6cd0c3f025c5c..edf1f6cb698dc 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -537,7 +537,7 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) } ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); - return 1; + return 0; } STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) From fa4a060e493ac7ea98c42560f35b947728c05267 Mon Sep 17 00:00:00 2001 From: Jon Ericson Date: Thu, 18 Jun 2026 12:14:57 -0700 Subject: [PATCH 034/189] CONTRIBUTING.md: add the AI declaration policy References: https://github.com/openssl/general-policies/pull/85 Reviewed-by: Milan Broz Reviewed-by: Bob Beck Reviewed-by: Tim Hudson Reviewed-by: Eugene Syromiatnikov MergeDate: Mon Jun 22 10:36:52 2026 (Merged from https://github.com/openssl/openssl/pull/31604) (cherry picked from commit f23329efa0fe3785131c715849f2577bc27b128d) --- CONTRIBUTING.md | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 06dfbaeff1fec..46b35fafa91eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,7 +70,37 @@ guidelines: git push -f [ []] ``` - 2. All source files should start with the following text (with + 2. Similarly, if a non-trivial portion of a contribution was created + by an AI, you must declare which agent and model were used. This + is done by adding `Assisted-by: {agent}:{model}` below the commit + message: + + ``` + One-line summary of change with AI-created portions + + Assisted-by: Claude:claude-sonnet-4-6 + ``` + + Multiple Assisted-by trailers can be included if multiple tools were used: + + ``` + Assisted-by: Claude:claude-sonnet-4-6 + Assisted-by: ChatGPT:gpt-4o + Assisted-by: GitHub Copilot:gpt-4.1 + ``` + + You will need to have signed a v1.1 or later CLA in order to + include AI-generated content in your contribution. CLAs signed + after June 2026 will have the requisite clauses. + + Consult the [OpenSSL AI Code and Documentation Contribution + Policy] if an AI model assisted with the creation of your + contribution. + + [OpenSSL AI Code and Documentation Contribution + Policy]: + + 3. All source files should start with the following text (with appropriate comment characters at the start of each line and the year(s) updated): @@ -83,11 +113,11 @@ guidelines: https://www.openssl.org/source/license.html ``` - 3. Patches should be as current as possible; expect to have to rebase + 4. Patches should be as current as possible; expect to have to rebase often. We do not accept merge commits, you will have to remove them (usually by rebasing) before it will be acceptable. - 4. Code provided should follow our [coding style] and [documentation policy] + 5. Code provided should follow our [coding style] and [documentation policy] and compile without warnings. There is a [Perl tool](util/check-format.pl) that helps finding code formatting mistakes and other coding style nits. @@ -100,16 +130,16 @@ guidelines: [coding style]: https://openssl-library.org/policies/technical/coding-style/ [documentation policy]: https://openssl-library.org/policies/technical/documentation-policy/ - 5. When at all possible, code contributions should include tests. These can + 6. When at all possible, code contributions should include tests. These can either be added to an existing test, or completely new. Please see [test/README.md](test/README.md) for information on the test framework. - 6. New features or changed functionality must include + 7. New features or changed functionality must include documentation. Please look at the `.pod` files in `doc/man[1357]` for examples of our style. Run `make doc-nits` to make sure that your documentation changes are clean. - 7. For user visible changes (API changes, behaviour changes, ...), + 8. For user visible changes (API changes, behaviour changes, ...), consider adding a note in [CHANGES.md](CHANGES.md). This could be a summarising description of the change, and could explain the grander details. @@ -120,5 +150,5 @@ guidelines: with a specific release without having to sift through the higher noise ratio in git-log. - 8. Guidelines on how to integrate error output of new crypto library modules + 9. Guidelines on how to integrate error output of new crypto library modules can be found in [crypto/err/README.md](crypto/err/README.md). From 2a854601a1d5afbd6c191ec47b78a6e9fe319579 Mon Sep 17 00:00:00 2001 From: Bob Beck Date: Tue, 16 Jun 2026 12:49:52 -0600 Subject: [PATCH 035/189] doc/man3/ASN1_aux_cb.pod: correct return code documentation for the callbacks Attempt to make the documentation match the code. Not attempting to change what the code does at this point, it's all very random, and since it's been there, it is effectively established public API now. Reviewed-by: Nikola Pajkovsky Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson Reviewed-by: Eugene Syromiatnikov MergeDate: Mon Jun 22 11:56:58 2026 (Merged from https://github.com/openssl/openssl/pull/31549) (cherry picked from commit bf41baa2bf3215625d44f7c0dc438ab1b2e3a3d0) --- doc/man3/ASN1_aux_cb.pod | 58 +++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/doc/man3/ASN1_aux_cb.pod b/doc/man3/ASN1_aux_cb.pod index 68b230ca1afe9..9a38ab168ff31 100644 --- a/doc/man3/ASN1_aux_cb.pod +++ b/doc/man3/ASN1_aux_cb.pod @@ -106,9 +106,11 @@ During the processing of an B object the callbacks set via I or I will be invoked as a result of various events indicated via the I parameter. The value of I<*in> will be the B object being processed based on the template in I. An -additional operation specific parameter may be passed in I. The currently -supported operations are as follows. The callbacks should return a positive -value on success or zero on error, unless otherwise noted below. +additional operation specific parameter may be passed in I. The +currently supported operations are as follows. Unless noted otherwise below, +the callbacks should return a positive value on success and zero on error; +some operations recognise additional return values, and a few do not consult +the return value at all. =over 4 @@ -130,13 +132,15 @@ I<*pval>. Invoked when processing a B, B or B structure immediately before an B is freed. If the callback originally constructed the B via B then it should free it at -this point and return 2 from the callback. Otherwise it should return 1 for -success or 0 on error. +this point and return 2; the caller will then skip its normal freeing. Any +other return value (including zero) causes the caller to proceed with normal +freeing; the hook cannot signal an error. =item B Invoked when processing a B, B or B structure -immediately after B sub-structures are freed. +immediately after B sub-structures are freed. The caller does not +consult the return value from this hook. =item B @@ -162,7 +166,10 @@ immediately after a "i2d" operation for the B. Invoked when processing a B or B structure immediately before printing the B. The I argument will be a pointer to an -B structure (see below). +B structure (see below). If the callback has fully printed the +value itself it should return 2; the caller will then skip the per-field +printing loop and the matching B callback. Return zero on +error or any other positive value to continue with normal printing. =item B @@ -260,8 +267,41 @@ The streaming I/O boundary. =head1 RETURN VALUES -The callbacks return 0 on error and a positive value on success. Some operations -require specific positive success values as noted above. +In general the callbacks return zero on error and a positive value on +success. Several operations have additional or different return-value +semantics, summarised here: + +=over 4 + +=item * + +B recognises a return of 2, meaning that the callback has +allocated the B itself and normal allocation should be skipped. + +=item * + +B recognises a return of 2, meaning that the callback has +freed the B itself and normal freeing should be skipped. Other +return values (including zero) cause normal freeing to proceed; the hook +cannot signal an error. + +=item * + +B's return value is not consulted by the caller. + +=item * + +B recognises a return of 2, meaning that the callback +has printed the value itself; the caller will skip the per-field printing +loop and the matching B invocation. + +=item * + +B, B, B, and +B treat any non-positive return value (zero or +negative) as an error. + +=back =head1 SEE ALSO From d1fbea9b6b2902f6450216b611b2b246a327c9f5 Mon Sep 17 00:00:00 2001 From: Wolfgang Beck Date: Thu, 18 Jun 2026 00:21:21 +0000 Subject: [PATCH 036/189] Backport PR #30313 into 3.5 branch. Add icx compiler version support in perl asm scripts Reviewed-by: Neil Horman Reviewed-by: Tim Hudson Reviewed-by: Dmitry Belyavskiy MergeDate: Tue Jun 23 12:27:19 2026 (Merged from https://github.com/openssl/openssl/pull/31572) --- crypto/aes/asm/aesni-mb-x86_64.pl | 7 +++++++ crypto/aes/asm/aesni-sha1-x86_64.pl | 3 +++ crypto/aes/asm/aesni-sha256-x86_64.pl | 7 +++++++ crypto/aes/asm/aesni-xts-avx512.pl | 7 +++++++ crypto/bn/asm/rsaz-2k-avx512.pl | 7 +++++++ crypto/bn/asm/rsaz-2k-avxifma.pl | 7 +++++++ crypto/bn/asm/rsaz-3k-avx512.pl | 7 +++++++ crypto/bn/asm/rsaz-3k-avxifma.pl | 7 +++++++ crypto/bn/asm/rsaz-4k-avx512.pl | 7 +++++++ crypto/bn/asm/rsaz-4k-avxifma.pl | 7 +++++++ crypto/bn/asm/rsaz-avx2.pl | 8 ++++++++ crypto/bn/asm/rsaz-x86_64.pl | 7 +++++++ crypto/bn/asm/x86_64-mont.pl | 7 +++++++ crypto/bn/asm/x86_64-mont5.pl | 7 +++++++ crypto/chacha/asm/chacha-x86.pl | 4 ++++ crypto/chacha/asm/chacha-x86_64.pl | 7 +++++++ crypto/ec/asm/ecp_nistz256-x86_64.pl | 8 ++++++++ crypto/ec/asm/x25519-x86_64.pl | 7 +++++++ crypto/modes/asm/aes-gcm-avx512.pl | 7 +++++++ crypto/modes/asm/aesni-gcm-x86_64.pl | 7 +++++++ crypto/modes/asm/ghash-x86_64.pl | 7 +++++++ crypto/poly1305/asm/poly1305-x86.pl | 7 +++++++ crypto/poly1305/asm/poly1305-x86_64.pl | 7 +++++++ crypto/sha/asm/sha1-586.pl | 3 +++ crypto/sha/asm/sha1-mb-x86_64.pl | 7 +++++++ crypto/sha/asm/sha1-x86_64.pl | 7 +++++++ crypto/sha/asm/sha256-586.pl | 7 +++++++ crypto/sha/asm/sha256-mb-x86_64.pl | 7 +++++++ crypto/sha/asm/sha512-x86_64.pl | 7 +++++++ 29 files changed, 194 insertions(+) diff --git a/crypto/aes/asm/aesni-mb-x86_64.pl b/crypto/aes/asm/aesni-mb-x86_64.pl index dde15b1ef7ee5..791e161f67059 100644 --- a/crypto/aes/asm/aesni-mb-x86_64.pl +++ b/crypto/aes/asm/aesni-mb-x86_64.pl @@ -80,6 +80,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/aes/asm/aesni-sha1-x86_64.pl index 4e8fa1d753d7a..47f4422b56acf 100644 --- a/crypto/aes/asm/aesni-sha1-x86_64.pl +++ b/crypto/aes/asm/aesni-sha1-x86_64.pl @@ -111,6 +111,9 @@ $1>=10); $avx=1 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0-9]+\.[0-9]+)/ && $2>=3.0); +$avx=1 if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` =~ /#define __clang_major__.([0-9]+)/ && + $1>=11); #icx started with clang 11 + $shaext=1; ### set to zero if compiling for 1.0.1 $stitched_decrypt=0; diff --git a/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/aes/asm/aesni-sha256-x86_64.pl index 39d29ddbb0228..fdace4ced8cf8 100644 --- a/crypto/aes/asm/aesni-sha256-x86_64.pl +++ b/crypto/aes/asm/aesni-sha256-x86_64.pl @@ -75,6 +75,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + $shaext=$avx; ### set to zero if compiling for 1.0.1 $avx=1 if (!$shaext && $avx); diff --git a/crypto/aes/asm/aesni-xts-avx512.pl b/crypto/aes/asm/aesni-xts-avx512.pl index d89564112e313..16f2bbe789649 100644 --- a/crypto/aes/asm/aesni-xts-avx512.pl +++ b/crypto/aes/asm/aesni-xts-avx512.pl @@ -59,6 +59,13 @@ } } +if (!$avx512vaes && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx512vaes = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/bn/asm/rsaz-2k-avx512.pl b/crypto/bn/asm/rsaz-2k-avx512.pl index 27f2e9b4b9385..7e1db31e223ac 100644 --- a/crypto/bn/asm/rsaz-2k-avx512.pl +++ b/crypto/bn/asm/rsaz-2k-avx512.pl @@ -64,6 +64,13 @@ } } +if (!$avx512ifma && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx512ifma = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/bn/asm/rsaz-2k-avxifma.pl b/crypto/bn/asm/rsaz-2k-avxifma.pl index b84a3e4f1954a..52d9781834d68 100644 --- a/crypto/bn/asm/rsaz-2k-avxifma.pl +++ b/crypto/bn/asm/rsaz-2k-avxifma.pl @@ -39,6 +39,13 @@ $avxifma = ($ver>=16.0); } +if (!$avxifma && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avxifma = ($1>=16); + } +} + if ($win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && `nasm -v 2>&1` =~ /NASM version ([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(rc[0-9]+)?/) { my $ver = $1 + $2/100.0 + $3/10000.0; # 3.1.0->3.01, 3.10.1->3.1001 diff --git a/crypto/bn/asm/rsaz-3k-avx512.pl b/crypto/bn/asm/rsaz-3k-avx512.pl index b2ed3e8ca7cfd..403e09099f732 100644 --- a/crypto/bn/asm/rsaz-3k-avx512.pl +++ b/crypto/bn/asm/rsaz-3k-avx512.pl @@ -63,6 +63,13 @@ } } +if (!$avx512ifma && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx512ifma = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/bn/asm/rsaz-3k-avxifma.pl b/crypto/bn/asm/rsaz-3k-avxifma.pl index 1948d726b38b4..aa11c546af6db 100644 --- a/crypto/bn/asm/rsaz-3k-avxifma.pl +++ b/crypto/bn/asm/rsaz-3k-avxifma.pl @@ -38,6 +38,13 @@ $avxifma = ($ver>=16.0); } +if (!$avxifma && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avxifma = ($1>=16); + } +} + if ($win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?(rc[0-9]+)?/) { $avxifma = ($1>2.16) + ($1==2.16 && ((!defined($2) && !defined($3)) || (defined($2)))); diff --git a/crypto/bn/asm/rsaz-4k-avx512.pl b/crypto/bn/asm/rsaz-4k-avx512.pl index b76ab5904c887..f41c1c60df838 100644 --- a/crypto/bn/asm/rsaz-4k-avx512.pl +++ b/crypto/bn/asm/rsaz-4k-avx512.pl @@ -63,6 +63,13 @@ } } +if (!$avx512ifma && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx512ifma = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/bn/asm/rsaz-4k-avxifma.pl b/crypto/bn/asm/rsaz-4k-avxifma.pl index 9f299430cefcd..28a447800d0d7 100644 --- a/crypto/bn/asm/rsaz-4k-avxifma.pl +++ b/crypto/bn/asm/rsaz-4k-avxifma.pl @@ -38,6 +38,13 @@ $avxifma = ($ver>=16.0); } +if (!$avxifma && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avxifma = ($1>=16); + } +} + if ($win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?(rc[0-9]+)?/) { $avxifma = ($1>2.16) + ($1==2.16 && ((!defined($2) && !defined($3)) || (defined($2)))); diff --git a/crypto/bn/asm/rsaz-avx2.pl b/crypto/bn/asm/rsaz-avx2.pl index 59b9c89b5be2d..56973a19f5347 100755 --- a/crypto/bn/asm/rsaz-avx2.pl +++ b/crypto/bn/asm/rsaz-avx2.pl @@ -73,6 +73,14 @@ $addx = ($ver>=3.03); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $addx = ($1>=11); #icx started with clang 11 + $avx = ($1>=11); + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT = *OUT; diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl index 64acf8f0d84d5..16e215c2e8b53 100755 --- a/crypto/bn/asm/rsaz-x86_64.pl +++ b/crypto/bn/asm/rsaz-x86_64.pl @@ -90,6 +90,13 @@ $addx = ($ver>=3.03); } +if (!$addx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $addx = ($1>=11); #icx started with clang 11 + } +} + ($out, $inp, $mod) = ("%rdi", "%rsi", "%rbp"); # common internal API { my ($out,$inp,$mod,$n0,$times) = ("%rdi","%rsi","%rdx","%rcx","%r8d"); diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl index 140072b899dcb..6c8aa647e20d6 100755 --- a/crypto/bn/asm/x86_64-mont.pl +++ b/crypto/bn/asm/x86_64-mont.pl @@ -82,6 +82,13 @@ $addx = ($ver>=3.03); } +if (!$addx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $addx = ($1>=11); #icx started with clang 11 + } +} + # int bn_mul_mont( $rp="%rdi"; # BN_ULONG *rp, $ap="%rsi"; # const BN_ULONG *ap, diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl index e06d13d74aeae..fc32e76c9014e 100755 --- a/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/bn/asm/x86_64-mont5.pl @@ -69,6 +69,13 @@ $addx = ($ver>=3.03); } +if (!$addx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $addx = ($1>=11); #icx started with clang 11 + } +} + # int bn_mul_mont_gather5( $rp="%rdi"; # BN_ULONG *rp, $ap="%rsi"; # const BN_ULONG *ap, diff --git a/crypto/chacha/asm/chacha-x86.pl b/crypto/chacha/asm/chacha-x86.pl index a1ea4ea461b06..7a825f133965a 100755 --- a/crypto/chacha/asm/chacha-x86.pl +++ b/crypto/chacha/asm/chacha-x86.pl @@ -64,6 +64,10 @@ `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|based on LLVM) ([0-9]+\.[0-9]+)/ && $2>=3.0); # first version supporting AVX +$ymm=1 if ($xmm && !$ymm && + `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` =~ /#define __clang_major__.([0-9]+)/ && + $1>=11); #icx started with clang 11 + $a="eax"; ($b,$b_)=("ebx","ebp"); ($c,$c_)=("ecx","esi"); diff --git a/crypto/chacha/asm/chacha-x86_64.pl b/crypto/chacha/asm/chacha-x86_64.pl index d46bc03b3eec2..40a30b27fa847 100755 --- a/crypto/chacha/asm/chacha-x86_64.pl +++ b/crypto/chacha/asm/chacha-x86_64.pl @@ -91,6 +91,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/ec/asm/ecp_nistz256-x86_64.pl index 4da9a149a99a9..2bb961aeba596 100755 --- a/crypto/ec/asm/ecp_nistz256-x86_64.pl +++ b/crypto/ec/asm/ecp_nistz256-x86_64.pl @@ -80,6 +80,14 @@ $addx = ($ver>=3.03); } +if (!$addx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + $addx = ($1>=11); + } +} + $code.=<<___; .text .extern OPENSSL_ia32cap_P diff --git a/crypto/ec/asm/x25519-x86_64.pl b/crypto/ec/asm/x25519-x86_64.pl index d2285269a308c..4c066eb120824 100755 --- a/crypto/ec/asm/x25519-x86_64.pl +++ b/crypto/ec/asm/x25519-x86_64.pl @@ -97,6 +97,13 @@ $addx = ($ver>=3.03); } +if (!$addx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $addx = ($1>=11); #icx started with clang 11 + } +} + $code.=<<___; .text diff --git a/crypto/modes/asm/aes-gcm-avx512.pl b/crypto/modes/asm/aes-gcm-avx512.pl index 054672bb6b9bf..ad6461f9e52fb 100644 --- a/crypto/modes/asm/aes-gcm-avx512.pl +++ b/crypto/modes/asm/aes-gcm-avx512.pl @@ -72,6 +72,13 @@ } } +if (!$avx512vaes && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx512vaes = ($1>=11); #icx started with clang 11 + } +} + open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT = *OUT; diff --git a/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/modes/asm/aesni-gcm-x86_64.pl index c63570bae42f6..682a8318dd059 100644 --- a/crypto/modes/asm/aesni-gcm-x86_64.pl +++ b/crypto/modes/asm/aesni-gcm-x86_64.pl @@ -73,6 +73,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl index 6ef8e555d0a25..01d9468c4b09f 100644 --- a/crypto/modes/asm/ghash-x86_64.pl +++ b/crypto/modes/asm/ghash-x86_64.pl @@ -121,6 +121,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/poly1305/asm/poly1305-x86.pl b/crypto/poly1305/asm/poly1305-x86.pl index c91d01fb3ba4e..2d9f49d673c98 100755 --- a/crypto/poly1305/asm/poly1305-x86.pl +++ b/crypto/poly1305/asm/poly1305-x86.pl @@ -73,6 +73,13 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|based on LLVM) ([0-9]+\.[0-9]+)/) { $avx = ($2>=3.0) + ($2>3.0); } + + if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } + } } ######################################################################## diff --git a/crypto/poly1305/asm/poly1305-x86_64.pl b/crypto/poly1305/asm/poly1305-x86_64.pl index 305099ca0308a..9647335a426bc 100755 --- a/crypto/poly1305/asm/poly1305-x86_64.pl +++ b/crypto/poly1305/asm/poly1305-x86_64.pl @@ -95,6 +95,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/sha/asm/sha1-586.pl b/crypto/sha/asm/sha1-586.pl index 00350324a117d..3b2927748f605 100644 --- a/crypto/sha/asm/sha1-586.pl +++ b/crypto/sha/asm/sha1-586.pl @@ -146,6 +146,9 @@ $ymm=1 if ($xmm && !$ymm && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|based on LLVM) ([0-9]+\.[0-9]+)/ && $2>=3.0); # first version supporting AVX +$ymm=1 if ($xmm && !$ymm && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` =~ /#define __clang_major__.([0-9]+)/ && + $1>=11); #icx started with clang 11 + $shaext=$xmm; ### set to zero if compiling for 1.0.1 &external_label("OPENSSL_ia32cap_P") if ($xmm); diff --git a/crypto/sha/asm/sha1-mb-x86_64.pl b/crypto/sha/asm/sha1-mb-x86_64.pl index d9d1630d16dbc..b252473ee56b1 100644 --- a/crypto/sha/asm/sha1-mb-x86_64.pl +++ b/crypto/sha/asm/sha1-mb-x86_64.pl @@ -76,6 +76,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl index 30c545cf419a7..990e3afc5b2c6 100755 --- a/crypto/sha/asm/sha1-x86_64.pl +++ b/crypto/sha/asm/sha1-x86_64.pl @@ -124,6 +124,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + $shaext=1; ### set to zero if compiling for 1.0.1 $avx=1 if (!$shaext && $avx); diff --git a/crypto/sha/asm/sha256-586.pl b/crypto/sha/asm/sha256-586.pl index 8e19cd875e3f3..06aab0a28d69c 100644 --- a/crypto/sha/asm/sha256-586.pl +++ b/crypto/sha/asm/sha256-586.pl @@ -99,6 +99,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if ($xmm && !$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + $shaext=$xmm; ### set to zero if compiling for 1.0.1 $unroll_after = 64*4; # If pre-evicted from L1P cache first spin of diff --git a/crypto/sha/asm/sha256-mb-x86_64.pl b/crypto/sha/asm/sha256-mb-x86_64.pl index 9398b7954a7f4..b619e6bafb744 100644 --- a/crypto/sha/asm/sha256-mb-x86_64.pl +++ b/crypto/sha/asm/sha256-mb-x86_64.pl @@ -77,6 +77,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" or die "can't call $xlate: $!"; *STDOUT=*OUT; diff --git a/crypto/sha/asm/sha512-x86_64.pl b/crypto/sha/asm/sha512-x86_64.pl index b37058ae03faf..8a74d56b70eb5 100755 --- a/crypto/sha/asm/sha512-x86_64.pl +++ b/crypto/sha/asm/sha512-x86_64.pl @@ -140,6 +140,13 @@ $avx = ($2>=3.0) + ($2>3.0); } +if (!$avx && `$ENV{CC} -x c /dev/null -dM -E|grep __clang_major__` + =~ /#define __clang_major__.([0-9]+)/) { + if ($1) { + $avx = ($1>=11); #icx started with clang 11 + } +} + $shaext=1; ### set to zero if compiling for 1.0.1 $avx=1 if (!$shaext && $avx); From 68848a750318f9b042b1199f1bfa324058c0254b Mon Sep 17 00:00:00 2001 From: 007bsd <22483432+007bsd@users.noreply.github.com> Date: Fri, 15 May 2026 12:04:58 +0300 Subject: [PATCH 037/189] Fix key2ms_newctx() pointer type mismatch in MSBLOB/PVK key encoder key2ms_newctx() returned struct key2ms_ctx_st *, but is registered as OSSL_FUNC_ENCODER_NEWCTX and called through OSSL_FUNC_encoder_newctx_fn (void *(*)(void *)), which is a case of undefined behavior, flagged by -fsanitize=function. Same class as [1], missed there. Give it the correct signature and add the self-check forward declaration, as key2ms_freectx() already has. [1] https://github.com/openssl/openssl/pull/31078 CLA: trivial Fixes: 0cc0164d193f "PROV: Add MSBLOB and PVK encoders" Reviewed-by: Frederik Wedel-Heinen Reviewed-by: Viktor Dukhovni Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale MergeDate: Tue Jun 23 14:45:54 2026 (Merged from https://github.com/openssl/openssl/pull/31189) (cherry picked from commit 8d0f837db83586b6e4b12a24ee68c5e2ea643d75) --- providers/implementations/encode_decode/encode_key2ms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/providers/implementations/encode_decode/encode_key2ms.c b/providers/implementations/encode_decode/encode_key2ms.c index 362a806589e6a..7500235399d32 100644 --- a/providers/implementations/encode_decode/encode_key2ms.c +++ b/providers/implementations/encode_decode/encode_key2ms.c @@ -65,10 +65,11 @@ static int write_pvk(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout, return ret; } +static OSSL_FUNC_encoder_newctx_fn key2ms_newctx; static OSSL_FUNC_encoder_freectx_fn key2ms_freectx; static OSSL_FUNC_encoder_does_selection_fn key2ms_does_selection; -static struct key2ms_ctx_st *key2ms_newctx(void *provctx) +static void *key2ms_newctx(void *provctx) { struct key2ms_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); From 962879eea85e685e4b0660503ccbd2e3a4e98ff1 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Tue, 21 Apr 2026 10:32:50 +0900 Subject: [PATCH 038/189] pkcs7: Fix negative index handling in PKCS7_get_issuer_and_serial() Reject negative indices before looking up the recipient info stack entry. This makes negative out-of-range indices match the existing behavior for too-large positive indices and avoids dereferencing a NULL recipient info. Add a regression test for the negative index case. Resolves: https://github.com/openssl/openssl/issues/30910 Reviewed-by: Eugene Syromiatnikov Reviewed-by: Nikola Pajkovsky Reviewed-by: David von Oheimb MergeDate: Wed Jun 24 09:10:22 2026 (Merged from https://github.com/openssl/openssl/pull/30914) (cherry picked from commit b44fd71741b7b5092c087d227b32298c7fedb520) --- crypto/pkcs7/pk7_doit.c | 2 +- test/pkcs7_test.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index 1ec7895fc1976..aaf3c19aaeae0 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -1200,7 +1200,7 @@ PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) rsk = p7->d.signed_and_enveloped->recipientinfo; if (rsk == NULL) return NULL; - if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) + if (idx < 0 || sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return NULL; ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); return ri->issuer_and_serial; diff --git a/test/pkcs7_test.c b/test/pkcs7_test.c index ac4bb84bbe366..d2fbdb73bb382 100644 --- a/test/pkcs7_test.c +++ b/test/pkcs7_test.c @@ -15,6 +15,30 @@ #include "internal/nelem.h" #include "testutil.h" +static int pkcs7_issuer_and_serial_negative_idx_test(void) +{ + PKCS7 *p7 = NULL; + PKCS7_RECIP_INFO *ri = NULL; + int ret = 0; + + if (!TEST_ptr(p7 = PKCS7_new()) + || !TEST_true(PKCS7_set_type(p7, NID_pkcs7_signedAndEnveloped)) + || !TEST_ptr(ri = PKCS7_RECIP_INFO_new()) + || !TEST_true(PKCS7_add_recipient_info(p7, ri))) + goto end; + ri = NULL; + + if (!TEST_ptr(PKCS7_get_issuer_and_serial(p7, 0)) + || !TEST_ptr_null(PKCS7_get_issuer_and_serial(p7, -1))) + goto end; + + ret = 1; +end: + PKCS7_RECIP_INFO_free(ri); + PKCS7_free(p7); + return ret; +} + #ifndef OPENSSL_NO_EC static const unsigned char cert_der[] = { 0x30, 0x82, 0x01, 0x51, 0x30, 0x81, 0xf7, 0xa0, 0x03, 0x02, 0x01, 0x02, @@ -389,6 +413,7 @@ static int pkcs7_inner_content_verify_test(void) int setup_tests(void) { + ADD_TEST(pkcs7_issuer_and_serial_negative_idx_test); #ifndef OPENSSL_NO_EC ADD_TEST(pkcs7_verify_test); ADD_TEST(pkcs7_inner_content_verify_test); From 430409b4dc66fcbf01b5b35545a91d41ede6af34 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Mon, 15 Jun 2026 20:10:07 +0200 Subject: [PATCH 039/189] Prevent integer overflow in ASN1_mbstring_ncopy This prevents a theoretically possible integer overflow in OPENSSL_malloc(outlen + 1) at the end of ASN1_mbstring_ncopy, when outlen is exactly INT_MAX. That affects conversions from MBSTRING_ASC to MBSTRING_UTF8 and MBSTRING_UTF8 to MBSTRING_ASC, because a terminating zero has to be added to the result. And also conversions MBSTRING_BMP to MBSTRING_UTF8 in cases when UTF8 characters 0x800..0xFFFF are encoded as 3-byte UTF8-characters and the resulting UTF8-string is exactly INT_MAX in size. Fixes: 97f6b621f7af ("Reject oversized inputs in ASN1_mbstring_ncopy()") Reviewed-by: Paul Dale Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz MergeDate: Wed Jun 24 12:56:59 2026 (Merged from https://github.com/openssl/openssl/pull/31529) --- crypto/asn1/a_mbstr.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c index ce5618dfd48b8..9a61f7f1e051f 100644 --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -51,12 +51,24 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, unsigned char *p; int nchar; int (*cpyfunc)(unsigned long, void *) = NULL; - if (len == -1) - len = strlen((const char *)in); + if (len == -1) { + size_t len_s = strlen((const char *)in); + + if (len_s >= INT_MAX) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG); + return -1; + } + len = (int)len_s; + } if (!mask) mask = DIRSTRING_TYPE; - if (len < 0) + if (len < 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_INVALID_ARGUMENT); + return -1; + } else if (len >= INT_MAX) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG); return -1; + } /* First do a string check and work out the number of characters */ switch (inform) { @@ -294,7 +306,7 @@ static int out_utf8(unsigned long value, void *arg) return len; } outlen = arg; - if (*outlen > INT_MAX - len) { + if (*outlen >= INT_MAX - len) { ERR_raise(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG); return -1; } From be907383c55bae2eec87c8284e385cdcd957de13 Mon Sep 17 00:00:00 2001 From: Bob Beck Date: Fri, 29 May 2026 05:39:40 -0600 Subject: [PATCH 040/189] Add documentation for NAME_CONSTRAINTS_check We document which names and name constraints will be evaluated as well as the limits that will be placed on the evauluation on a per certificate basis. We call out in the BUGS section that the RFC 5280 requires a byte per byte match of name constraints unless the higher level protocol has defines a different matching method for wildcards. This "deferall of specification" and corresponding lack of specification by upper level protocols means that across implementations encountering the default behaviour is to be expected, and that therefore relying on excluded names to constrain signers in a PKI from signing wildcards is ill advised. This is then cross referenced in the documentation for X509_verify_cert and the maximum possible comparisons which can be forces in a certificate validtion noted in the BUGS section of X509_verify_cert. Fixes: https://github.com/openssl/openssl/issues/30706 Reviewed-by: Neil Horman Reviewed-by: Nikola Pajkovsky MergeDate: Wed Jun 24 13:03:54 2026 (Merged from https://github.com/openssl/openssl/pull/31334) (cherry picked from commit 1a65972ad0b5e3a02e33de3cd7bda61764067710) --- doc/build.info | 6 + doc/man3/NAME_CONSTRAINTS_check.pod | 211 ++++++++++++++++++++++++++++ doc/man3/X509_verify_cert.pod | 13 +- util/missingcrypto.txt | 2 - 4 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 doc/man3/NAME_CONSTRAINTS_check.pod diff --git a/doc/build.info b/doc/build.info index eb4492ba9c753..8f20c3f59b8b7 100644 --- a/doc/build.info +++ b/doc/build.info @@ -1523,6 +1523,10 @@ DEPEND[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod GENERATE[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod DEPEND[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod GENERATE[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod +DEPEND[html/man3/NAME_CONSTRAINTS_check.html]=man3/NAME_CONSTRAINTS_check.pod +GENERATE[html/man3/NAME_CONSTRAINTS_check.html]=man3/NAME_CONSTRAINTS_check.pod +DEPEND[man/man3/NAME_CONSTRAINTS_check.3]=man3/NAME_CONSTRAINTS_check.pod +GENERATE[man/man3/NAME_CONSTRAINTS_check.3]=man3/NAME_CONSTRAINTS_check.pod DEPEND[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod GENERATE[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod DEPEND[man/man3/NCONF_new_ex.3]=man3/NCONF_new_ex.pod @@ -3446,6 +3450,7 @@ html/man3/GENERAL_NAME.html \ html/man3/HMAC.html \ html/man3/MD5.html \ html/man3/MDC2_Init.html \ +html/man3/NAME_CONSTRAINTS_check.html \ html/man3/NCONF_new_ex.html \ html/man3/OBJ_nid2obj.html \ html/man3/OCSP_REQUEST_new.html \ @@ -4123,6 +4128,7 @@ man/man3/GENERAL_NAME.3 \ man/man3/HMAC.3 \ man/man3/MD5.3 \ man/man3/MDC2_Init.3 \ +man/man3/NAME_CONSTRAINTS_check.3 \ man/man3/NCONF_new_ex.3 \ man/man3/OBJ_nid2obj.3 \ man/man3/OCSP_REQUEST_new.3 \ diff --git a/doc/man3/NAME_CONSTRAINTS_check.pod b/doc/man3/NAME_CONSTRAINTS_check.pod new file mode 100644 index 0000000000000..3dfe39ea29420 --- /dev/null +++ b/doc/man3/NAME_CONSTRAINTS_check.pod @@ -0,0 +1,211 @@ +=pod + +=head1 NAME + +NAME_CONSTRAINTS_check, +NAME_CONSTRAINTS_check_CN - check a certificate's names against a name +constraints extension + +=head1 SYNOPSIS + + #include + + int NAME_CONSTRAINTS_check(const X509 *x, NAME_CONSTRAINTS *nc); + int NAME_CONSTRAINTS_check_CN(const X509 *x, NAME_CONSTRAINTS *nc); + +=head1 DESCRIPTION + +NAME_CONSTRAINTS_check() tests whether the names asserted by certificate +I satisfy the name constraints I. It implements the matching +primitive of RFC 5280 section 4.2.1.10: given a constraint set (a +B structure containing zero or more B +and B) and a candidate certificate, decide whether the +certificate's names fall within the permitted subtrees and outside the +excluded subtrees. + +The names considered by NAME_CONSTRAINTS_check() are: + +=over 4 + +=item * + +The certificate's subject distinguished name, matched as a B +general-name type. The subject is considered only when it is nonempty. + +=item * + +Each B attribute appearing within the subject distinguished +name, matched as an B general-name type. These attributes are +the historical, pre-SAN way of expressing an email address in a +certificate's subject, and RFC 5280 requires that they be subjected to +name-constraint checking. + +=item * + +Each entry in the certificate's subject alternative name extension, matched +according to its declared general-name type. + +=back + +NAME_CONSTRAINTS_check() implements matching for the following +general-name types: B, B, B, +B, and B. The B form +B (RFC 8398) is additionally matched against +B subtrees. Any other general-name type, including +B, B, B, and other B +forms, yields B. + +For each name considered, the function evaluates two conditions: + +=over 4 + +=item * + +If I contains at least one B of the same general-name +type as the name, the name must match at least one of those permitted +subtrees. If I contains no permitted subtrees of that type, no +permitted-subtrees test is imposed on names of that type. + +=item * + +The name must not match any B of the same general-name +type in I. + +=back + +The function returns at the first violation encountered; it does not +collect or report multiple failures. + +For B entries, matching follows the byte/label algorithm of +RFC 5280 section 4.2.1.10, which RFC 5280 mandates when no +protocol-specific matching rules apply. Because this match is performed +without awareness of any specific higher-level protocol, additional +matching rules defined by later or more specific protocols must be +applied independently of this function to the certificate chain. + +NAME_CONSTRAINTS_check() performs only the constraint match for a single +certificate against a single constraint set. It does B perform the +chain-wide enforcement of RFC 5280 section 6.1.4(g)-(j): callers wishing to +enforce name constraints across an entire certification path must walk the +chain themselves and apply each ancestor's constraint set to certificates +lower in the chain, observing the usual exceptions (for example, +self-issued intermediate certificates are exempt from constraints imposed +by certificates above them, except when they are the leaf of the chain). +For full RFC 5280 name-constraint enforcement integrated with chain +validation, applications should use L, which performs +this internally. + +NAME_CONSTRAINTS_check() enforces an implementation limit on the product +of the certificate's name count and the constraint set's subtree count, to +prevent computationally expensive matching on pathological input. If that +limit is exceeded the function returns B without +performing any matching. The current limit is 2**20 (1,048,576) on the +product of the name count (subject DN entries plus B +entries) and the subtree count (B plus +B). + +=head1 RETURN VALUES + +NAME_CONSTRAINTS_check() returns B if every name considered +satisfies the constraints. Otherwise it returns one of the following +B codes: + +=over 4 + +=item B + +A name of a type for which I contains at least one permitted subtree +failed to match any of those subtrees. + +=item B + +A name matched an excluded subtree. + +=item B + +A subtree in I specified a B other than 0 or a B at +all. RFC 5280 requires that these B fields not be used, +and a constraint set that uses them cannot be processed. + +=item B + +A general-name type for which matching is not implemented was encountered. +The list of supported types is given in the DESCRIPTION above. + +=item B + +A name in the certificate is encoded in a way that cannot be matched (for +example, an B attribute in the subject that is not encoded +as an B). + +=item B + +The product of the certificate's name count and the constraint set's +subtree count exceeded the implementation limit; no matching was +performed. + +=back + +Other B codes may be returned by deeper name-matching +helpers (for example, codes arising from individual general-name type +comparisons). Callers should treat the return value as the authoritative +success/failure signal and treat any value other than B as a +failure, rather than enumerating the specific codes above. + +=head1 NOTES + +NAME_CONSTRAINTS_check() does not match the certificate's commonName +against B name constraints; that check is provided by a separate +function, B(). The commonName-as-DNS-identity +practice is a legacy concern: modern certificates assert DNS identities +through B entries in the subject alternative name extension, +which NAME_CONSTRAINTS_check() already covers. NAME_CONSTRAINTS_check_CN() +is required only for older certificates that express a DNS identity +through their commonName instead of, or in addition to, the SAN; for +certificates conforming to modern profiles a call to NAME_CONSTRAINTS_check() +alone is generally sufficient. + +=head1 BUGS + +RFC 9525's wildcard semantics apply only to presented-identifier +matching for TLS service identity, and explicitly call out they are not +valid for any other purpose; they do not define wildcard handling +for name-constraint matching. NAME_CONSTRAINTS_check() therefore +follows RFC 5280's requirements for when this is undefined, and treats +the B<*> character in a B as a literal label component, per +the RFC 5280 algorithm, which is often contrary to caller expectation. + +Even if specified in the future, due to the "fallback implementation" +nature of matching wildcards in SAN B entries specified by +RFC 5280, name constraint behaviour in the presence of wildcards +should not be strictly relied upon across implementations and +protocols. This matters most for the use of B +constraints, which should not be relied upon to reliably constrain +signing certificates for a PKI in a security dependent manner unless +the consumers of these certificates are themselves known to be +constrained by other means to only use implementations that provide +different semantics, or the PKI can be constrained by other means to +ensure that wildcards are never issued from such signing +certificates. + +=head1 SEE ALSO + +L, +L + +=head1 HISTORY + +NAME_CONSTRAINTS_check() was added in OpenSSL 1.0.0. + +NAME_CONSTRAINTS_check_CN() was added in OpenSSL 1.1.0. + +=head1 COPYRIGHT + +Copyright 2026 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 +L. + +=cut diff --git a/doc/man3/X509_verify_cert.pod b/doc/man3/X509_verify_cert.pod index 95f3404e27511..2bbfa25006f9d 100644 --- a/doc/man3/X509_verify_cert.pod +++ b/doc/man3/X509_verify_cert.pod @@ -104,7 +104,9 @@ terminator. =item 7. -B per RFC 5280 section 4.2.1.10. +B per RFC 5280 section 4.2.1.10; see +L for details of the matching primitive and +the general-name types it covers. =item 8. @@ -450,8 +452,17 @@ above it. Callers should nevertheless be aware that the chain returned in this mode does not necessarily terminate at an RFC 5280-style trust anchor. +L caps each per-pair check at 2**20 +comparisons, but the chain orchestrator issues B(B-1)/2 such +checks for an B-certificate chain. An adversary submitting a +maximally constructed chain can therefore force up to approximately +6.3 million name-constraint comparisons in a four-certificate chain +(one leaf and three name-constrained signers), or approximately 5.2 +billion at the default chain-depth limit of 100. + =head1 SEE ALSO +L, L, L, L, diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index 16ca0e49dfa0c..ad0f165fa6ba6 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -590,8 +590,6 @@ LONG_it(3) MD2_options(3) MD4_Transform(3) MD5_Transform(3) -NAME_CONSTRAINTS_check(3) -NAME_CONSTRAINTS_check_CN(3) NAME_CONSTRAINTS_it(3) NAMING_AUTHORITY_it(3) NCONF_WIN32(3) From 948b17002e148a473dc1920668938975da58228a Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Tue, 23 Jun 2026 10:06:04 +0200 Subject: [PATCH 041/189] include/internal/hashtable.h: avoid OOB read in ossl_ht_strcase() Avoid accessing src[len] by swapping the check order and bound check the iterator variable before the access. Found by cppcheck. Fixes: cc4ea5e00028 "Introduce new internal hashtable implementation" Signed-off-by: Eugene Syromiatnikov Reviewed-by: Nikola Pajkovsky Reviewed-by: Neil Horman Reviewed-by: Paul Dale MergeDate: Wed Jun 24 13:09:25 2026 (Merged from https://github.com/openssl/openssl/pull/31663) (cherry picked from commit 029d629db23e95c6e827d09dae89ee8b4b54f3e2) --- include/internal/hashtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/hashtable.h b/include/internal/hashtable.h index bc44e43678a36..edc447b50b290 100644 --- a/include/internal/hashtable.h +++ b/include/internal/hashtable.h @@ -272,7 +272,7 @@ static void ossl_unused ossl_ht_strcase(char *tgt, const char *src, int len) if (src == NULL) return; - for (i = 0; src[i] != '\0' && i < len; i++) + for (i = 0; i < len && src[i] != '\0'; i++) tgt[i] = case_adjust & src[i]; } From 9b9c3886b22d57d428a481ae22cafeca525ca67f Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Wed, 20 May 2026 23:55:17 +1000 Subject: [PATCH 042/189] Fix EVP_PKEY_dup() for ML-KEM keys (3.5) ossl_ml_kem_key_dup() left the (PUB|PRIV) selection case unhandled, so EVP_PKEY_dup() silently returned NULL for ML-KEM-512/768/1024. add_storage() also zeroed the duplicated rho_pkhash, leaving the dup unequal to the original. Add a parameterised dup sweep to test/endecode_test.c covering every supported public-key algorithm in three shapes: full keypair, public-only, and embryonic (parameters-only). While here, stop endecode_test from silently passing when key generation fails: setup_tests() now returns its accumulated status, MAKE_*KEYS no longer short-circuits, and each ADD_TEST_SUITE is now conditional on keygen success. Guard the explicit-EC-curve tests with OPENSSL_NO_EC_EXPLICIT_CURVES. Reviewed-by: Nikola Pajkovsky Reviewed-by: Bob Beck MergeDate: Thu Jun 25 02:09:47 2026 (Merged from https://github.com/openssl/openssl/pull/31253) --- crypto/ml_kem/ml_kem.c | 23 ++-- test/endecode_test.c | 247 +++++++++++++++++++++++++++++++++++------ 2 files changed, 228 insertions(+), 42 deletions(-) diff --git a/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c index dd8a39197ac8b..1bc3c0a0a8909 100644 --- a/crypto/ml_kem/ml_kem.c +++ b/crypto/ml_kem/ml_kem.c @@ -1845,7 +1845,7 @@ static int decap(uint8_t secret[ML_KEM_SHARED_SECRET_BYTES], * After allocating storage for public or private key data, update the key * component pointers to reference that storage. */ -static __owur int add_storage(scalar *p, int private, ML_KEM_KEY *key) +static __owur int add_storage(scalar *p, int private, int dup, ML_KEM_KEY *key) { int rank = key->vinfo->rank; @@ -1854,9 +1854,12 @@ static __owur int add_storage(scalar *p, int private, ML_KEM_KEY *key) /* * We're adding key material, the seed buffer will now hold |rho| and - * |pkhash|. + * |pkhash|. Zero the key hash when creating fresh keys; when + * duplicating, |key| was memdup'd from the source so |seedbuf| + * already carries the correct |rho|/|pkhash| bytes — preserve them. */ - memset(key->seedbuf, 0, sizeof(key->seedbuf)); + if (dup == 0) + memset(key->seedbuf, 0, sizeof(key->seedbuf)); key->rho = key->seedbuf; key->pkhash = key->seedbuf + ML_KEM_RANDOM_BYTES; key->d = key->z = NULL; @@ -1980,18 +1983,18 @@ ML_KEM_KEY *ossl_ml_kem_key_dup(const ML_KEM_KEY *key, int selection) selection = 0; else if (!ossl_ml_kem_have_prvkey(key)) selection &= ~OSSL_KEYMGMT_SELECT_PRIVATE_KEY; + else if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + selection &= ~OSSL_KEYMGMT_SELECT_PUBLIC_KEY; switch (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) { case 0: ok = 1; break; case OSSL_KEYMGMT_SELECT_PUBLIC_KEY: - ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->puballoc), 0, ret); - ret->rho = ret->seedbuf; - ret->pkhash = ret->rho + ML_KEM_RANDOM_BYTES; + ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->puballoc), 0, 1, ret); break; case OSSL_KEYMGMT_SELECT_PRIVATE_KEY: - ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->prvalloc), 1, ret); + ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->prvalloc), 1, 1, ret); /* Duplicated keys retain |d|, if available */ if (key->d != NULL) ret->d = ret->z + ML_KEM_RANDOM_BYTES; @@ -2111,7 +2114,7 @@ int ossl_ml_kem_parse_public_key(const uint8_t *in, size_t len, ML_KEM_KEY *key) || (mdctx = EVP_MD_CTX_new()) == NULL) return 0; - if (add_storage(OPENSSL_malloc(vinfo->puballoc), 0, key)) + if (add_storage(OPENSSL_malloc(vinfo->puballoc), 0, 0, key)) ret = parse_pubkey(in, mdctx, key); if (!ret) @@ -2139,7 +2142,7 @@ int ossl_ml_kem_parse_private_key(const uint8_t *in, size_t len, || (mdctx = EVP_MD_CTX_new()) == NULL) return 0; - if (add_storage(OPENSSL_malloc(vinfo->prvalloc), 1, key)) + if (add_storage(OPENSSL_malloc(vinfo->prvalloc), 1, 0, key)) ret = parse_prvkey(in, mdctx, key); if (!ret) @@ -2187,7 +2190,7 @@ int ossl_ml_kem_genkey(uint8_t *pubenc, size_t publen, ML_KEM_KEY *key) */ CONSTTIME_SECRET(seed, ML_KEM_SEED_BYTES); - if (add_storage(OPENSSL_malloc(vinfo->prvalloc), 1, key)) + if (add_storage(OPENSSL_malloc(vinfo->prvalloc), 1, 0, key)) ret = genkey(seed, mdctx, pubenc, key); OPENSSL_cleanse(seed, sizeof(seed)); diff --git a/test/endecode_test.c b/test/endecode_test.c index bd068b208a912..e523e1bff643d 100644 --- a/test/endecode_test.c +++ b/test/endecode_test.c @@ -60,6 +60,7 @@ static OSSL_PROVIDER *keyprov = NULL; #ifndef OPENSSL_NO_EC static BN_CTX *bnctx = NULL; +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES static OSSL_PARAM_BLD *bld_prime_nc = NULL; static OSSL_PARAM_BLD *bld_prime = NULL; static OSSL_PARAM *ec_explicit_prime_params_nc = NULL; @@ -72,6 +73,7 @@ static OSSL_PARAM *ec_explicit_tri_params_nc = NULL; static OSSL_PARAM *ec_explicit_tri_params_explicit = NULL; #endif #endif +#endif #ifndef OPENSSL_NO_KEYPARAMS static EVP_PKEY *make_template(const char *type, OSSL_PARAM *genparams) @@ -870,21 +872,155 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) test_mem, check_public_MSBLOB, dump_der, 0); } +/* + * Build a public-only EVP_PKEY of the same algorithm as |src| by + * round-tripping the public component through OSSL_PARAMs. + */ +static EVP_PKEY *make_public_only_copy(EVP_PKEY *src) +{ + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *cctx = NULL; + EVP_PKEY *pub = NULL; + + if (!EVP_PKEY_todata(src, EVP_PKEY_PUBLIC_KEY, ¶ms)) + goto end; + if ((cctx = EVP_PKEY_CTX_new_from_pkey(NULL, src, NULL)) == NULL + || EVP_PKEY_fromdata_init(cctx) <= 0 + || EVP_PKEY_fromdata(cctx, &pub, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + EVP_PKEY_free(pub); + pub = NULL; + } +end: + OSSL_PARAM_free(params); + EVP_PKEY_CTX_free(cctx); + return pub; +} + +/* + * Build an "embryonic" EVP_PKEY of the same algorithm as |src|: just + * the keymgmt-bound type and (where applicable) domain parameters, + * with no key material. Mirrors the idiom used in + * test/ml_kem_evp_extra_test.c. + */ +static EVP_PKEY *make_embryonic_copy(EVP_PKEY *src) +{ + EVP_PKEY *embryo = EVP_PKEY_new(); + + if (embryo == NULL) + return NULL; + if (EVP_PKEY_copy_parameters(embryo, src) <= 0) { + EVP_PKEY_free(embryo); + return NULL; + } + return embryo; +} + +/* + * Check that EVP_PKEY_dup() works for every supported provider-backed + * key type, and that the duplicate compares equal to the original. + * + * Exercised in three shapes: + * 1. The full keypair |key| (typically pub + priv). + * 2. A public-only key derived from |key|. + * 3. An "embryonic" key (algorithm + domain parameters only, no key + * material) produced with EVP_PKEY_copy_parameters(). Not every + * keymgmt allows building such a key (RSA's dup refuses any + * selection without keypair bits); when EVP_PKEY_copy_parameters + * fails we skip this arm with a TEST_info(). + */ +static int test_dup(const char *type, EVP_PKEY *key) +{ + EVP_PKEY *dup = NULL; + EVP_PKEY *pub_only = NULL; + EVP_PKEY *embryo = NULL; + int ok = 0; + + if (!TEST_ptr(key)) { + TEST_info("%s: no source key", type); + return 0; + } + + /* 1. Dup the full keypair. */ + if (!TEST_ptr(dup = EVP_PKEY_dup(key))) { + TEST_info("%s: EVP_PKEY_dup of keypair returned NULL", type); + goto end; + } + if (!TEST_int_eq(EVP_PKEY_eq(key, dup), 1)) { + TEST_info("%s: keypair dup does not compare equal to original", type); + goto end; + } + EVP_PKEY_free(dup); + dup = NULL; + + /* 2. Dup a public-only copy of the same key. */ + if (!TEST_ptr(pub_only = make_public_only_copy(key))) { + TEST_info("%s: could not derive a public-only key", type); + goto end; + } + if (!TEST_ptr(dup = EVP_PKEY_dup(pub_only))) { + TEST_info("%s: EVP_PKEY_dup of public-only key returned NULL", type); + goto end; + } + if (!TEST_int_eq(EVP_PKEY_eq(pub_only, dup), 1)) { + TEST_info("%s: public-only dup does not compare equal to original", + type); + goto end; + } + EVP_PKEY_free(dup); + dup = NULL; + + /* + * 3. Dup an embryonic key. EVP_PKEY_parameters_eq() answers 1 for + * algorithms with real domain parameters and may answer -2 ("nothing + * to compare") for those without. We only reject 0 (definitively + * unequal) and -1 (different keymgmts). + */ + embryo = make_embryonic_copy(key); + if (embryo != NULL) { + if (!TEST_ptr(dup = EVP_PKEY_dup(embryo))) { + TEST_info("%s: EVP_PKEY_dup of embryonic key returned NULL", + type); + goto end; + } + { + int eq = EVP_PKEY_parameters_eq(embryo, dup); + + if (!TEST_true(eq == 1 || eq == -2)) { + TEST_info("%s: embryonic dup parameters_eq %d (want 1 or -2)", + type, eq); + goto end; + } + } + } else { + TEST_info("%s: skipping embryonic dup (no params-only key shape)", + type); + } + + ok = 1; +end: + EVP_PKEY_free(dup); + EVP_PKEY_free(pub_only); + EVP_PKEY_free(embryo); + return ok; +} + #define KEYS(KEYTYPE) \ static EVP_PKEY *key_##KEYTYPE = NULL #define MAKE_KEYS(KEYTYPE, KEYTYPEstr, params) \ - ok = ok \ - && TEST_ptr(key_##KEYTYPE = make_key(KEYTYPEstr, NULL, params)) + ok &= TEST_ptr(key_##KEYTYPE = make_key(KEYTYPEstr, NULL, params)) #define FREE_KEYS(KEYTYPE) \ EVP_PKEY_free(key_##KEYTYPE); #define DOMAIN_KEYS(KEYTYPE) \ static EVP_PKEY *template_##KEYTYPE = NULL; \ static EVP_PKEY *key_##KEYTYPE = NULL -#define MAKE_DOMAIN_KEYS(KEYTYPE, KEYTYPEstr, params) \ - ok = ok \ - && TEST_ptr(template_##KEYTYPE = make_template(KEYTYPEstr, params)) \ - && TEST_ptr(key_##KEYTYPE = make_key(KEYTYPEstr, template_##KEYTYPE, NULL)) +#define MAKE_DOMAIN_KEYS(KEYTYPE, KEYTYPEstr, params) \ + do { \ + ok &= TEST_ptr(template_##KEYTYPE = make_template(KEYTYPEstr, \ + params)); \ + ok &= TEST_ptr(key_##KEYTYPE = make_key(KEYTYPEstr, \ + template_##KEYTYPE, NULL)); \ + } while (0) #define FREE_DOMAIN_KEYS(KEYTYPE) \ EVP_PKEY_free(template_##KEYTYPE); \ EVP_PKEY_free(key_##KEYTYPE) @@ -913,15 +1049,24 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) static int test_public_##KEYTYPE##_via_PEM(void) \ { \ return test_public_via_PEM(KEYTYPEstr, key_##KEYTYPE, fips); \ + } \ + static int test_dup_##KEYTYPE(void) \ + { \ + return test_dup(KEYTYPEstr, key_##KEYTYPE); \ } -#define ADD_TEST_SUITE(KEYTYPE) \ - ADD_TEST(test_unprotected_##KEYTYPE##_via_DER); \ - ADD_TEST(test_unprotected_##KEYTYPE##_via_PEM); \ - ADD_TEST(test_protected_##KEYTYPE##_via_DER); \ - ADD_TEST(test_protected_##KEYTYPE##_via_PEM); \ - ADD_TEST(test_public_##KEYTYPE##_via_DER); \ - ADD_TEST(test_public_##KEYTYPE##_via_PEM) +#define ADD_TEST_SUITE(KEYTYPE) \ + do { \ + if (key_##KEYTYPE != NULL) { \ + ADD_TEST(test_unprotected_##KEYTYPE##_via_DER); \ + ADD_TEST(test_unprotected_##KEYTYPE##_via_PEM); \ + ADD_TEST(test_protected_##KEYTYPE##_via_DER); \ + ADD_TEST(test_protected_##KEYTYPE##_via_PEM); \ + ADD_TEST(test_public_##KEYTYPE##_via_DER); \ + ADD_TEST(test_public_##KEYTYPE##_via_PEM); \ + ADD_TEST(test_dup_##KEYTYPE); \ + } \ + } while (0) #define IMPLEMENT_TEST_SUITE_PARAMS(KEYTYPE, KEYTYPEstr) \ static int test_params_##KEYTYPE##_via_DER(void) \ @@ -933,9 +1078,13 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) return test_params_via_PEM(KEYTYPEstr, key_##KEYTYPE); \ } -#define ADD_TEST_SUITE_PARAMS(KEYTYPE) \ - ADD_TEST(test_params_##KEYTYPE##_via_DER); \ - ADD_TEST(test_params_##KEYTYPE##_via_PEM) +#define ADD_TEST_SUITE_PARAMS(KEYTYPE) \ + do { \ + if (key_##KEYTYPE != NULL) { \ + ADD_TEST(test_params_##KEYTYPE##_via_DER); \ + ADD_TEST(test_params_##KEYTYPE##_via_PEM); \ + } \ + } while (0) #define IMPLEMENT_TEST_SUITE_LEGACY(KEYTYPE, KEYTYPEstr) \ static int test_unprotected_##KEYTYPE##_via_legacy_PEM(void) \ @@ -947,9 +1096,13 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) return test_protected_via_legacy_PEM(KEYTYPEstr, key_##KEYTYPE); \ } -#define ADD_TEST_SUITE_LEGACY(KEYTYPE) \ - ADD_TEST(test_unprotected_##KEYTYPE##_via_legacy_PEM); \ - ADD_TEST(test_protected_##KEYTYPE##_via_legacy_PEM) +#define ADD_TEST_SUITE_LEGACY(KEYTYPE) \ + do { \ + if (key_##KEYTYPE != NULL) { \ + ADD_TEST(test_unprotected_##KEYTYPE##_via_legacy_PEM); \ + ADD_TEST(test_protected_##KEYTYPE##_via_legacy_PEM); \ + } \ + } while (0) #define IMPLEMENT_TEST_SUITE_MSBLOB(KEYTYPE, KEYTYPEstr) \ static int test_unprotected_##KEYTYPE##_via_MSBLOB(void) \ @@ -961,25 +1114,35 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key) return test_public_via_MSBLOB(KEYTYPEstr, key_##KEYTYPE); \ } -#define ADD_TEST_SUITE_MSBLOB(KEYTYPE) \ - ADD_TEST(test_unprotected_##KEYTYPE##_via_MSBLOB); \ - ADD_TEST(test_public_##KEYTYPE##_via_MSBLOB) +#define ADD_TEST_SUITE_MSBLOB(KEYTYPE) \ + do { \ + if (key_##KEYTYPE != NULL) { \ + ADD_TEST(test_unprotected_##KEYTYPE##_via_MSBLOB); \ + ADD_TEST(test_public_##KEYTYPE##_via_MSBLOB); \ + } \ + } while (0) #define IMPLEMENT_TEST_SUITE_UNPROTECTED_PVK(KEYTYPE, KEYTYPEstr) \ static int test_unprotected_##KEYTYPE##_via_PVK(void) \ { \ return test_unprotected_via_PVK(KEYTYPEstr, key_##KEYTYPE); \ } -#define ADD_TEST_SUITE_UNPROTECTED_PVK(KEYTYPE) \ - ADD_TEST(test_unprotected_##KEYTYPE##_via_PVK) +#define ADD_TEST_SUITE_UNPROTECTED_PVK(KEYTYPE) \ + do { \ + if (key_##KEYTYPE != NULL) \ + ADD_TEST(test_unprotected_##KEYTYPE##_via_PVK); \ + } while (0) #ifndef OPENSSL_NO_RC4 #define IMPLEMENT_TEST_SUITE_PROTECTED_PVK(KEYTYPE, KEYTYPEstr) \ static int test_protected_##KEYTYPE##_via_PVK(void) \ { \ return test_protected_via_PVK(KEYTYPEstr, key_##KEYTYPE); \ } -#define ADD_TEST_SUITE_PROTECTED_PVK(KEYTYPE) \ - ADD_TEST(test_protected_##KEYTYPE##_via_PVK) +#define ADD_TEST_SUITE_PROTECTED_PVK(KEYTYPE) \ + do { \ + if (key_##KEYTYPE != NULL) \ + ADD_TEST(test_protected_##KEYTYPE##_via_PVK); \ + } while (0) #endif #ifndef OPENSSL_NO_DH @@ -1010,6 +1173,7 @@ DOMAIN_KEYS(EC); IMPLEMENT_TEST_SUITE(EC, "EC", 1) IMPLEMENT_TEST_SUITE_PARAMS(EC, "EC") IMPLEMENT_TEST_SUITE_LEGACY(EC, "EC") +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES DOMAIN_KEYS(ECExplicitPrimeNamedCurve); IMPLEMENT_TEST_SUITE(ECExplicitPrimeNamedCurve, "EC", 1) IMPLEMENT_TEST_SUITE_LEGACY(ECExplicitPrimeNamedCurve, "EC") @@ -1024,6 +1188,7 @@ DOMAIN_KEYS(ECExplicitTri2G); IMPLEMENT_TEST_SUITE(ECExplicitTri2G, "EC", 0) IMPLEMENT_TEST_SUITE_LEGACY(ECExplicitTri2G, "EC") #endif +#endif /* OPENSSL_NO_EC_EXPLICIT_CURVES */ #ifndef OPENSSL_NO_SM2 KEYS(SM2); IMPLEMENT_TEST_SUITE(SM2, "SM2", 0) @@ -1106,6 +1271,7 @@ IMPLEMENT_TEST_SUITE(ML_DSA_87, "ML-DSA-87", 1) #endif /* OPENSSL_NO_ML_DSA */ #ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES /* Explicit parameters that match a named curve */ static int do_create_ec_explicit_prime_params(OSSL_PARAM_BLD *bld, const unsigned char *gen, @@ -1286,6 +1452,7 @@ static int create_ec_explicit_trinomial_params(OSSL_PARAM_BLD *bld) return do_create_ec_explicit_trinomial_params(bld, gen2, sizeof(gen2)); } #endif /* OPENSSL_NO_EC2M */ +#endif /* OPENSSL_NO_EC_EXPLICIT_CURVES */ /* * Test that multiple calls to OSSL_ENCODER_to_data() do not cause side effects @@ -1425,8 +1592,10 @@ int setup_tests(void) return 0; #ifndef OPENSSL_NO_EC - if (!TEST_ptr(bnctx = BN_CTX_new_ex(testctx)) - || !TEST_ptr(bld_prime_nc = OSSL_PARAM_BLD_new()) + if (!TEST_ptr(bnctx = BN_CTX_new_ex(testctx))) + return 0; +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES + if (!TEST_ptr(bld_prime_nc = OSSL_PARAM_BLD_new()) || !TEST_ptr(bld_prime = OSSL_PARAM_BLD_new()) || !create_ec_explicit_prime_params_namedcurve(bld_prime_nc) || !create_ec_explicit_prime_params(bld_prime) @@ -1442,6 +1611,7 @@ int setup_tests(void) #endif ) return 0; +#endif /* OPENSSL_NO_EC_EXPLICIT_CURVES */ #endif TEST_info("Generating keys..."); @@ -1458,12 +1628,14 @@ int setup_tests(void) #ifndef OPENSSL_NO_EC TEST_info("Generating EC keys..."); MAKE_DOMAIN_KEYS(EC, "EC", EC_params); +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES MAKE_DOMAIN_KEYS(ECExplicitPrimeNamedCurve, "EC", ec_explicit_prime_params_nc); MAKE_DOMAIN_KEYS(ECExplicitPrime2G, "EC", ec_explicit_prime_params_explicit); #ifndef OPENSSL_NO_EC2M MAKE_DOMAIN_KEYS(ECExplicitTriNamedCurve, "EC", ec_explicit_tri_params_nc); MAKE_DOMAIN_KEYS(ECExplicitTri2G, "EC", ec_explicit_tri_params_explicit); #endif +#endif /* OPENSSL_NO_EC_EXPLICIT_CURVES */ #ifndef OPENSSL_NO_SM2 MAKE_KEYS(SM2, "SM2", NULL); #endif @@ -1506,12 +1678,17 @@ int setup_tests(void) #endif /* OPENSSL_NO_SLH_DSA */ TEST_info("Loading RSA key..."); - ok = ok && TEST_ptr(key_RSA = load_pkey_pem(rsa_file, keyctx)); + ok &= TEST_ptr(key_RSA = load_pkey_pem(rsa_file, keyctx)); TEST_info("Loading RSA_PSS key..."); - ok = ok && TEST_ptr(key_RSA_PSS = load_pkey_pem(rsa_pss_file, keyctx)); + ok &= TEST_ptr(key_RSA_PSS = load_pkey_pem(rsa_pss_file, keyctx)); TEST_info("Generating keys done"); - if (ok) { + /* + * Register every test whose key was successfully generated. The + * per-algorithm key_##KEYTYPE != NULL guard inside each + * ADD_TEST_SUITE* macro keeps us from referencing missing keys. + */ + { #ifndef OPENSSL_NO_DH ADD_TEST_SUITE(DH); ADD_TEST_SUITE_PARAMS(DH); @@ -1537,6 +1714,7 @@ int setup_tests(void) ADD_TEST_SUITE(EC); ADD_TEST_SUITE_PARAMS(EC); ADD_TEST_SUITE_LEGACY(EC); +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES ADD_TEST_SUITE(ECExplicitPrimeNamedCurve); ADD_TEST_SUITE_LEGACY(ECExplicitPrimeNamedCurve); ADD_TEST_SUITE(ECExplicitPrime2G); @@ -1547,6 +1725,7 @@ int setup_tests(void) ADD_TEST_SUITE(ECExplicitTri2G); ADD_TEST_SUITE_LEGACY(ECExplicitTri2G); #endif +#endif /* OPENSSL_NO_EC_EXPLICIT_CURVES */ #ifndef OPENSSL_NO_SM2 if (!is_fips_3_0_0) { /* 3.0.0 FIPS provider imports explicit EC params and then fails. */ @@ -1610,12 +1789,13 @@ int setup_tests(void) #endif /* OPENSSL_NO_SLH_DSA */ } - return 1; + return ok; } void cleanup_tests(void) { #ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES OSSL_PARAM_free(ec_explicit_prime_params_nc); OSSL_PARAM_free(ec_explicit_prime_params_explicit); OSSL_PARAM_BLD_free(bld_prime_nc); @@ -1626,6 +1806,7 @@ void cleanup_tests(void) OSSL_PARAM_BLD_free(bld_tri_nc); OSSL_PARAM_BLD_free(bld_tri); #endif +#endif /* OPENSSL_NO_EC_EXPLICIT_CURVES */ BN_CTX_free(bnctx); #endif /* OPENSSL_NO_EC */ @@ -1638,12 +1819,14 @@ void cleanup_tests(void) #endif #ifndef OPENSSL_NO_EC FREE_DOMAIN_KEYS(EC); +#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES FREE_DOMAIN_KEYS(ECExplicitPrimeNamedCurve); FREE_DOMAIN_KEYS(ECExplicitPrime2G); #ifndef OPENSSL_NO_EC2M FREE_DOMAIN_KEYS(ECExplicitTriNamedCurve); FREE_DOMAIN_KEYS(ECExplicitTri2G); #endif +#endif /* OPENSSL_NO_EC_EXPLICIT_CURVES */ #ifndef OPENSSL_NO_SM2 FREE_KEYS(SM2); #endif From f9ba3e7cc508cd506b152b3addde72090a9c8b54 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Sun, 24 May 2026 23:47:19 +1000 Subject: [PATCH 043/189] DH: harden empty fromdata EVP_PKEY_fromdata for DH/DHX accepts an empty array and yields a DH with NULL params.p / params.g. Several DH check entry points (DH_check, DH_check_params, DH_check_pub_key) then read dh->params.p / .g via BN_num_bits or BN_is_odd before any NULL check. Add defensive guards at the top of each that report failure via *ret without dereferencing NULL; the existing return-1-with-flags contract is preserved. A new test_fromdata in endecode_test drives every supported keymgmt with an empty OSSL_PARAM[] for both EVP_PKEY_PUBLIC_KEY and EVP_PKEY_KEYPAIR selections, and tests that any returned key is sufficiently well behaved. Reviewed-by: Nikola Pajkovsky Reviewed-by: Bob Beck MergeDate: Thu Jun 25 02:09:51 2026 (Merged from https://github.com/openssl/openssl/pull/31253) --- crypto/dh/dh_check.c | 22 ++++ test/endecode_test.c | 261 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 283 insertions(+) diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 3002609b68f5e..96256f9283487 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -74,6 +74,14 @@ int DH_check_params(const DH *dh, int *ret) BN_CTX *ctx = NULL; *ret = 0; + /* + * A DH with no modulus or generator cannot be checked. Report + * the failure via |*ret| rather than dereferencing NULL below. + */ + if (dh->params.p == NULL || dh->params.g == NULL) { + *ret = DH_NOT_SUITABLE_GENERATOR | DH_CHECK_P_NOT_PRIME; + return 1; + } ctx = BN_CTX_new_ex(dh->libctx); if (ctx == NULL) goto err; @@ -150,6 +158,11 @@ int DH_check(const DH *dh, int *ret) int nid = DH_get_nid((DH *)dh); *ret = 0; + /* A DH with no modulus or generator cannot be checked. */ + if (dh->params.p == NULL || dh->params.g == NULL) { + *ret = DH_NOT_SUITABLE_GENERATOR | DH_CHECK_P_NOT_PRIME; + return 1; + } if (nid != NID_undef) return 1; @@ -250,6 +263,15 @@ int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key) */ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { + *ret = 0; + /* + * Without a modulus we cannot check anything; signal failure via + * |*ret| rather than crashing in BN_num_bits below. + */ + if (dh->params.p == NULL) { + *ret = DH_CHECK_PUBKEY_INVALID; + return 1; + } /* Don't do any checks at all with an excessively large modulus */ if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) { ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); diff --git a/test/endecode_test.c b/test/endecode_test.c index e523e1bff643d..64701d32b86f8 100644 --- a/test/endecode_test.c +++ b/test/endecode_test.c @@ -1004,6 +1004,254 @@ static int test_dup(const char *type, EVP_PKEY *key) return ok; } +/* + * Drive EVP_PKEY_fromdata with the supplied OSSL_PARAM[] (NULL = + * empty array) for the given selection. Either outcome is accepted: + * fromdata may reject the input, or it may succeed and yield a key + * with at most algorithm-bound parameters. In the success case a + * battery of common consumer ops must not crash on the resulting + * key; their return values are not asserted. + */ +static int run_empty_fromdata_probe(const char *type, EVP_PKEY_CTX *cctx, + int selection, OSSL_PARAM *params, const char *selname) +{ + EVP_PKEY *pkey = NULL; + OSSL_PARAM empty[1]; + int r; + int ok = 0; + + if (params == NULL) { + empty[0] = OSSL_PARAM_construct_end(); + params = empty; + } + + if (!TEST_int_gt(EVP_PKEY_fromdata_init(cctx), 0)) { + TEST_info("%s: fromdata_init failed (%s)", type, selname); + goto end; + } + r = EVP_PKEY_fromdata(cctx, &pkey, selection, params); + if (r <= 0) { + /* Rejection is fine, but the out-pointer must remain NULL. */ + if (!TEST_ptr_null(pkey)) { + TEST_info("%s: fromdata returned %d but pkey != NULL (%s)", + type, r, selname); + goto end; + } + ok = 1; + goto end; + } + if (!TEST_ptr(pkey)) { + TEST_info("%s: fromdata returned %d but pkey == NULL (%s)", + type, r, selname); + goto end; + } + /* + * Walk a battery of common consumer ops on the resulting key. + * Their return values are not asserted - a contentless key may + * fail every op - only crashing is forbidden. + */ + (void)EVP_PKEY_get_bits(pkey); + (void)EVP_PKEY_get_security_bits(pkey); + (void)EVP_PKEY_get_size(pkey); + (void)EVP_PKEY_eq(pkey, pkey); + (void)EVP_PKEY_parameters_eq(pkey, pkey); + { + OSSL_PARAM *out = NULL; + + if (EVP_PKEY_todata(pkey, selection, &out) > 0) + OSSL_PARAM_free(out); + } + { + EVP_PKEY *clone = EVP_PKEY_dup(pkey); + + EVP_PKEY_free(clone); + } + { + BIO *bio = BIO_new(BIO_s_null()); + + if (bio != NULL) { + (void)EVP_PKEY_print_public(bio, pkey, 0, NULL); + (void)EVP_PKEY_print_private(bio, pkey, 0, NULL); + (void)EVP_PKEY_print_params(bio, pkey, 0, NULL); + BIO_free(bio); + } + } + { + /* The param/public/private/pairwise check family. */ + EVP_PKEY_CTX *vctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + + if (vctx != NULL) { + (void)EVP_PKEY_param_check(vctx); + (void)EVP_PKEY_param_check_quick(vctx); + (void)EVP_PKEY_public_check(vctx); + (void)EVP_PKEY_public_check_quick(vctx); + (void)EVP_PKEY_private_check(vctx); + (void)EVP_PKEY_pairwise_check(vctx); + EVP_PKEY_CTX_free(vctx); + } + } + ok = 1; +end: + EVP_PKEY_free(pkey); + return ok; +} + +static int probe_empty_fromdata(const char *type, EVP_PKEY *prototype, + int selection, const char *selname) +{ + EVP_PKEY_CTX *cctx = NULL; + int ok = 0; + + if (!TEST_ptr(cctx = EVP_PKEY_CTX_new_from_pkey(NULL, prototype, NULL))) { + TEST_info("%s: CTX alloc failed for empty fromdata (%s)", + type, selname); + goto end; + } + ok = run_empty_fromdata_probe(type, cctx, selection, NULL, selname); +end: + EVP_PKEY_CTX_free(cctx); + return ok; +} + +/* + * Drive EVP_PKEY_fromdata with an empty OSSL_PARAM[] for both + * EVP_PKEY_PUBLIC_KEY and EVP_PKEY_KEYPAIR selections. Either + * outcome is acceptable: fromdata rejects, or it succeeds and the + * resulting key survives the consumer-op battery without crashing. + */ +static int test_fromdata(const char *type, EVP_PKEY *prototype) +{ + if (!TEST_ptr(prototype)) { + TEST_info("%s: no prototype key", type); + return 0; + } + if (!probe_empty_fromdata(type, prototype, EVP_PKEY_PUBLIC_KEY, + "EVP_PKEY_PUBLIC_KEY")) + return 0; + if (!probe_empty_fromdata(type, prototype, EVP_PKEY_KEYPAIR, + "EVP_PKEY_KEYPAIR")) + return 0; + return 1; +} + +/* + * Named-group-only partial-shape variants for prototype-matrix + * algorithms, plus any keymgmts without a keygen path. Each entry + * is one (name, selection, params-builder) shape; a NULL builder + * means "use an empty OSSL_PARAM[]". Algorithms not loadable under + * the active provider set are silently skipped. + */ +typedef int (*fromdata_shape_build_fn)(OSSL_PARAM_BLD *bld); + +struct fromdata_shape { + const char *name; /* keymgmt algorithm name */ + int selection; /* EVP_PKEY_PUBLIC_KEY / KEYPAIR / etc. */ + fromdata_shape_build_fn build; /* NULL -> empty OSSL_PARAM[] */ + const char *label; /* diagnostic label */ +}; + +#ifndef OPENSSL_NO_DH +static int build_dh_named_group(OSSL_PARAM_BLD *bld) +{ + return OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, + "ffdhe2048", 0); +} +#endif + +#ifndef OPENSSL_NO_EC +static int build_ec_named_group(OSSL_PARAM_BLD *bld) +{ + return OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, + "P-256", 0); +} +#ifndef OPENSSL_NO_SM2 +static int build_sm2_named_group(OSSL_PARAM_BLD *bld) +{ + return OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, + "SM2", 0); +} +#endif +#endif + +#if defined(OPENSSL_NO_DH) && defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_SM2) +#undef TEST_FROMDATA_NO_KEYGEN +#else +#define TEST_FROMDATA_NO_KEYGEN + +static const struct fromdata_shape no_keygen_shapes[] = { +/* Named-group-only partial shapes. */ +#ifndef OPENSSL_NO_DH + { "DH", EVP_PKEY_KEYPAIR, build_dh_named_group, + "DH / named group only / KEYPAIR" }, + { "DH", EVP_PKEY_PUBLIC_KEY, build_dh_named_group, + "DH / named group only / PUBLIC_KEY" }, +#endif +#ifndef OPENSSL_NO_EC + { "EC", EVP_PKEY_KEYPAIR, build_ec_named_group, + "EC / group only / KEYPAIR" }, + { "EC", EVP_PKEY_PUBLIC_KEY, build_ec_named_group, + "EC / group only / PUBLIC_KEY" }, +#ifndef OPENSSL_NO_SM2 + { "SM2", EVP_PKEY_KEYPAIR, build_sm2_named_group, + "SM2 / group only / KEYPAIR" }, +#endif +#endif +}; + +/* + * Probe an algorithm by name rather than a prototype key, for keymgmts without + * a keygen path. Algorithms not loadable under the active provider set are + * silently skipped. |params| may be NULL (= empty OSSL_PARAM[]) or a + * caller-built partial array. + */ +static int probe_fromdata_by_name(const char *name, int selection, + OSSL_PARAM *params, const char *selname) +{ + EVP_PKEY_CTX *cctx = NULL; + int ok = 1; + + cctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL); + if (cctx == NULL) + return 1; + ok = run_empty_fromdata_probe(name, cctx, selection, params, selname); + EVP_PKEY_CTX_free(cctx); + return ok; +} + +static int test_fromdata_no_keygen(void) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(no_keygen_shapes); i++) { + const struct fromdata_shape *s = &no_keygen_shapes[i]; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + int ok; + + if (s->build != NULL) { + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())) + return 0; + if (!s->build(bld)) { + TEST_info("%s: builder failed", s->label); + OSSL_PARAM_BLD_free(bld); + return 0; + } + params = OSSL_PARAM_BLD_to_param(bld); + if (!TEST_ptr(params)) { + OSSL_PARAM_BLD_free(bld); + return 0; + } + } + ok = probe_fromdata_by_name(s->name, s->selection, params, s->label); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + if (!ok) + return 0; + } + return 1; +} +#endif + #define KEYS(KEYTYPE) \ static EVP_PKEY *key_##KEYTYPE = NULL #define MAKE_KEYS(KEYTYPE, KEYTYPEstr, params) \ @@ -1053,6 +1301,10 @@ static int test_dup(const char *type, EVP_PKEY *key) static int test_dup_##KEYTYPE(void) \ { \ return test_dup(KEYTYPEstr, key_##KEYTYPE); \ + } \ + static int test_fromdata_##KEYTYPE(void) \ + { \ + return test_fromdata(KEYTYPEstr, key_##KEYTYPE); \ } #define ADD_TEST_SUITE(KEYTYPE) \ @@ -1065,6 +1317,7 @@ static int test_dup(const char *type, EVP_PKEY *key) ADD_TEST(test_public_##KEYTYPE##_via_DER); \ ADD_TEST(test_public_##KEYTYPE##_via_PEM); \ ADD_TEST(test_dup_##KEYTYPE); \ + ADD_TEST(test_fromdata_##KEYTYPE); \ } \ } while (0) @@ -1787,6 +2040,14 @@ int setup_tests(void) ADD_TEST_SUITE(SLH_DSA_SHAKE_256f); } #endif /* OPENSSL_NO_SLH_DSA */ + + /* + * Named-group-only partial shapes for DH and EC/SM2. Each + * shape is silently skipped if the algorithm is not loadable. + */ +#ifdef TEST_FROMDATA_NO_KEYGEN + ADD_TEST(test_fromdata_no_keygen); +#endif } return ok; From 5898e2fec76d35f922d9a8a6ca46ea9b1881f2d1 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Tue, 23 Jun 2026 11:05:18 +0200 Subject: [PATCH 044/189] crypto/armcap.c: reformat MIDR CPU-model conditionals for readability break long chain of MIDR_IS_CPU_MODEL() alternatives packed onto a single line, which was effectively unreadable and impossible to review or diff one model at a time. move the OPENSSL_armcap_P feature-flag test to the front of the expression so the guard is obvious before the model list. This is a formatting-only change. Signed-off-by: Nikola Pajkovsky Reviewed-by: Eugene Syromiatnikov Reviewed-by: Bob Beck MergeDate: Thu Jun 25 06:18:39 2026 (Merged from https://github.com/openssl/openssl/pull/31664) --- crypto/armcap.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/crypto/armcap.c b/crypto/armcap.c index 03e47dc5bbfb0..754d2674a85ff 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -408,14 +408,49 @@ void OPENSSL_cpuid_setup(void) if (OPENSSL_armcap_P & ARMV8_CPUID) OPENSSL_arm_midr = _armv8_cpuid_probe(); - if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N1)) && (OPENSSL_armcap_P & ARMV7_NEON)) { + if ((OPENSSL_armcap_P & ARMV7_NEON) + && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N1))) OPENSSL_armv8_rsa_neonized = 1; - } - if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_COBALT_100) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE) && (OPENSSL_armcap_P & ARMV8_SHA3)) + + if ((OPENSSL_armcap_P & ARMV8_SHA3) + && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_COBALT_100) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) + || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE)) OPENSSL_armcap_P |= ARMV8_UNROLL8_EOR3; - if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE) && (OPENSSL_armcap_P & ARMV8_SHA3)) + + if ((OPENSSL_armcap_P & ARMV8_SHA3) + && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) + || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS))) OPENSSL_armcap_P |= ARMV8_UNROLL12_EOR3; - if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX)) && (OPENSSL_armcap_P & ARMV8_SHA3)) + + if ((OPENSSL_armcap_P & ARMV8_SHA3) + && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS))) OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING; #endif } From 54686a9dc99c9ebadfbf2397f3ed52264226f0c0 Mon Sep 17 00:00:00 2001 From: Daniel Kubec Date: Tue, 23 Jun 2026 14:10:45 +0200 Subject: [PATCH 045/189] AEAD: reject late AAD in ChaCha20-Poly1305 after plaintext update Align behavior with AES GCM, which already rejects this misuse with a hard error, by tracking whether plaintext processing has started and returning an error if AAD is supplied afterwards. Fixes #31188 Reviewed-by: Tomas Mraz Reviewed-by: Bob Beck MergeDate: Thu Jun 25 07:02:29 2026 (Merged from https://github.com/openssl/openssl/pull/31673) --- .../ciphers/cipher_chacha20_poly1305_hw.c | 2 ++ test/evp_extra_test.c | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c index 733547a7e7323..0f9027a7d12b2 100644 --- a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c +++ b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c @@ -301,6 +301,8 @@ static int chacha20_poly1305_aead_cipher(PROV_CIPHER_CTX *bctx, if (in != NULL) { /* aad or text */ if (out == NULL) { /* aad */ + if (ctx->len.text != 0) + goto err; Poly1305_Update(poly, in, inl); ctx->len.aad += inl; ctx->aad = 1; diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 80a133dd7f1d7..bdf2f5bbb441a 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -6711,6 +6711,30 @@ static int test_aes_gcm_siv_empty_data(void) return ret; } +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) +static int test_chacha20_poly1305_late_aad(void) +{ + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER *c = NULL; + unsigned char key[32] = { 0 }; + unsigned char iv[12] = { 0 }; + unsigned char aad[4] = "aad"; + unsigned char msg[8] = "message"; + unsigned char out[32]; + int len, test; + + test = TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + && TEST_ptr(c = EVP_CIPHER_fetch(testctx, "ChaCha20-Poly1305", testpropq)) + && TEST_true(EVP_EncryptInit_ex2(ctx, c, key, iv, NULL)) + && TEST_true(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad))) + && TEST_true(EVP_EncryptUpdate(ctx, out, &len, msg, sizeof(msg))) + && TEST_false(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad))); + + EVP_CIPHER_free(c); + EVP_CIPHER_CTX_free(ctx); + return test; +} +#endif /* * AES-SIV reuse-without-rekey: * msg1: legit non-empty CT, tag verifies, final_ret=0 @@ -7482,6 +7506,7 @@ int setup_tests(void) #endif #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) ADD_TEST(test_decrypt_null_chunks); + ADD_TEST(test_chacha20_poly1305_late_aad); #endif #ifndef OPENSSL_NO_DH ADD_TEST(test_DH_priv_pub); From e549ff518114e691910dbdf1c3714c1bbf3030bf Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Mon, 22 Jun 2026 07:56:45 +0200 Subject: [PATCH 046/189] rec_layer_s3.c: prevent max_early_data overflow in ossl_early_data_count_ok() Apply change similar to the one made in d41a9225196b "tls_common.c: prevent max_early_data overflow in rlayer_early_data_count_ok()" to ossl_early_data_count_ok(), that has similar logic in it (as rlayer_early_data_count_ok() has been copied from ossl_early_data_count_ok() in 9dd90232d537 "Move early data counting out of the SSL object and into the record layer"). Complements: d41a9225196b "tls_common.c: prevent max_early_data overflow in rlayer_early_data_count_ok()" Fixes: 70ef40a05e06 "Check max_early_data against the amount of early data we actually receive" Signed-off-by: Eugene Syromiatnikov Reviewed-by: Paul Dale Reviewed-by: Daniel Kubec MergeDate: Thu Jun 25 07:13:53 2026 (Merged from https://github.com/openssl/openssl/pull/31628) --- ssl/record/rec_layer_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index ba407478b4121..71cedd641b652 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -150,7 +150,7 @@ static uint32_t ossl_get_max_early_data(SSL_CONNECTION *s) static int ossl_early_data_count_ok(SSL_CONNECTION *s, size_t length, size_t overhead, int send) { - uint32_t max_early_data; + uint64_t max_early_data; max_early_data = ossl_get_max_early_data(s); From 8fed0d2d53fdc1194b738e4465cc546e969df1d9 Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Tue, 23 Jun 2026 09:48:25 +0200 Subject: [PATCH 047/189] crypto/ctype.c: fix off-by-one OOB in ossl_toascii()/ossl_fromascii() Incorrect check for the upper bound allowed the value of 256 to slip through, which could lead to OOB read one element beyound the end of the os_toascii/os_toebcdic arrays. Fix that by changing the comparison with 256 from strictly great to great-or-equal. Found by cppcheck. Fixes: a1df06b36347 "This has been added to avoid the situation where some host ctype.h functions return true for characters > 127. I.e. they are allowing extended ASCII characters through which then cause problems. E.g. marking superscript '2' as a number then causes the common (ch - '0') conversion to number to fail miserably. Likewise letters with diacritical marks can also cause problems." Signed-off-by: Eugene Syromiatnikov Reviewed-by: Nikola Pajkovsky Reviewed-by: Daniel Kubec MergeDate: Thu Jun 25 07:20:42 2026 (Merged from https://github.com/openssl/openssl/pull/31661) --- crypto/ctype.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/ctype.c b/crypto/ctype.c index 686fe64165fcb..75192b11f4af7 100644 --- a/crypto/ctype.c +++ b/crypto/ctype.c @@ -226,7 +226,7 @@ static const unsigned short ctype_char_map[128] = { #ifdef CHARSET_EBCDIC int ossl_toascii(int c) { - if (c < -128 || c > 256 || c == EOF) + if (c < -128 || c >= 256 || c == EOF) return c; /* * Adjust negatively signed characters. @@ -241,7 +241,7 @@ int ossl_toascii(int c) int ossl_fromascii(int c) { - if (c < -128 || c > 256 || c == EOF) + if (c < -128 || c >= 256 || c == EOF) return c; if (c < 0) c += 256; From 9a2836b3e79fe396baf731ca664b9f616aa01a4c Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Mon, 22 Jun 2026 19:46:51 +0200 Subject: [PATCH 048/189] CONTRIBUTING.md: tweak wording with regards to ML tooling usage ML tools do not satisfy the authorship requirement, so they are merely used, and not "create" on their own. Signed-off-by: Eugene Syromiatnikov Reviewed-by: Paul Dale Reviewed-by: Kurt Roeckx MergeDate: Thu Jun 25 07:23:04 2026 (Merged from https://github.com/openssl/openssl/pull/31643) --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 46b35fafa91eb..8a0d40524ddbd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,12 +71,12 @@ guidelines: ``` 2. Similarly, if a non-trivial portion of a contribution was created - by an AI, you must declare which agent and model were used. This - is done by adding `Assisted-by: {agent}:{model}` below the commit + using an AI tool, you must declare which agent and model were used. + This is done by adding `Assisted-by: {agent}:{model}` below the commit message: ``` - One-line summary of change with AI-created portions + One-line summary of change with AI-generated portions Assisted-by: Claude:claude-sonnet-4-6 ``` From 1e08c5223873c352d47e29505de283b7b0ac7b7a Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Thu, 25 Jun 2026 11:14:17 +0200 Subject: [PATCH 049/189] Fix incorrect backport of "crypto/armcap.c: reformat MIDR CPU-model conditionals for readability" Backport of commit d681e8b6bf09 "crypto/armcap.c: reformat MIDR CPU-model conditionals for readability" has introduced checks that were not there before, fix that. Fixes: 5898e2fec76d ("crypto/armcap.c: reformat MIDR CPU-model conditionals for readability") Signed-off-by: Nikola Pajkovsky Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Thu Jun 25 12:17:34 2026 (Merged from https://github.com/openssl/openssl/pull/31724) --- crypto/armcap.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/crypto/armcap.c b/crypto/armcap.c index 754d2674a85ff..345d600fcd6cd 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -416,24 +416,15 @@ void OPENSSL_cpuid_setup(void) if ((OPENSSL_armcap_P & ARMV8_SHA3) && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_COBALT_100) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE)) OPENSSL_armcap_P |= ARMV8_UNROLL8_EOR3; if ((OPENSSL_armcap_P & ARMV8_SHA3) && (MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3_AE) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N3) - || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS))) + || MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE)) OPENSSL_armcap_P |= ARMV8_UNROLL12_EOR3; if ((OPENSSL_armcap_P & ARMV8_SHA3) @@ -448,9 +439,7 @@ void OPENSSL_cpuid_setup(void) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO) || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_QCOMM, QCOM_CPU_PART_ORYON_X1) - || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS))) + || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX))) OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING; #endif } From 36bc0b5621f63fbfd0d082b6c85be564a2a67b6e Mon Sep 17 00:00:00 2001 From: 007bsd <22483432+007bsd@users.noreply.github.com> Date: Tue, 23 Jun 2026 21:42:29 +0300 Subject: [PATCH 050/189] crypto/x509/pcy_cache.c: fix ext_pcons leak in policy_cache_new() Two early-return paths in policy_cache_new() bypass the just_cleanup: label and leak the POLICY_CONSTRAINTS object ext_pcons: (1) when certificatePolicies is absent but policyConstraints is present, and (2) when policy_cache_create() returns <= 0. Free ext_pcons before each early return. Assisted-by: Claude:claude-sonnet-4-6 CLA: trivial Fixes: 4acc3e907d29 "Initial support for certificate policy checking and evaluation." Reviewed-by: Tomas Mraz Reviewed-by: Nikola Pajkovsky Reviewed-by: Eugene Syromiatnikov MergeDate: Fri Jun 26 15:26:07 2026 (Merged from https://github.com/openssl/openssl/pull/31678) (cherry picked from commit 1f5a44a66df44751d999fc90751ce098975f18a6) --- crypto/x509/pcy_cache.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crypto/x509/pcy_cache.c b/crypto/x509/pcy_cache.c index d1ee35377bda3..bffa96fd6c51d 100644 --- a/crypto/x509/pcy_cache.c +++ b/crypto/x509/pcy_cache.c @@ -134,6 +134,7 @@ static int policy_cache_new(X509 *x) /* If not absent some problem with extension */ if (i != -1) goto bad_cache; + POLICY_CONSTRAINTS_free(ext_pcons); return 1; } @@ -141,8 +142,10 @@ static int policy_cache_new(X509 *x) /* NB: ext_cpols freed by policy_cache_set_policies */ - if (i <= 0) + if (i <= 0) { + POLICY_CONSTRAINTS_free(ext_pcons); return i; + } ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); From 67db947764922f38b93aac48083fbeacc8f63565 Mon Sep 17 00:00:00 2001 From: 007bsd <22483432+007bsd@users.noreply.github.com> Date: Tue, 23 Jun 2026 21:42:33 +0300 Subject: [PATCH 051/189] crypto/x509/v3_ncons.c: fix scheme buffer leak in nc_uri() for schemeless URIs OSSL_parse_url() allocates a 1-byte empty-string buffer for the scheme even when the URI has no scheme. The empty-scheme error branch freed uri_copy and jumped to end: which only frees host, leaving scheme unfreed. Add OPENSSL_free(scheme) before the goto. Assisted-by: Claude:claude-sonnet-4-6 CLA: trivial Fixes: e599893a9fec "x509: allow SAN URIs to contain userinfo" Reviewed-by: Tomas Mraz Reviewed-by: Nikola Pajkovsky Reviewed-by: Eugene Syromiatnikov MergeDate: Fri Jun 26 15:26:09 2026 (Merged from https://github.com/openssl/openssl/pull/31678) (cherry picked from commit 8be7309f34eecac16b23edfa2ea8de7c52a33b3d) --- crypto/x509/v3_ncons.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c index 2d4b23685b0e0..1af2c8682046d 100644 --- a/crypto/x509/v3_ncons.c +++ b/crypto/x509/v3_ncons.c @@ -789,6 +789,7 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) if (scheme == NULL || *scheme == '\0') { ERR_raise_data(ERR_LIB_X509V3, X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, "x509: missing scheme in URI: %s\n", uri_copy); + OPENSSL_free(scheme); OPENSSL_free(uri_copy); ret = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; goto end; From 91a82efa1686be8f8d7f80b76a5bdf481cc037ff Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Wed, 24 Jun 2026 14:17:15 +0200 Subject: [PATCH 052/189] .github/workflows: add backport.yml from master So it is run when a PR targets multiple stable branches. Signed-off-by: Eugene Syromiatnikov Reviewed-by: Bob Beck Reviewed-by: Norbert Pocs MergeDate: Fri Jun 26 16:45:36 2026 (Merged from https://github.com/openssl/openssl/pull/31703) --- .github/workflows/backport.yml | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 0000000000000..86a53a2abaebb --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,64 @@ +# Copyright 2021-2026 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 + +name: Backports CI + +on: [pull_request] + +permissions: + contents: read + +jobs: + check_backports: + strategy: + fail-fast: false + matrix: + release: [ + { + branch: '4.0', + cppflags: '' + }, { + branch: '3.6', + cppflags: '' + }, { + branch: '3.5', + cppflags: 'CPPFLAGS=-ansi' + }, { + branch: '3.4', + cppflags: 'CPPFLAGS=-ansi' + }, { + branch: '3.0', + cppflags: 'CPPFLAGS=-ansi' + } + ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + if: ${{ contains(join(github.event.pull_request.labels.*.name,','),matrix.release.branch) }} + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + persist-credentials: false + - name: cherry-pick + if: ${{ contains(join(github.event.pull_request.labels.*.name,','),matrix.release.branch) }} + run: | + REFEND=$(git rev-parse HEAD) + REFSTART=$(git rev-parse $REFEND~${{ github.event.pull_request.commits }}) + git checkout ${{ format('openssl-{0}', matrix.release.branch) }} + git config user.name "OpenSSL Machine" + git config user.email "openssl-machine@openssl.org" + echo Cherry-picking $REFSTART..$REFEND + git cherry-pick $REFSTART..$REFEND || { git diff | head -n1000; exit 1; } + - name: config + if: ${{ contains(join(github.event.pull_request.labels.*.name,','),matrix.release.branch) }} + run: ${{ matrix.release.cppflags }} ./config --strict-warnings --banner=Configured no-asm enable-fips --strict-warnings -D_DEFAULT_SOURCE && perl configdata.pm --dump + - name: make + if: ${{ contains(join(github.event.pull_request.labels.*.name,','),matrix.release.branch) }} + run: make -s -j4 + - name: make test + if: ${{ contains(join(github.event.pull_request.labels.*.name,','),matrix.release.branch) }} + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} From c8167c17c206a04efd5b81d52ee5a0d435178f9a Mon Sep 17 00:00:00 2001 From: Alicja Kario Date: Tue, 16 Jun 2026 17:12:14 +0200 Subject: [PATCH 053/189] test/evp_extra_test.c: add test case for CVE-2026-42770 Signed-off-by: Alicja Kario Reviewed-by: Igor Ustinov Reviewed-by: Dmitry Belyavskiy MergeDate: Wed Jun 24 11:56:27 2026 (cherry picked from commit 1cfec91eb67b82066ad493b1150c253231cc2a9f) Reviewed-by: Eugene Syromiatnikov (Merged from https://github.com/openssl/openssl/pull/31702) --- test/evp_extra_test.c | 252 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index bdf2f5bbb441a..9a5f8f9fddbcf 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -4333,6 +4333,257 @@ static int test_EVP_PKEY_set1_DH(void) return ret; } #endif /* !OPENSSL_NO_DEPRECATED_3_0 */ + +/* Test that DHX (X9.42) rejects a malicious peer key during the + * derivation phase (specifically EVP_PKEY_derive_set_peer) when the + * remote 'q' does not match the local domain parameters but is still + * consistent with the remote key share. + * (CVE-2026-42770) + */ +static int test_dhx_derive_rejects_bad_peer_q(void) +{ + int ret = 0; + EVP_PKEY *local_key = NULL, *remote_key = NULL; + EVP_PKEY_CTX *pctx = NULL, *derive_ctx = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + + BIGNUM *p = NULL, *g = NULL; + BIGNUM *q_valid = NULL, *pub_local = NULL, *priv_local = NULL; + BIGNUM *q_bad = NULL, *pub_bad = NULL; + + static const unsigned char bin_p[] = { + 0x87, 0xa8, 0xe6, 0x1d, 0xb4, 0xb6, 0x66, 0x3c, + 0xff, 0xbb, 0xd1, 0x9c, 0x65, 0x19, 0x59, 0x99, + 0x8c, 0xee, 0xf6, 0x08, 0x66, 0x0d, 0xd0, 0xf2, + 0x5d, 0x2c, 0xee, 0xd4, 0x43, 0x5e, 0x3b, 0x00, + 0xe0, 0x0d, 0xf8, 0xf1, 0xd6, 0x19, 0x57, 0xd4, + 0xfa, 0xf7, 0xdf, 0x45, 0x61, 0xb2, 0xaa, 0x30, + 0x16, 0xc3, 0xd9, 0x11, 0x34, 0x09, 0x6f, 0xaa, + 0x3b, 0xf4, 0x29, 0x6d, 0x83, 0x0e, 0x9a, 0x7c, + 0x20, 0x9e, 0x0c, 0x64, 0x97, 0x51, 0x7a, 0xbd, + 0x5a, 0x8a, 0x9d, 0x30, 0x6b, 0xcf, 0x67, 0xed, + 0x91, 0xf9, 0xe6, 0x72, 0x5b, 0x47, 0x58, 0xc0, + 0x22, 0xe0, 0xb1, 0xef, 0x42, 0x75, 0xbf, 0x7b, + 0x6c, 0x5b, 0xfc, 0x11, 0xd4, 0x5f, 0x90, 0x88, + 0xb9, 0x41, 0xf5, 0x4e, 0xb1, 0xe5, 0x9b, 0xb8, + 0xbc, 0x39, 0xa0, 0xbf, 0x12, 0x30, 0x7f, 0x5c, + 0x4f, 0xdb, 0x70, 0xc5, 0x81, 0xb2, 0x3f, 0x76, + 0xb6, 0x3a, 0xca, 0xe1, 0xca, 0xa6, 0xb7, 0x90, + 0x2d, 0x52, 0x52, 0x67, 0x35, 0x48, 0x8a, 0x0e, + 0xf1, 0x3c, 0x6d, 0x9a, 0x51, 0xbf, 0xa4, 0xab, + 0x3a, 0xd8, 0x34, 0x77, 0x96, 0x52, 0x4d, 0x8e, + 0xf6, 0xa1, 0x67, 0xb5, 0xa4, 0x18, 0x25, 0xd9, + 0x67, 0xe1, 0x44, 0xe5, 0x14, 0x05, 0x64, 0x25, + 0x1c, 0xca, 0xcb, 0x83, 0xe6, 0xb4, 0x86, 0xf6, + 0xb3, 0xca, 0x3f, 0x79, 0x71, 0x50, 0x60, 0x26, + 0xc0, 0xb8, 0x57, 0xf6, 0x89, 0x96, 0x28, 0x56, + 0xde, 0xd4, 0x01, 0x0a, 0xbd, 0x0b, 0xe6, 0x21, + 0xc3, 0xa3, 0x96, 0x0a, 0x54, 0xe7, 0x10, 0xc3, + 0x75, 0xf2, 0x63, 0x75, 0xd7, 0x01, 0x41, 0x03, + 0xa4, 0xb5, 0x43, 0x30, 0xc1, 0x98, 0xaf, 0x12, + 0x61, 0x16, 0xd2, 0x27, 0x6e, 0x11, 0x71, 0x5f, + 0x69, 0x38, 0x77, 0xfa, 0xd7, 0xef, 0x09, 0xca, + 0xdb, 0x09, 0x4a, 0xe9, 0x1e, 0x1a, 0x15, 0x97 + }; + static const unsigned char bin_g[] = { + 0x3F, 0xB3, 0x2C, 0x9B, 0x73, 0x13, 0x4D, 0x0B, + 0x2E, 0x77, 0x50, 0x66, 0x60, 0xED, 0xBD, 0x48, + 0x4C, 0xA7, 0xB1, 0x8F, 0x21, 0xEF, 0x20, 0x54, + 0x07, 0xF4, 0x79, 0x3A, 0x1A, 0x0B, 0xA1, 0x25, + 0x10, 0xDB, 0xC1, 0x50, 0x77, 0xBE, 0x46, 0x3F, + 0xFF, 0x4F, 0xED, 0x4A, 0xAC, 0x0B, 0xB5, 0x55, + 0xBE, 0x3A, 0x6C, 0x1B, 0x0C, 0x6B, 0x47, 0xB1, + 0xBC, 0x37, 0x73, 0xBF, 0x7E, 0x8C, 0x6F, 0x62, + 0x90, 0x12, 0x28, 0xF8, 0xC2, 0x8C, 0xBB, 0x18, + 0xA5, 0x5A, 0xE3, 0x13, 0x41, 0x00, 0x0A, 0x65, + 0x01, 0x96, 0xF9, 0x31, 0xC7, 0x7A, 0x57, 0xF2, + 0xDD, 0xF4, 0x63, 0xE5, 0xE9, 0xEC, 0x14, 0x4B, + 0x77, 0x7D, 0xE6, 0x2A, 0xAA, 0xB8, 0xA8, 0x62, + 0x8A, 0xC3, 0x76, 0xD2, 0x82, 0xD6, 0xED, 0x38, + 0x64, 0xE6, 0x79, 0x82, 0x42, 0x8E, 0xBC, 0x83, + 0x1D, 0x14, 0x34, 0x8F, 0x6F, 0x2F, 0x91, 0x93, + 0xB5, 0x04, 0x5A, 0xF2, 0x76, 0x71, 0x64, 0xE1, + 0xDF, 0xC9, 0x67, 0xC1, 0xFB, 0x3F, 0x2E, 0x55, + 0xA4, 0xBD, 0x1B, 0xFF, 0xE8, 0x3B, 0x9C, 0x80, + 0xD0, 0x52, 0xB9, 0x85, 0xD1, 0x82, 0xEA, 0x0A, + 0xDB, 0x2A, 0x3B, 0x73, 0x13, 0xD3, 0xFE, 0x14, + 0xC8, 0x48, 0x4B, 0x1E, 0x05, 0x25, 0x88, 0xB9, + 0xB7, 0xD2, 0xBB, 0xD2, 0xDF, 0x01, 0x61, 0x99, + 0xEC, 0xD0, 0x6E, 0x15, 0x57, 0xCD, 0x09, 0x15, + 0xB3, 0x35, 0x3B, 0xBB, 0x64, 0xE0, 0xEC, 0x37, + 0x7F, 0xD0, 0x28, 0x37, 0x0D, 0xF9, 0x2B, 0x52, + 0xC7, 0x89, 0x14, 0x28, 0xCD, 0xC6, 0x7E, 0xB6, + 0x18, 0x4B, 0x52, 0x3D, 0x1D, 0xB2, 0x46, 0xC3, + 0x2F, 0x63, 0x07, 0x84, 0x90, 0xF0, 0x0E, 0xF8, + 0xD6, 0x47, 0xD1, 0x48, 0xD4, 0x79, 0x54, 0x51, + 0x5E, 0x23, 0x27, 0xCF, 0xEF, 0x98, 0xC5, 0x82, + 0x66, 0x4B, 0x4C, 0x0F, 0x6C, 0xC4, 0x16, 0x59 + }; + + static const unsigned char bin_q_valid[] = { + 0x8C, 0xF8, 0x36, 0x42, 0xA7, 0x09, 0xA0, 0x97, + 0xB4, 0x47, 0x99, 0x76, 0x40, 0x12, 0x9D, 0xA2, + 0x99, 0xB1, 0xA4, 0x7D, 0x1E, 0xB3, 0x75, 0x0B, + 0xA3, 0x08, 0xB0, 0xFE, 0x64, 0xF5, 0xFB, 0xD3 + }; + static const unsigned char bin_local_pub[] = { + 0x79, 0x6e, 0x15, 0x43, 0x14, 0x70, 0xac, 0x86, + 0xfa, 0x8a, 0x78, 0xb8, 0xbc, 0xdd, 0x1f, 0x35, + 0x89, 0xdb, 0xf1, 0x5f, 0xfe, 0x0e, 0x0a, 0x7a, + 0x41, 0xdd, 0x86, 0x40, 0x88, 0x7f, 0x3c, 0xc3, + 0xf0, 0x43, 0x9e, 0x28, 0x1f, 0x4c, 0xf3, 0x80, + 0x0b, 0xac, 0x2d, 0xbd, 0xfc, 0xda, 0x58, 0x9b, + 0x26, 0xcc, 0x82, 0x85, 0x12, 0x08, 0x5c, 0xe0, + 0xd3, 0xe5, 0x7a, 0xa1, 0x3c, 0xd9, 0xe7, 0xa4, + 0x66, 0xd8, 0x81, 0xba, 0xce, 0x91, 0xed, 0x10, + 0xc6, 0x06, 0x4a, 0xb3, 0x6e, 0x0d, 0x66, 0x36, + 0x7c, 0x4b, 0xfe, 0xd5, 0x6a, 0x9f, 0x90, 0x7e, + 0x4d, 0xae, 0xc1, 0x67, 0x32, 0xfb, 0x5c, 0x54, + 0x89, 0x1c, 0xb0, 0xd2, 0x62, 0x51, 0xfd, 0x61, + 0xc3, 0x20, 0x40, 0x77, 0x42, 0x46, 0xb3, 0xf8, + 0xbd, 0xcd, 0x5e, 0xf6, 0x0e, 0x68, 0x47, 0xcd, + 0xd6, 0x9b, 0xd6, 0xd3, 0x18, 0xd1, 0xcd, 0xa0, + 0xe8, 0xa3, 0x0a, 0x71, 0x6d, 0xe4, 0xdc, 0x1a, + 0x4e, 0xb9, 0x9b, 0x06, 0x86, 0xb7, 0x71, 0x20, + 0xc4, 0xb6, 0x9b, 0x00, 0x05, 0xf6, 0xa8, 0xc3, + 0xae, 0x76, 0x8d, 0x23, 0xc0, 0x8c, 0x85, 0xbd, + 0x1d, 0x58, 0xf4, 0x0d, 0xc0, 0x13, 0x8d, 0x62, + 0x77, 0x43, 0x61, 0x37, 0xae, 0x69, 0x77, 0x9f, + 0xdc, 0x21, 0x8c, 0x07, 0x1c, 0x14, 0x82, 0x6f, + 0x47, 0x15, 0x62, 0x03, 0x3e, 0x85, 0xff, 0xc9, + 0x9a, 0x21, 0x47, 0xd5, 0x39, 0xe2, 0x74, 0x13, + 0x6a, 0x4a, 0x1e, 0x7f, 0x1d, 0xb9, 0x75, 0x83, + 0xb5, 0x1d, 0xc0, 0x38, 0x5a, 0x52, 0xd7, 0x38, + 0x39, 0x63, 0x75, 0x8d, 0x89, 0x33, 0x98, 0xa8, + 0xd0, 0x13, 0xfd, 0xba, 0xd2, 0x0d, 0xdf, 0x30, + 0xfb, 0xe0, 0x5f, 0xbb, 0x22, 0x49, 0x91, 0x3a, + 0xe6, 0x75, 0x1b, 0x6b, 0x24, 0x6a, 0xe5, 0x62, + 0x2b, 0xa2, 0x6c, 0x48, 0x27, 0x41, 0x7c, 0x2d + }; + static const unsigned char bin_local_priv[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22 + }; + + /* Remote malicious parameters */ + static const unsigned char bin_remote_q[] = { 0x09, 0xf5 }; + static const unsigned char bin_remote_pub[] = { + 0x54, 0xc0, 0x57, 0x90, 0x3d, 0x36, 0x22, 0x35, + 0xa6, 0x5c, 0x03, 0xf0, 0x01, 0xd8, 0xa3, 0xea, + 0x25, 0x28, 0x36, 0xb3, 0x58, 0x02, 0x50, 0xab, + 0xdc, 0x0a, 0x10, 0x83, 0x45, 0x1a, 0xf0, 0x12, + 0x6f, 0xd1, 0x50, 0xf9, 0xe8, 0xd2, 0x12, 0xb3, + 0x84, 0xae, 0x0c, 0x23, 0xaa, 0x7c, 0x67, 0xfe, + 0x85, 0x13, 0x68, 0x11, 0x4c, 0xcc, 0x06, 0x1a, + 0x66, 0x1e, 0x98, 0x6b, 0xd7, 0xe6, 0x3d, 0x25, + 0x75, 0x13, 0x33, 0x9a, 0x69, 0x14, 0xcb, 0xfa, + 0xb2, 0x09, 0xad, 0x79, 0x3e, 0xf2, 0x57, 0x04, + 0xcd, 0x53, 0x2d, 0xdf, 0xb7, 0xe6, 0x93, 0xde, + 0x70, 0x1d, 0x17, 0xe6, 0x29, 0xef, 0x3c, 0x18, + 0x4d, 0x40, 0xd5, 0xfe, 0xa1, 0xf9, 0xed, 0xb8, + 0x9c, 0x5b, 0xf8, 0xd7, 0xaa, 0x19, 0xe3, 0x37, + 0x4f, 0x80, 0x59, 0x32, 0x15, 0x9c, 0xa7, 0xb5, + 0xd5, 0x73, 0xb9, 0xe2, 0xf3, 0xc9, 0x4f, 0xe7, + 0x47, 0xc4, 0xa3, 0xb0, 0x9e, 0x31, 0xaf, 0xa3, + 0x78, 0x8d, 0x35, 0x83, 0x3a, 0xaf, 0x2a, 0xc8, + 0xae, 0x8b, 0xc4, 0x85, 0x00, 0x13, 0x14, 0x64, + 0xe7, 0x93, 0xa2, 0xe0, 0x35, 0x2e, 0x7c, 0x3e, + 0xd9, 0xda, 0x9f, 0xcf, 0x89, 0xb1, 0x21, 0xbc, + 0x1c, 0xee, 0x83, 0xc5, 0x44, 0x21, 0x4c, 0xeb, + 0x33, 0x38, 0xb1, 0x4a, 0xc6, 0x89, 0x19, 0x68, + 0x35, 0x17, 0x46, 0xea, 0xf6, 0x2b, 0xb5, 0x17, + 0xeb, 0x98, 0xfc, 0x63, 0x3d, 0x8d, 0x23, 0x5b, + 0xac, 0x37, 0xbc, 0x08, 0xe4, 0x7f, 0x18, 0x51, + 0xd0, 0x55, 0x01, 0x94, 0x9a, 0x67, 0x33, 0x96, + 0x5a, 0xdb, 0xfe, 0x8e, 0x43, 0xf7, 0xc3, 0xb9, + 0x3c, 0xa7, 0x51, 0x5c, 0xd6, 0xab, 0x36, 0xd7, + 0xef, 0x26, 0xbb, 0x0f, 0xd6, 0x03, 0x3a, 0xbc, + 0x39, 0x61, 0x3e, 0x88, 0x0f, 0xff, 0xc8, 0x72, + 0x9b, 0x03, 0xbf, 0xea, 0xdd, 0xf0, 0x88, 0x33 + }; + + if (!TEST_ptr(p = BN_bin2bn(bin_p, sizeof(bin_p), NULL)) + || !TEST_ptr(g = BN_bin2bn(bin_g, sizeof(bin_g), NULL))) + goto err; + + if (!TEST_ptr(q_valid = BN_bin2bn(bin_q_valid, sizeof(bin_q_valid), NULL)) + || !TEST_ptr(pub_local + = BN_bin2bn(bin_local_pub, sizeof(bin_local_pub), NULL)) + || !TEST_true(priv_local + = BN_bin2bn(bin_local_priv, sizeof(bin_local_priv), NULL))) + goto err; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q_valid)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_local)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv_local)) + || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) + goto err; + + if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(testctx, "DHX", testpropq)) + || !TEST_int_gt(EVP_PKEY_fromdata_init(pctx), 0) + || !TEST_int_gt(EVP_PKEY_fromdata(pctx, &local_key, EVP_PKEY_KEYPAIR, params), 0)) + goto err; + + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(pctx); + params = NULL; + bld = NULL; + pctx = NULL; + + if (!TEST_ptr(q_bad = BN_bin2bn(bin_remote_q, sizeof(bin_remote_q), NULL)) + || !TEST_ptr(pub_bad + = BN_bin2bn(bin_remote_pub, sizeof(bin_remote_pub), NULL))) + goto err; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q_bad)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_bad)) + || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) + goto err; + + if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(testctx, "DHX", testpropq)) + || !TEST_int_gt(EVP_PKEY_fromdata_init(pctx), 0) + || !TEST_int_gt(EVP_PKEY_fromdata(pctx, &remote_key, EVP_PKEY_PUBLIC_KEY, params), 0)) + goto err; + + if (!TEST_ptr(derive_ctx = EVP_PKEY_CTX_new(local_key, NULL)) + || !TEST_int_gt(EVP_PKEY_derive_init(derive_ctx), 0)) + goto err; + + /* reject the remote key share, even if it is self-consistent, correct + * code needs to use local q, not remote-provided q. */ + if (!TEST_int_le(EVP_PKEY_derive_set_peer(derive_ctx, remote_key), 0)) { + TEST_error("EVP_PKEY_derive_set_peer incorrectly accepted a peer with malicious 'q'"); + goto err; + } + + ret = 1; + +err: + BN_free(p); + BN_free(g); + BN_free(q_valid); + BN_free(pub_local); + BN_free(priv_local); + BN_free(q_bad); + BN_free(pub_bad); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_CTX_free(derive_ctx); + EVP_PKEY_free(local_key); + EVP_PKEY_free(remote_key); + return ret; +} #endif /* !OPENSSL_NO_DH */ /* @@ -7513,6 +7764,7 @@ int setup_tests(void) #ifndef OPENSSL_NO_DEPRECATED_3_0 ADD_TEST(test_EVP_PKEY_set1_DH); #endif + ADD_TEST(test_dhx_derive_rejects_bad_peer_q); #endif #ifndef OPENSSL_NO_EC ADD_TEST(test_EC_priv_pub); From 27dbea794067340c85576c75fca788c8fd5c071e Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Thu, 30 Apr 2026 21:46:43 -0700 Subject: [PATCH 054/189] providers/defltprov.c: remove static globals from provider_init The default provider stored two function pointers from the core dispatch table (c_gettable_params, c_get_params) in file-scope statics, written by ossl_default_provider_init() without any synchronization. When OSSL_PROVIDER_load() is invoked from multiple threads concurrently, TSAN reports a data race on both writes[1]. c_gettable_params is never read anywhere in the file; it was dead storage. c_get_params is only consumed once, inside the same call to ossl_default_provider_init(), to seed the provider context via ossl_prov_ctx_set0_core_get_params(). It can therefore be a local variable rather than file-scope state. Drop the unused c_gettable_params static together with its dispatch case, and scope c_get_params inside the init function. The behavior of the default provider is unchanged for single-threaded callers; the concurrent-load race goes away because the shared mutable state is gone. [1] https://github.com/openssl/openssl/issues/28935 CLA: trivial Resolves: https://github.com/openssl/openssl/issues/28935 Reviewed-by: Norbert Pocs Reviewed-by: Neil Horman Reviewed-by: Eugene Syromiatnikov MergeDate: Sun Jun 28 17:51:52 2026 (Merged from https://github.com/openssl/openssl/pull/31508) (cherry picked from commit 57f4bd9ab801c9d362ef5e110b74362f41db26c3) --- providers/defltprov.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/providers/defltprov.c b/providers/defltprov.c index a74a048d6f76a..de2a46515e113 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -34,10 +34,6 @@ static OSSL_FUNC_provider_query_operation_fn deflt_query; #define ALGC(NAMES, FUNC, CHECK) { { NAMES, "provider=default", FUNC }, CHECK } #define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL) -/* Functions provided by the core */ -static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; -static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; - /* Parameters we provide to the core */ static const OSSL_PARAM deflt_param_types[] = { OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), @@ -733,6 +729,7 @@ int ossl_default_provider_init(const OSSL_CORE_HANDLE *handle, void **provctx) { OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL; + OSSL_FUNC_core_get_params_fn *c_get_params = NULL; BIO_METHOD *corebiometh; if (!ossl_prov_bio_from_dispatch(in) @@ -740,9 +737,6 @@ int ossl_default_provider_init(const OSSL_CORE_HANDLE *handle, return 0; for (; in->function_id != 0; in++) { switch (in->function_id) { - case OSSL_FUNC_CORE_GETTABLE_PARAMS: - c_gettable_params = OSSL_FUNC_core_gettable_params(in); - break; case OSSL_FUNC_CORE_GET_PARAMS: c_get_params = OSSL_FUNC_core_get_params(in); break; From 0cca982d787efbc81f76e3a8713fc87a0c0a056f Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Tue, 16 Jun 2026 08:11:32 +0200 Subject: [PATCH 055/189] providers/baseprov.c: remove static globals c_gettable_params is never read anywhere in the file; it was dead storage. c_get_params is only consumed once, inside the same call to ossl_default_provider_init(), to seed the provider context via ossl_prov_ctx_set0_core_get_params(). It can therefore be a local variable rather than file-scope state. Drop the unused c_gettable_params static together with its dispatch case, and scope c_get_params inside the init function. The behavior of the base provider is unchanged for single-threaded callers; the concurrent-load race goes away because the shared mutable state is gone. Signed-off-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs Reviewed-by: Neil Horman Reviewed-by: Eugene Syromiatnikov MergeDate: Sun Jun 28 17:51:54 2026 (Merged from https://github.com/openssl/openssl/pull/31508) (cherry picked from commit f3447c3bc217a4439470fb65609b1c3e77956116) --- providers/baseprov.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/providers/baseprov.c b/providers/baseprov.c index 16d2f91bb1ac1..f517e5ae81b53 100644 --- a/providers/baseprov.c +++ b/providers/baseprov.c @@ -29,10 +29,6 @@ static OSSL_FUNC_provider_gettable_params_fn base_gettable_params; static OSSL_FUNC_provider_get_params_fn base_get_params; static OSSL_FUNC_provider_query_operation_fn base_query; -/* Functions provided by the core */ -static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; -static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; - /* Parameters we provide to the core */ static const OSSL_PARAM base_param_types[] = { OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), @@ -139,15 +135,13 @@ int ossl_base_provider_init(const OSSL_CORE_HANDLE *handle, void **provctx) { OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL; + OSSL_FUNC_core_get_params_fn *c_get_params = NULL; BIO_METHOD *corebiometh; if (!ossl_prov_bio_from_dispatch(in)) return 0; for (; in->function_id != 0; in++) { switch (in->function_id) { - case OSSL_FUNC_CORE_GETTABLE_PARAMS: - c_gettable_params = OSSL_FUNC_core_gettable_params(in); - break; case OSSL_FUNC_CORE_GET_PARAMS: c_get_params = OSSL_FUNC_core_get_params(in); break; From cb293968e27b91d61c998a7cfe45ac9d408d03b5 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Tue, 16 Jun 2026 08:32:35 +0200 Subject: [PATCH 056/189] providers/fips/fipsprov.c, test/p_test.c: remove c_gettable_params static global c_gettable_params is never read anywhere in the files; it was dead storage. Remove it. Signed-off-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs Reviewed-by: Neil Horman Reviewed-by: Eugene Syromiatnikov MergeDate: Sun Jun 28 17:51:55 2026 (Merged from https://github.com/openssl/openssl/pull/31508) (cherry picked from commit f32f8682eac94360684d9856b7f72de4948b8637) --- providers/fips/fipsprov.c | 4 ---- test/p_test.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 419878719e98e..0a7deaeb78dc2 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -56,7 +56,6 @@ extern OSSL_FUNC_core_thread_start_fn *c_thread_start; */ /* Functions provided by the core */ -static OSSL_FUNC_core_gettable_params_fn *c_gettable_params; static OSSL_FUNC_core_get_params_fn *c_get_params; OSSL_FUNC_core_thread_start_fn *c_thread_start; static OSSL_FUNC_core_new_error_fn *c_new_error; @@ -771,9 +770,6 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, case OSSL_FUNC_CORE_GET_LIBCTX: set_func(c_get_libctx, OSSL_FUNC_core_get_libctx(in)); break; - case OSSL_FUNC_CORE_GETTABLE_PARAMS: - set_func(c_gettable_params, OSSL_FUNC_core_gettable_params(in)); - break; case OSSL_FUNC_CORE_GET_PARAMS: set_func(c_get_params, OSSL_FUNC_core_get_params(in)); break; diff --git a/test/p_test.c b/test/p_test.c index 1e38bee717b68..655cb7ce6fc8f 100644 --- a/test/p_test.c +++ b/test/p_test.c @@ -43,7 +43,6 @@ typedef struct p_test_ctx { OSSL_LIB_CTX *libctx; } P_TEST_CTX; -static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; static OSSL_FUNC_core_new_error_fn *c_new_error; static OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug; @@ -258,9 +257,6 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, for (; in->function_id != 0; in++) { switch (in->function_id) { - case OSSL_FUNC_CORE_GETTABLE_PARAMS: - c_gettable_params = OSSL_FUNC_core_gettable_params(in); - break; case OSSL_FUNC_CORE_GET_PARAMS: c_get_params = OSSL_FUNC_core_get_params(in); break; From e7a956c3643b1bcb764516ef0dd49d3f9c674342 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 24 Jun 2026 15:55:48 -0400 Subject: [PATCH 057/189] ensure writes are syncronized on windows in CRYPTO_THREAD_run_once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We've tried to fix this properly using InitOnceExecuteOnce, but it results in an ABI breakage, so we're doing it this way. on windows, CRYPTO_THREAD_run_once, on weakly memory ordered systems, may complete the write of the run once variable lock before some of the writes made by the init callback routine complete. The result is that on a heavily multithreaded application, other therads may see the data that was meant to be in an initalized state, as in some erroneous in-between state, leading to errors. Fix it by inserting a full memory barrier after we return from the init callback, and prior to setting the run once variable to ONCE_DONE. Reviewed-by: Saša Nedvědický Reviewed-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs MergeDate: Tue Jun 30 08:51:57 2026 (Merged from https://github.com/openssl/openssl/pull/31713) --- crypto/threads_win.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crypto/threads_win.c b/crypto/threads_win.c index 2c0e27ce06eb6..158aa2ea91c98 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -535,6 +535,20 @@ int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); if (result == ONCE_UNINITED) { init(); + /* + * On weakly ordered systems, it may happen that the write to *lock + * below completes prior to some writes in whatever the init() + * callback routine above may do. In this case, other threads + * entering here may see unsynchronized data in whatever the init + * routine initializes, leading to erroneous behavior. + * + * We should use InitOnceExecuteOnce here to implement this, but + * doing so requires that we modify the definition of the + * CRYPTO_ONCE type, which is an ABI breakage. So instead + * just insert a memory barrier here to ensure that any pending + * writes are flushed to memory prior to setting ONCE_DONE below + */ + MemoryBarrier(); *lock = ONCE_DONE; return 1; } From 04a1fc500f0199336517713d7d7019cac5885883 Mon Sep 17 00:00:00 2001 From: Bob Beck Date: Fri, 22 May 2026 06:37:24 -0600 Subject: [PATCH 058/189] SSL_OP_SECOP is dead code Nothing set the "vfy" parameters in any of these functions to anything but 0. Remove the parameter and stage things related to SSL_OP_SECOP to go away in the future. Reviewed-by: Neil Horman Reviewed-by: Norbert Pocs MergeDate: Tue Jun 30 10:55:31 2026 (Merged from https://github.com/openssl/openssl/pull/31271) --- apps/lib/s_cb.c | 4 ---- include/openssl/ssl.h.in | 18 +++++++++++------- ssl/ssl_cert.c | 6 +++--- ssl/ssl_local.h | 5 ++--- ssl/ssl_rsa.c | 8 ++++---- ssl/statem/statem_lib.c | 4 ++-- ssl/t1_lib.c | 17 +++++++---------- 7 files changed, 29 insertions(+), 33 deletions(-) diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c index 80b5c65554246..f65606302fb1d 100644 --- a/apps/lib/s_cb.c +++ b/apps/lib/s_cb.c @@ -1461,10 +1461,7 @@ static STRINT_PAIR callback_types[] = { { "Signature Algorithm mask", SSL_SECOP_SIGALG_MASK }, { "Certificate chain EE key", SSL_SECOP_EE_KEY }, { "Certificate chain CA key", SSL_SECOP_CA_KEY }, - { "Peer Chain EE key", SSL_SECOP_PEER_EE_KEY }, - { "Peer Chain CA key", SSL_SECOP_PEER_CA_KEY }, { "Certificate chain CA digest", SSL_SECOP_CA_MD }, - { "Peer chain CA digest", SSL_SECOP_PEER_CA_MD }, { "SSL compression", SSL_SECOP_COMPRESSION }, { "Session ticket", SSL_SECOP_TICKET }, { NULL } @@ -1498,7 +1495,6 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, show_nm = 0; break; case SSL_SECOP_CA_MD: - case SSL_SECOP_PEER_CA_MD: cert_md = 1; break; case SSL_SECOP_SIGALG_SUPPORTED: diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in index e684f7c429750..99087b874ab9a 100644 --- a/include/openssl/ssl.h.in +++ b/include/openssl/ssl.h.in @@ -2688,8 +2688,18 @@ const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx); #define SSL_SECOP_OTHER_SIGALG (5 << 16) #define SSL_SECOP_OTHER_CERT (6 << 16) -/* Indicated operation refers to peer key or certificate */ +/* + * Unused values - these do nothing and are never set. + * They are retained because of API. They should + * be removed next major + */ #define SSL_SECOP_PEER 0x1000 +/* Peer EE key in certificate */ +#define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER) +/* Peer CA key in certificate */ +#define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER) +/* Peer CA digest algorithm in certificate */ +#define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER) /* Values for "op" parameter in security callback */ @@ -2728,12 +2738,6 @@ const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx); #define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT) /* CA digest algorithm in certificate */ #define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT) -/* Peer EE key in certificate */ -#define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER) -/* Peer CA key in certificate */ -#define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER) -/* Peer CA digest algorithm in certificate */ -#define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER) void SSL_set_security_level(SSL *s, int level); __owur int SSL_get_security_level(const SSL *s); diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index adc5bb3d35c3e..e9b05225ad7a8 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -306,7 +306,7 @@ int ssl_cert_set0_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain) for (i = 0; i < sk_X509_num(chain); i++) { X509 *x = sk_X509_value(chain, i); - r = ssl_security_cert(s, ctx, x, 0, 0); + r = ssl_security_cert(s, ctx, x, 0); if (r != 1) { ERR_raise(ERR_LIB_SSL, r); return 0; @@ -340,7 +340,7 @@ int ssl_cert_add0_chain_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x) if (!cpk) return 0; - r = ssl_security_cert(s, ctx, x, 0, 0); + r = ssl_security_cert(s, ctx, x, 0); if (r != 1) { ERR_raise(ERR_LIB_SSL, r); return 0; @@ -1149,7 +1149,7 @@ int ssl_build_cert_chain(SSL_CONNECTION *s, SSL_CTX *ctx, int flags) */ for (i = 0; i < sk_X509_num(chain); i++) { x = sk_X509_value(chain, i); - rv = ssl_security_cert(s, ctx, x, 0, 0); + rv = ssl_security_cert(s, ctx, x, 0); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); OSSL_STACK_OF_X509_free(chain); diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 8fc8b64406153..893a2c004f17f 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -2901,10 +2901,9 @@ __owur int ssl_validate_ct(SSL_CONNECTION *s); __owur EVP_PKEY *ssl_get_auto_dh(SSL_CONNECTION *s); -__owur int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int vfy, - int is_ee); +__owur int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int is_ee); __owur int ssl_security_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk, - X509 *ex, int vfy); + X509 *ex); int tls_choose_sigalg(SSL_CONNECTION *s, int fatalerrs); diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index 740460f5c2e02..42958d9d0c2d1 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -42,7 +42,7 @@ int SSL_use_certificate(SSL *ssl, X509 *x) return 0; } - rv = ssl_security_cert(sc, NULL, x, 0, 1); + rv = ssl_security_cert(sc, NULL, x, 1); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); return 0; @@ -247,7 +247,7 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) return 0; } - rv = ssl_security_cert(NULL, ctx, x, 0, 1); + rv = ssl_security_cert(NULL, ctx, x, 1); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); return 0; @@ -993,13 +993,13 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr c = sc != NULL ? sc->cert : ctx->cert; /* Do all security checks before anything else */ - rv = ssl_security_cert(sc, ctx, x509, 0, 1); + rv = ssl_security_cert(sc, ctx, x509, 1); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); goto out; } for (j = 0; j < sk_X509_num(chain); j++) { - rv = ssl_security_cert(sc, ctx, sk_X509_value(chain, j), 0, 0); + rv = ssl_security_cert(sc, ctx, sk_X509_value(chain, j), 0); if (rv != 1) { ERR_raise(ERR_LIB_SSL, rv); goto out; diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 7e3be12f7a718..c690087081477 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1071,7 +1071,7 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i /* Don't leave errors in the queue */ ERR_clear_error(); chain = X509_STORE_CTX_get0_chain(xs_ctx); - i = ssl_security_cert_chain(s, chain, NULL, 0); + i = ssl_security_cert_chain(s, chain, NULL); if (i != 1) { #if 0 /* Dummy error calls so mkerr generates them */ @@ -1096,7 +1096,7 @@ static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, i } X509_STORE_CTX_free(xs_ctx); } else { - i = ssl_security_cert_chain(s, extra_certs, x, 0); + i = ssl_security_cert_chain(s, extra_certs, x); if (i != 1) { if (!for_comp) SSLfatal(s, SSL_AD_INTERNAL_ERROR, i); diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index e11fa8bc638ec..7ba3d79776131 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -4421,19 +4421,16 @@ static int ssl_security_cert_sig(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, return ssl_ctx_security(ctx, op, secbits, nid, x); } -int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int vfy, - int is_ee) +int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int is_ee) { - if (vfy) - vfy = SSL_SECOP_PEER; if (is_ee) { - if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy)) + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY)) return SSL_R_EE_KEY_TOO_SMALL; } else { - if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy)) + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY)) return SSL_R_CA_KEY_TOO_SMALL; } - if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy)) + if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD)) return SSL_R_CA_MD_TOO_WEAK; return 1; } @@ -4445,7 +4442,7 @@ int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int vfy, */ int ssl_security_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk, - X509 *x, int vfy) + X509 *x) { int rv, start_idx, i; @@ -4457,13 +4454,13 @@ int ssl_security_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk, } else start_idx = 0; - rv = ssl_security_cert(s, NULL, x, vfy, 1); + rv = ssl_security_cert(s, NULL, x, 1); if (rv != 1) return rv; for (i = start_idx; i < sk_X509_num(sk); i++) { x = sk_X509_value(sk, i); - rv = ssl_security_cert(s, NULL, x, vfy, 0); + rv = ssl_security_cert(s, NULL, x, 0); if (rv != 1) return rv; } From 1609edf2edbf91ddd1f027458c8ff52d44a24dde Mon Sep 17 00:00:00 2001 From: Bob Beck Date: Fri, 22 May 2026 04:10:37 -0600 Subject: [PATCH 059/189] Don't attempt to check the security level on what signed our own certificate. What matters to us is that the key *we* are using matches our desired security level, as we may sign things with that key. As far as who signed us, this could be signed by something we don't recognize at all, and it is up to the peer to decide if the thing signing us matters to it (i.e. if it recognizes the algorithm, decides it's strong enough, or it even verifies the signature, as it might already trusts our key due to pinning, TOFU, Prayer and Clean Living, or whatever.) Obviously, we still check the security level on any signatures *we* recieve to verify *from* a peer. Fixes: https://github.com/openssl/openssl/issues/31195 Reviewed-by: Neil Horman Reviewed-by: Norbert Pocs MergeDate: Tue Jun 30 10:55:32 2026 (Merged from https://github.com/openssl/openssl/pull/31271) --- ssl/t1_lib.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 7ba3d79776131..e3268e1a952d5 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -4401,26 +4401,6 @@ static int ssl_security_cert_key(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, return ssl_ctx_security(ctx, op, secbits, 0, x); } -static int ssl_security_cert_sig(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, - int op) -{ - /* Lookup signature algorithm digest */ - int secbits, nid, pknid; - - /* Don't check signature if self signed */ - if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0) - return 1; - if (!X509_get_signature_info(x, &nid, &pknid, &secbits, NULL)) - secbits = -1; - /* If digest NID not defined use signature NID */ - if (nid == NID_undef) - nid = pknid; - if (s != NULL) - return ssl_security(s, op, secbits, nid, x); - else - return ssl_ctx_security(ctx, op, secbits, nid, x); -} - int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int is_ee) { if (is_ee) { @@ -4430,15 +4410,16 @@ int ssl_security_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x, int is_ee) if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY)) return SSL_R_CA_KEY_TOO_SMALL; } - if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD)) - return SSL_R_CA_MD_TOO_WEAK; return 1; } /* - * Check security of a chain, if |sk| includes the end entity certificate then - * |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending - * one to the peer. Return values: 1 if ok otherwise error code to use + * Call ssl_security_check() on all certificates in a stack. + * If |x| is non NULL it is checked first, before checking the + * certificates in the stack. + * + * Return values: 1 if ok otherwise the error code from the first + * failing ssl_security_check().; */ int ssl_security_cert_chain(SSL_CONNECTION *s, STACK_OF(X509) *sk, From df2711dd9df73adafd70bdc470b00d4837981e5d Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Thu, 25 Jun 2026 11:06:30 +0200 Subject: [PATCH 060/189] s390x: Fix return code handling in HMAC_Init_ex() When running on the s390x platform HMAC_Init_ex() calls s390x_HMAC_init() to optionally allow hardware acceleration of the HMAC operation. In case the hardware acceleration is not available, s390x_HMAC_init() returns -1 to indicate that. In this case the software path is continued. The problem is that rv was set to -1 by s390x_HMAC_init() and stays at this until the end of the function. In case the software path detects an error it goes to the 'err' label which just returns rv as is, and thus HMAC_Init_ex() now returns -1 instead of 0 (rv was initialized to 0 at declaration). The wrong return value might then be propagated through all layers, i.e. to EVP_MAC_init() which also returns -1 in this case. However, EVP_MAC_init() is defined as returning 1 on success, or 0 on error, i.e. a boolean kind of return value. Typically, callers will do something like 'if (!EVP_MAC_init(s....))' to check for errors. A return value of -1 is non-zero, and thus it is treated as successful return. Fix this by setting rv back to 0 when s390x_HMAC_init() returned -1. Fixes: 0499de5adda2 "s390x: Add hardware acceleration for HMAC" Resolves: https://github.com/openssl/openssl/issues/31706 Signed-off-by: Ingo Franzki Reviewed-by: Eugene Syromiatnikov Reviewed-by: Milan Broz MergeDate: Tue Jun 30 20:49:52 2026 (Merged from https://github.com/openssl/openssl/pull/31723) (cherry picked from commit f0ca416976ac5b6761bf45e28fa42f1981edbe2c) --- crypto/hmac/hmac.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c index c5d42db820200..fa54540be322d 100644 --- a/crypto/hmac/hmac.c +++ b/crypto/hmac/hmac.c @@ -50,9 +50,11 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, return 0; #ifdef OPENSSL_HMAC_S390X - rv = s390x_HMAC_init(ctx, key, len, impl); - if (rv >= 1) - return rv; + { + int ret = s390x_HMAC_init(ctx, key, len, impl); + if (ret != -1) /* -1 means SW fallback */ + return ret; + } #endif if (key != NULL) { From dba3838f722f0b7c865fa9a6438f2f805c3cba42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Trojnara?= Date: Sat, 27 Jun 2026 22:39:44 +0200 Subject: [PATCH 061/189] s_client: skip TCP shutdown drain for datagram protocols The shutdown-side drain uses a TCP half-close and a fixed 500 ms select() timeout to let peers consume buffered alerts before close. Running it for DTLS/QUIC datagram connections causes an unnecessary delay after the connection has otherwise completed. Limit this workaround to non-DTLS, non-QUIC connections. CLA: trivial Reviewed-by: Matt Caswell Reviewed-by: Dmitry Belyavskiy Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jul 1 13:35:53 2026 (Merged from https://github.com/openssl/openssl/pull/31558) (cherry picked from commit 5d61a36a9425c7615f9b8510967db330ee5ed6fc) --- apps/s_client.c | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/apps/s_client.c b/apps/s_client.c index c83976c7516be..b3f333a6993c3 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -3347,29 +3347,32 @@ int s_client_main(int argc, char **argv) print_stuff(bio_c_out, con, full_log); do_ssl_shutdown(con); - /* - * If we ended with an alert being sent, but still with data in the - * network buffer to be read, then calling BIO_closesocket() will - * result in a TCP-RST being sent. On some platforms (notably - * Windows) then this will result in the peer immediately abandoning - * the connection including any buffered alert data before it has - * had a chance to be read. Shutting down the sending side first, - * and then closing the socket sends TCP-FIN first followed by - * TCP-RST. This seems to allow the peer to read the alert data. - */ - shutdown(SSL_get_fd(con), 1); /* SHUT_WR */ - /* - * We just said we have nothing else to say, but it doesn't mean that - * the other side has nothing. It's even recommended to consume incoming - * data. [In testing context this ensures that alerts are passed on...] - */ - timeout.tv_sec = 0; - timeout.tv_usec = 500000; /* some extreme round-trip */ - do { - FD_ZERO(&readfds); - openssl_fdset(sock, &readfds); - } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 - && BIO_read(sbio, sbuf, BUFSIZZ) > 0); + /* The following half-close/drain workaround is TCP-specific. */ + if (!isdtls && !isquic) { + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(SSL_get_fd(con), 1); /* SHUT_WR */ + /* + * We just said we have nothing else to say, but it doesn't mean that + * the other side has nothing. It's even recommended to consume incoming + * data. [In testing context this ensures that alerts are passed on...] + */ + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* some extreme round-trip */ + do { + FD_ZERO(&readfds); + openssl_fdset(sock, &readfds); + } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 + && BIO_read(sbio, sbuf, BUFSIZZ) > 0); + } BIO_closesocket(SSL_get_fd(con)); end: From b859876985a06d52c8c370d8d4ac4370d219712d Mon Sep 17 00:00:00 2001 From: olszomal Date: Tue, 5 Aug 2025 12:00:03 +0200 Subject: [PATCH 062/189] BIO: avoid returning internal FILE * with UPLINK-enabled builds on Windows On Windows with UPLINK enabled, BIO_get_fp() may return a FILE * pointer incompatible with the C runtime. Ensure that it returns NULL instead, preventing undefined behavior in applications. Update the documentation to include the missing return type for BIO_[gs]et_fp() and remove the mention that BIO_get_fp() never returns 0, as it does so now when NULL fp is returned. Signed-off-by: olszomal Reviewed-by: Dmitry Belyavskiy Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jul 8 09:47:40 2026 (Merged from https://github.com/openssl/openssl/pull/28172) (cherry picked from commit b5b34d32cb98341434dd8b88a13182b0131d9344) --- crypto/bio/bss_file.c | 8 +++++++- doc/man3/BIO_s_file.pod | 7 +++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c index 6b8daeb95f905..023bb458ce5f0 100644 --- a/crypto/bio/bss_file.c +++ b/crypto/bio/bss_file.c @@ -312,7 +312,13 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) /* the ptr parameter is actually a FILE ** in this case. */ if (ptr != NULL) { fpp = (FILE **)ptr; - *fpp = (FILE *)b->ptr; + if (BIO_FLAGS_UPLINK_INTERNAL == 0 + || b->flags & BIO_FLAGS_UPLINK_INTERNAL) { + *fpp = (FILE *)b->ptr; + } else { /* avoid returning internal FILE * to the app */ + *fpp = NULL; + ret = 0; + } } break; case BIO_CTRL_GET_CLOSE: diff --git a/doc/man3/BIO_s_file.pod b/doc/man3/BIO_s_file.pod index 5dcd4bbbcaeda..6cd1da02a3eae 100644 --- a/doc/man3/BIO_s_file.pod +++ b/doc/man3/BIO_s_file.pod @@ -14,8 +14,8 @@ BIO_rw_filename - FILE bio BIO *BIO_new_file(const char *filename, const char *mode); BIO *BIO_new_fp(FILE *stream, int flags); - BIO_set_fp(BIO *b, FILE *fp, int flags); - BIO_get_fp(BIO *b, FILE **fpp); + long BIO_set_fp(BIO *b, FILE *fp, int flags); + long BIO_get_fp(BIO *b, FILE **fpp); int BIO_read_filename(BIO *b, char *name); int BIO_write_filename(BIO *b, char *name); @@ -87,8 +87,7 @@ BIO_s_file() returns the file BIO method. BIO_new_file() and BIO_new_fp() return a file BIO or NULL if an error occurred. -BIO_set_fp() and BIO_get_fp() return 1 for success or <=0 for failure -(although the current implementation never return 0). +BIO_set_fp() and BIO_get_fp() return 1 for success or <=0 for failure. BIO_seek() returns 0 for success or negative values for failure. From ad4e559a800bae8fdf621a3e85a70366504a9a5c Mon Sep 17 00:00:00 2001 From: olszomal Date: Fri, 8 Aug 2025 12:06:36 +0200 Subject: [PATCH 063/189] apps: adjust stat usage to account for uplink Call stat() instead of fstat() when the FILE pointer provided by BIO_get_fp() is unavailable (as it may be the case in case of UPLINK builds). Signed-off-by: olszomal Reviewed-by: Dmitry Belyavskiy Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jul 8 09:47:42 2026 (Merged from https://github.com/openssl/openssl/pull/28172) (cherry picked from commit d2a9af2144ac2938619e44af3eaeaed3ea49cb05) --- apps/lib/apps.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/lib/apps.c b/apps/lib/apps.c index 1258f1ecdf1d9..29dd6514f6d93 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -1688,11 +1688,18 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) goto err; #ifndef OPENSSL_NO_POSIX_IO - BIO_get_fp(in, &dbfp); - if (fstat(fileno(dbfp), &dbst) == -1) { - ERR_raise_data(ERR_LIB_SYS, errno, - "calling fstat(%s)", dbfile); - goto err; + if (BIO_get_fp(in, &dbfp) > 0 && dbfp != NULL) { + if (fstat(fileno(dbfp), &dbst) == -1) { + ERR_raise_data(ERR_LIB_SYS, errno, + "calling fstat(%s)", dbfile); + goto err; + } + } else { + if (stat(dbfile, &dbst) == -1) { + ERR_raise_data(ERR_LIB_SYS, errno, + "calling stat(%s)", dbfile); + goto err; + } } #endif From 8207846175a8625b9ac878918b057042241212ef Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Wed, 1 Jul 2026 17:11:54 +0100 Subject: [PATCH 064/189] doc/man3/ASN1_INTEGER_get_int64.pod: fix a typo CLA: trivial Fixes: 6c5b6cb03566 "ASN1 INTEGER refactor." Reviewed-by: Neil Horman Reviewed-by: Frederik Wedel-Heinen Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jul 8 10:18:11 2026 (Merged from https://github.com/openssl/openssl/pull/31815) (cherry picked from commit 51584371a27d2e939babcac3a8fd145c0a2f16ac) --- doc/man3/ASN1_INTEGER_get_int64.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/man3/ASN1_INTEGER_get_int64.pod b/doc/man3/ASN1_INTEGER_get_int64.pod index 4ba6c4c0d71f4..d25c87a5e25c2 100644 --- a/doc/man3/ASN1_INTEGER_get_int64.pod +++ b/doc/man3/ASN1_INTEGER_get_int64.pod @@ -108,7 +108,7 @@ B structure respectively or NULL if an error occurs. They will only fail due to a memory allocation error. ASN1_INTEGER_to_BN() and ASN1_ENUMERATED_to_BN() return a B structure -of NULL if an error occurs. They can fail if the passed type is incorrect +or NULL if an error occurs. They can fail if the passed type is incorrect (due to programming error) or due to a memory allocation failure. =head1 SEE ALSO From 1b025efdcb76643323e9efb347896d12dfdc6291 Mon Sep 17 00:00:00 2001 From: Steven WdV Date: Tue, 7 Jul 2026 14:52:30 +0200 Subject: [PATCH 065/189] Allow `getentropy` for Emscripten Usually Emscripten emulates `/dev/urandom`, but in some cases, like with `-sNODERAWFS`, it doesn't. This means that on non-Unix platforms, where `/dev/urandom` does not exist on the host, OpenSSL will fail to seed its PRNG. This fixes that by instead using the POSIX function it implements, like which was already done for WASI. See https://github.com/emscripten-core/emscripten/issues/9628#issuecomment-4892658766 for more context. CLA: trivial Reviewed-by: Kurt Roeckx Reviewed-by: Daniel Kubec Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz MergeDate: Wed Jul 8 17:50:39 2026 (Merged from https://github.com/openssl/openssl/pull/31882) (cherry picked from commit dc219a04088d08de7df5afdb14263b3e9a4c7915) --- providers/implementations/rands/seeding/rand_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 80ae8173131db..6878421ce2b8c 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -394,7 +394,7 @@ static ssize_t syscall_random(void *buf, size_t buflen) return getrandom(buf, buflen, 0); #elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND) return sysctl_random(buf, buflen); -#elif defined(__wasi__) +#elif defined(__wasi__) || defined(__EMSCRIPTEN__) if (getentropy(buf, buflen) == 0) return (ssize_t)buflen; return -1; From 7175f9e31afb653b8ef187f39f3fc8e68d228d78 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Tue, 30 Jun 2026 09:01:20 +0200 Subject: [PATCH 066/189] crypto/x509/x509_lu.c: check X509_OBJECT_up_ref_count() in x509_object_dup() the return value of X509_OBJECT_up_ref_count() was ignored. If the reference count increment fails, x509_object_dup() still returned a duplicate X509_OBJECT whose ->data aliases the source X509/X509_CRL without a reference actually having been taken. Freeing that duplicate later drops a reference it never held, leading to a premature free and use-after-free of the shared object. Signed-off-by: Nikola Pajkovsky Reviewed-by: Eugene Syromiatnikov Reviewed-by: Neil Horman Reviewed-by: Norbert Pocs MergeDate: Wed Jul 8 18:20:10 2026 (Merged from https://github.com/openssl/openssl/pull/31811) (cherry picked from commit 38c7ace6c17267ca9a5dde25c7f025ba418a0c36) --- crypto/x509/x509_lu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index af8035bce8448..fc9e43e185a27 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -590,7 +590,12 @@ static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj) ret->type = obj->type; ret->data = obj->data; - X509_OBJECT_up_ref_count(ret); + + if (!X509_OBJECT_up_ref_count(ret)) { + OPENSSL_free(ret); + return NULL; + } + return ret; } From 2222cce10b753abecf5a8927005d9cb3a066e180 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 10 Jul 2026 11:09:09 +0200 Subject: [PATCH 067/189] Avoid undefined behavior adding or subtracting two BN_zero() values Reviewed-by: Dmitry Belyavskiy Reviewed-by: Nikola Pajkovsky MergeDate: Fri Jul 10 14:54:48 2026 (Merged from https://github.com/openssl/openssl/pull/31916) (cherry picked from commit 1768a5a1be8895f3cf54d418093c337ea1f3238d) --- crypto/bn/bn_add.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crypto/bn/bn_add.c b/crypto/bn/bn_add.c index 38de39d1b8aca..52f456850c04c 100644 --- a/crypto/bn/bn_add.c +++ b/crypto/bn/bn_add.c @@ -97,6 +97,8 @@ int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) return 0; r->top = max; + if (max == 0) + goto end; ap = a->d; bp = b->d; @@ -116,6 +118,7 @@ int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) *rp = carry; r->top += carry; +end: r->neg = 0; bn_check_top(r); return 1; @@ -143,6 +146,9 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) if (bn_wexpand(r, max) == NULL) return 0; + if (max == 0) + goto end; + ap = a->d; bp = b->d; rp = r->d; @@ -162,6 +168,7 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) while (max && *--rp == 0) max--; +end: r->top = max; r->neg = 0; bn_pollute(r); From bd873e74b9d98e982d31b2c998a16396157d2d5c Mon Sep 17 00:00:00 2001 From: Igor Ustinov Date: Thu, 9 Jul 2026 08:37:10 +0200 Subject: [PATCH 068/189] Fix a bug in BN_ucmp() when comparing constant-time BIGNUMs of different lengths Reviewed-by: Richard Levitte Reviewed-by: Tomas Mraz MergeDate: Fri Jul 10 15:12:02 2026 (Merged from https://github.com/openssl/openssl/pull/31904) --- crypto/bn/bn_lib.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 93d54fd0a6ed3..9dc443f5b7827 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -707,19 +707,37 @@ int BN_ucmp(const BIGNUM *a, const BIGNUM *b) int i; BN_ULONG t1, t2, *ap, *bp; + /* + * As it is a public API function, we should handle NULL parameters in + * some way. The function can’t return an error, so let’s define that NULL + * is less than any BIGNUM. + */ + if (!ossl_assert(a != NULL && b != NULL)) + return (b == NULL) - (a == NULL); + ap = a->d; bp = b->d; if (BN_get_flags(a, BN_FLG_CONSTTIME) - && a->top == b->top) { + || BN_get_flags(b, BN_FLG_CONSTTIME)) { int res = 0; + int min_top = a->top < b->top ? a->top : b->top; - for (i = 0; i < b->top; i++) { + for (i = 0; i < min_top; i++) { res = constant_time_select_int(constant_time_lt_bn(ap[i], bp[i]), -1, res); res = constant_time_select_int(constant_time_lt_bn(bp[i], ap[i]), 1, res); } + + for (i = min_top; i < a->top; ++i) + res = constant_time_select_int((int)constant_time_is_zero_bn(ap[i]), + res, 1); + + for (i = min_top; i < b->top; ++i) + res = constant_time_select_int((int)constant_time_is_zero_bn(bp[i]), + res, -1); + return res; } From 840158a2734bfd6ac3dab7a843ffa58844b34bc9 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 26 Jun 2026 15:04:27 +0200 Subject: [PATCH 069/189] quic: fix intermittent idle-test failure in tserver test The thread-assisted idle test advances fake time in 10ms steps while the connection is kept alive solely by the background assist thread sending keepalive PINGs. The test stepped fake time without checking that a due keepalive had actually been sent, so whether it went out before the server's idle deadline lapsed depended on thread scheduling - hence the intermittent failure. Now, before each step, check the event timeout (next_deadline minus fake-now): while a keepalive is still due to be sent it stays at zero, so we wake the assist thread and re-check without advancing until it goes positive (or the existing real-time watchdog fires). Only then do we step fake time. The negotiated 30s idle timeout and 60s idle duration are unchanged, so the keepalive is still required and still tested; only the race is removed. Assisted-by: Claude:claude-opus-4-8 Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz MergeDate: Fri Jul 10 15:33:45 2026 (Merged from https://github.com/openssl/openssl/pull/31746) (cherry picked from commit 9b182491fc47042fa3fa5c246b5b24482cd49efd) --- test/quic_tserver_test.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/test/quic_tserver_test.c b/test/quic_tserver_test.c index ae576441e7335..a80987296724e 100644 --- a/test/quic_tserver_test.c +++ b/test/quic_tserver_test.c @@ -331,16 +331,38 @@ static int do_test(int use_thread_assist, int use_fake_time, int use_inject) CRYPTO_THREAD_unlock(fake_time_lock); ++idle_units_done; - ossl_quic_conn_force_assist_thread_wake(c_ssl); /* - * If the event timeout has expired then give the assistance - * thread a chance to catch up + * The assist thread alone keeps the idle connection alive. It + * waits on real time internally, so advancing fake time can + * outrun it. Rather than race it, wait until it has caught up: + * the event timeout is computed against fake time, so once the + * next deadline is back in the future all events due up to now + * - including any keepalive - have been serviced. */ - if (!TEST_true(SSL_get_event_timeout(c_ssl, &tv, &isinf))) - goto err; - if (!isinf && ossl_time_compare(ossl_time_zero(), ossl_time_from_timeval(tv)) >= 0) - OSSL_sleep(100); /* Ensure CPU scheduling for test purposes */ + for (;;) { + ossl_quic_conn_force_assist_thread_wake(c_ssl); + + if (!TEST_true(SSL_get_event_timeout(c_ssl, &tv, &isinf))) + goto err; + + if (isinf + || ossl_time_compare(ossl_time_from_timeval(tv), + ossl_time_zero()) + > 0) + break; + + if (ossl_time_compare(ossl_time_subtract(real_now(NULL), + start_time), + ossl_ms2time(limit_ms)) + >= 0) { + TEST_error("timeout waiting for assist thread to send " + "keepalive during idle test"); + goto err; + } + + OSSL_sleep(1); /* Yield so the assist thread can run. */ + } } else { c_done_idle_test = 1; } From 37a53a9a3e68a988360472aa4074d492a5f991c4 Mon Sep 17 00:00:00 2001 From: Daniel Kubec Date: Tue, 7 Jul 2026 09:16:19 +0000 Subject: [PATCH 070/189] NULL-pointer subtraction UB in tls_collect_extensions() Fixed invalid-pointer-pair in the existing branch by ensuring thisex != NULL before subtraction. Fixes #31689 Reviewed-by: Tom Cosgrove Reviewed-by: Tomas Mraz MergeDate: Fri Jul 10 15:40:21 2026 (Merged from https://github.com/openssl/openssl/pull/31875) (cherry picked from commit 4f17865ba44b904c99d8e10ac1e460b811b7842e) --- ssl/statem/extensions.c | 25 ++++++++++++---------- test/sslapitest.c | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 2de540f828f03..33642ea8df0ab 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -605,6 +605,11 @@ int tls_collect_extensions(SSL_CONNECTION *s, PACKET *packet, SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION); goto err; } + + /* The server must tolerate the unknown extension and complete. */ + if (thisex == NULL) + continue; + idx = thisex - raw_extensions; /*- * Check that we requested this extension (if appropriate). Requests can @@ -635,17 +640,15 @@ int tls_collect_extensions(SSL_CONNECTION *s, PACKET *packet, SSL_R_UNSOLICITED_EXTENSION); goto err; } - if (thisex != NULL) { - thisex->data = extension; - thisex->present = 1; - thisex->type = type; - thisex->received_order = i++; - if (s->ext.debug_cb) - s->ext.debug_cb(SSL_CONNECTION_GET_USER_SSL(s), !s->server, - thisex->type, PACKET_data(&thisex->data), - PACKET_remaining(&thisex->data), - s->ext.debug_arg); - } + thisex->data = extension; + thisex->present = 1; + thisex->type = type; + thisex->received_order = i++; + if (s->ext.debug_cb) + s->ext.debug_cb(SSL_CONNECTION_GET_USER_SSL(s), !s->server, + thisex->type, PACKET_data(&thisex->data), + (int)PACKET_remaining(&thisex->data), + s->ext.debug_arg); } if (init) { diff --git a/test/sslapitest.c b/test/sslapitest.c index 0cdeb473cdfba..3da9e99752030 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -11965,6 +11965,51 @@ static int test_tls13_record_padding(int idx) SSL_CTX_free(cctx); return testresult; } + +static int un_ext_add_cb(SSL *s, unsigned int ext_type, + unsigned int context, const unsigned char **out, size_t *outlen, X509 *x, + size_t chainidx, int *al, void *add_arg) +{ + static const unsigned char data[] = { 0xaa }; + *out = data; + *outlen = sizeof(data); + return 1; +} + +static int un_ext_parse_cb(SSL *s, unsigned int ext_type, + unsigned int context, const unsigned char *in, size_t inlen, X509 *x, + size_t chainidx, int *al, void *parse_arg) +{ + return 1; +} + +/* + * Test that a handshake succeeds when the peer sends an extension type we do + * not recognise. The client registers a custom extension in its ClientHello + * that the server knows nothing about, so on the server tls_collect_extensions() + * takes the "unknown extension" branch. + */ +static int test_tls13_unknown_extension(void) +{ + SSL_CTX *s = NULL, *c = NULL; + SSL *s_ssl = NULL, *c_ssl = NULL; + int test; + + test = TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_3_VERSION, TLS1_3_VERSION, &s, &c, cert, privkey)) + && TEST_true(SSL_CTX_add_custom_ext(c, 0xfefe, SSL_EXT_CLIENT_HELLO, + un_ext_add_cb, NULL, NULL, un_ext_parse_cb, NULL)) + && TEST_true(create_ssl_objects(s, c, &s_ssl, &c_ssl, NULL, NULL)) + /* The server must tolerate the unknown extension and complete. */ + && TEST_true(create_ssl_connection(s_ssl, c_ssl, SSL_ERROR_NONE)); + + SSL_free(s_ssl); + SSL_free(c_ssl); + SSL_CTX_free(s); + SSL_CTX_free(c); + return test; +} + #endif /* OSSL_NO_USABLE_TLS1_3 */ #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) @@ -14312,6 +14357,7 @@ int setup_tests(void) #ifndef OSSL_NO_USABLE_TLS1_3 ADD_TEST(test_read_ahead_key_change); ADD_ALL_TESTS(test_tls13_record_padding, 6); + ADD_TEST(test_tls13_unknown_extension); #endif #if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3) ADD_ALL_TESTS(test_serverinfo_custom, 4); From 8533c807eddc5e841cf478b414bab54b8c0e696c Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 7 Jul 2026 12:32:13 +0200 Subject: [PATCH 071/189] Document the effect of SSL_VERIFY_FAIL_IF_NO_PEER_CERT on post-handshake auth Reviewed-by: Matt Caswell Reviewed-by: Paul Dale MergeDate: Fri Jul 10 15:45:39 2026 (Merged from https://github.com/openssl/openssl/pull/31876) (cherry picked from commit 3bf2aba5f5e2e602b7b72b71d91e3befb08e9e94) --- doc/man3/SSL_CTX_set_verify.pod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod index 58774796cd921..1a9ef7d83e323 100644 --- a/doc/man3/SSL_CTX_set_verify.pod +++ b/doc/man3/SSL_CTX_set_verify.pod @@ -74,7 +74,9 @@ SSL_CTX_set_client_cert_cb() if no certificate is provided at initialization. SSL_verify_client_post_handshake() causes a CertificateRequest message to be sent by a server on the given B connection. The SSL_VERIFY_PEER flag must -be set; the SSL_VERIFY_POST_HANDSHAKE flag is optional. +be set; the SSL_VERIFY_POST_HANDSHAKE flag is optional. The +SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag is also applicable and has the same +effect as with the client authentication during the handshake. =head1 NOTES From f63a2e98b22883f79a5411fe68dab59400c24fe5 Mon Sep 17 00:00:00 2001 From: Naveed Khan Date: Sat, 4 Jul 2026 22:39:47 +0530 Subject: [PATCH 072/189] pkcs12: free PKCS7 elements on error in PKCS12_unpack_authsafes Fixes: b536880c4572 "Add library context and property query support into the PKCS12 API" Reviewed-by: Shane Lontis Reviewed-by: Eugene Syromiatnikov MergeDate: Fri Jul 10 15:48:37 2026 (Merged from https://github.com/openssl/openssl/pull/31862) (cherry picked from commit b1393a04464eaf8b769bb6dc606d36a7734e73aa) --- crypto/pkcs12/p12_add.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c index 4750974d60443..938e6eb842602 100644 --- a/crypto/pkcs12/p12_add.c +++ b/crypto/pkcs12/p12_add.c @@ -222,6 +222,6 @@ STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) } return p7s; err: - sk_PKCS7_free(p7s); + sk_PKCS7_pop_free(p7s, PKCS7_free); return NULL; } From 3687ff719503ffc6d29c97d77e00199251890774 Mon Sep 17 00:00:00 2001 From: Marc Gutman Date: Thu, 9 Jul 2026 15:23:28 -0500 Subject: [PATCH 073/189] Don't raise NOT_ENOUGH_DATA on a clean EOF at an object boundary asn1_d2i_read_bio() reads one ASN.1 object at a time from a BIO. Callers commonly loop, decoding concatenated DER values until the call fails, and rely on a failure with no queued error to recognise a clean end of input. CPython's ssl module does this in _add_ca_certs() when loading the Windows certificate store via SSLContext.load_verify_locations(cadata=...); it re-raises any leftover ASN.1 error other than ASN1_R_HEADER_TOO_LONG as fatal. Commit 9eb6922c59 ("asn1: raise NOT_ENOUGH_DATA on header EOF") changed the BIO_read() check from "i < 0" to "i <= 0", so a clean EOF (BIO_read() returning 0, as an exhausted BIO_new_mem_buf does) on an object boundary now raises ASN1_R_NOT_ENOUGH_DATA instead of failing with an empty error queue. The rewrite in commit 35852da1d9 carried this behaviour forward. As a result Python 3 on Windows fails to initialise an SSLContext with: ssl.SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data Raise ASN1_R_NOT_ENOUGH_DATA only on an actual read error, on an EOF in the middle of an object (some bytes already buffered), or on an EOF while still inside an indefinite-length value awaiting its end-of-contents octets - all of which are genuine truncation. A clean EOF at a top-level object boundary again fails without queuing an error, restoring the long-standing behaviour that looping callers depend on. Add regression tests covering the clean-EOF, truncated, indefinite-length truncation and partial-header cases, and document the read behaviour in ASN1_item_d2i_bio(3). Fixes #31807 Assisted-by: Claude:claude-opus-4-8 Reviewed-by: Dmitry Belyavskiy Reviewed-by: Igor Ustinov Reviewed-by: Tomas Mraz MergeDate: Mon Jul 13 08:05:03 2026 (Merged from https://github.com/openssl/openssl/pull/31818) (cherry picked from commit d7e77b66cabb770932091ed5986221e0d1e57144) --- crypto/asn1/a_d2i_fp.c | 15 ++- doc/man3/ASN1_item_d2i_bio.pod | 18 +++- test/asn1_decode_test.c | 165 +++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 2 deletions(-) diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index a23dea8ebda2e..19595683ef982 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -139,7 +139,20 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) } i = BIO_read(in, &(b->data[len]), want); if (i <= 0) { - ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA); + /* + * A read error (i < 0), an EOF in the middle of an object + * (diff != 0, some bytes already buffered), or an EOF while + * still inside an indefinite-length constructed value awaiting + * its end-of-contents octets (eos != 0) all mean the input is + * truncated. Only a clean EOF at a top-level object boundary + * (i == 0, diff == 0, eos == 0) is the normal end of input: + * fail without queuing an error so that callers looping over + * concatenated DER values (e.g. the libcrypto d2i_*_bio() + * consumers in CPython's ssl module) terminate cleanly instead + * of seeing a spurious ASN1_R_NOT_ENOUGH_DATA. + */ + if (i < 0 || diff != 0 || eos != 0) + ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA); goto err; } if (i > 0) { diff --git a/doc/man3/ASN1_item_d2i_bio.pod b/doc/man3/ASN1_item_d2i_bio.pod index f8e4678367ef8..9b3f389a23fd1 100644 --- a/doc/man3/ASN1_item_d2i_bio.pod +++ b/doc/man3/ASN1_item_d2i_bio.pod @@ -59,6 +59,16 @@ B provided in the I parameter and the property query string in I. See L for more information about algorithm fetching. +When reading from I, decoding consumes one complete DER-encoded structure +and leaves any following bytes in the BIO, so concatenated structures can be +read with successive calls. Reaching the end of the input cleanly, at a +structure boundary, is not treated as an error: the function returns NULL +without adding to the error queue. If the end of the input is reached in the +middle of a structure, or an indefinite-length value is missing its +end-of-contents octets (that is, the input is truncated), an error is queued +with reason code B. The same applies to +ASN1_item_d2i_fp_ex(). + ASN1_item_d2i_bio() is the same as ASN1_item_d2i_bio_ex() except that the default B is used (i.e. NULL) and with a NULL property query string. @@ -92,6 +102,12 @@ that the I and I can be used when doing algorithm fetching. ASN1_item_d2i_bio(), ASN1_item_unpack_ex() and ASN1_item_unpack() return a pointer to an B or NULL on error. +The ASN1_item_d2i_bio() and ASN1_item_d2i_fp() functions, including their +B<_ex> variants, also return NULL at a clean end of input. In that case the +error queue is left unchanged, so a caller reading concatenated structures in +a loop can distinguish a clean end of input from a decoding error by +inspecting the error queue, for example with L. + ASN1_item_i2d_mem_bio() returns a pointer to a memory BIO or NULL on error. ASN1_item_pack() returns a pointer to an B or NULL on error. @@ -105,7 +121,7 @@ The function ASN1_item_unpack_ex() was added in OpenSSL 3.2. =head1 COPYRIGHT -Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2026 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/test/asn1_decode_test.c b/test/asn1_decode_test.c index 6e00d40896927..8a9629c21dc30 100644 --- a/test/asn1_decode_test.c +++ b/test/asn1_decode_test.c @@ -14,7 +14,11 @@ #include #include #include +#include +#include +#include #include "internal/numbers.h" +#include "internal/asn1.h" #include "testutil.h" #ifdef __GNUC__ @@ -266,6 +270,163 @@ static int test_reuse_asn1_object(void) return ret; } +/* + * A minimal, complete DER object: SEQUENCE { INTEGER 0 }. + * asn1_d2i_read_bio() should consume exactly these bytes. + */ +static const unsigned char one_obj[] = { + 0x30, 0x03, /* SEQUENCE, length 3 */ + 0x02, 0x01, 0x00 /* INTEGER 0 */ +}; + +/* + * Reading concatenated DER objects from a BIO must stop cleanly at EOF: + * once the input is exhausted on an object boundary, asn1_d2i_read_bio() + * returns < 0 and must NOT leave an error on the queue. Callers that loop + * over concatenated values (e.g. CPython's ssl module loading the Windows + * certificate store via d2i_X509_bio()) rely on this to detect end-of-input; + * a spurious ASN1_R_NOT_ENOUGH_DATA there is reported as a fatal error. + */ +static int test_d2i_read_bio_clean_eof(void) +{ + unsigned char two_objs[sizeof(one_obj) * 2]; + BIO *bio = NULL; + BUF_MEM *buf = NULL; + int ret = 0; + + memcpy(two_objs, one_obj, sizeof(one_obj)); + memcpy(two_objs + sizeof(one_obj), one_obj, sizeof(one_obj)); + + if (!TEST_ptr(bio = BIO_new_mem_buf(two_objs, sizeof(two_objs)))) + goto err; + ERR_clear_error(); + + /* Both complete objects are read, one per call. */ + if (!TEST_int_eq(asn1_d2i_read_bio(bio, &buf), (int)sizeof(one_obj))) + goto err; + BUF_MEM_free(buf); + buf = NULL; + if (!TEST_int_eq(asn1_d2i_read_bio(bio, &buf), (int)sizeof(one_obj))) + goto err; + BUF_MEM_free(buf); + buf = NULL; + + /* Clean EOF: failure return, but no error must be queued. */ + if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) + goto err; + if (!TEST_ulong_eq(ERR_peek_error(), 0)) + goto err; + + ret = 1; +err: + BUF_MEM_free(buf); + BIO_free(bio); + return ret; +} + +/* + * In contrast, hitting EOF in the middle of an object is genuine truncation + * and must still be reported as ASN1_R_NOT_ENOUGH_DATA. + */ +static int test_d2i_read_bio_truncated(void) +{ + static const unsigned char truncated[] = { + 0x30, 0x05, /* SEQUENCE claims 5 content bytes ... */ + 0x02, 0x01 /* ... but only 2 are present */ + }; + BIO *bio = NULL; + BUF_MEM *buf = NULL; + unsigned long e; + int ret = 0; + + if (!TEST_ptr(bio = BIO_new_mem_buf(truncated, sizeof(truncated)))) + goto err; + ERR_clear_error(); + + if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) + goto err; + e = ERR_peek_last_error(); + if (!TEST_int_eq(ERR_GET_LIB(e), ERR_LIB_ASN1) + || !TEST_int_eq(ERR_GET_REASON(e), ASN1_R_NOT_ENOUGH_DATA)) + goto err; + + ret = 1; +err: + BUF_MEM_free(buf); + BIO_free(bio); + return ret; +} + +/* + * An EOF reached while still inside an indefinite-length constructed value, + * before its end-of-contents octets, is truncation too (not a clean boundary), + * so it must also report ASN1_R_NOT_ENOUGH_DATA rather than an empty queue. + */ +static int test_d2i_read_bio_indefinite_truncated(void) +{ + /* SEQUENCE (indefinite) { INTEGER 0 } with the 00 00 EOC missing */ + static const unsigned char truncated_indefinite[] = { + 0x30, 0x80, /* SEQUENCE, indefinite length */ + 0x02, 0x01, 0x00 /* INTEGER 0; no end-of-contents octets follow */ + }; + BIO *bio = NULL; + BUF_MEM *buf = NULL; + unsigned long e; + int ret = 0; + + bio = BIO_new_mem_buf(truncated_indefinite, sizeof(truncated_indefinite)); + if (!TEST_ptr(bio)) + goto err; + ERR_clear_error(); + + if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) + goto err; + e = ERR_peek_last_error(); + if (!TEST_int_eq(ERR_GET_LIB(e), ERR_LIB_ASN1) + || !TEST_int_eq(ERR_GET_REASON(e), ASN1_R_NOT_ENOUGH_DATA)) + goto err; + + ret = 1; +err: + BUF_MEM_free(buf); + BIO_free(bio); + return ret; +} + +/* + * An EOF reached part-way through an object's header, with some header bytes + * already buffered, is truncation as well. This exercises the "diff != 0" arm + * of the header-read check (distinct from the body read handled elsewhere). + */ +static int test_d2i_read_bio_partial_header(void) +{ + /* SEQUENCE with a 2-byte long-form length, but only one length byte given */ + static const unsigned char partial_header[] = { + 0x30, 0x82, 0x01 /* SEQUENCE, length declared as 2 bytes, 1 present */ + }; + BIO *bio = NULL; + BUF_MEM *buf = NULL; + unsigned long e; + int ret = 0; + + if (!TEST_ptr(bio = BIO_new_mem_buf(partial_header, sizeof(partial_header)))) + goto err; + ERR_clear_error(); + + if (!TEST_int_lt(asn1_d2i_read_bio(bio, &buf), 0)) + goto err; + e = ERR_peek_last_error(); + if (!TEST_int_eq(ERR_GET_LIB(e), ERR_LIB_ASN1) + || !TEST_int_eq(ERR_GET_REASON(e), ASN1_R_NOT_ENOUGH_DATA)) + goto err; + + ret = 1; +err: + BUF_MEM_free(buf); + BIO_free(bio); + return ret; +} + int setup_tests(void) { #ifndef OPENSSL_NO_DEPRECATED_3_0 @@ -279,5 +440,9 @@ int setup_tests(void) ADD_TEST(test_utctime); ADD_TEST(test_invalid_template); ADD_TEST(test_reuse_asn1_object); + ADD_TEST(test_d2i_read_bio_clean_eof); + ADD_TEST(test_d2i_read_bio_truncated); + ADD_TEST(test_d2i_read_bio_indefinite_truncated); + ADD_TEST(test_d2i_read_bio_partial_header); return 1; } From 4e070342fecc2e059b3ca454d88e537d5effe797 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 6 Jul 2026 11:29:42 -0400 Subject: [PATCH 074/189] Remove the rio_notifier run_once routine We do this odd thing in rio_notifier. when we initalize it, we call a run_once routine to call WSAStartup(), create a lock and init a refcount. The purpose of those last two items is to track the refcount so that we record how many times we init that rio notifier. when the refcount reaches zero, we tear down the windows socket api by calling WSA cleanup, destroy the lock and refcount, and then re-initzlize the run_once gate. That last step is sketchy. Even though our implementations of run_once allow doing so, we should never be re-initing those gates, as its going to be very prone to races, and they are, well, run_once, so we should only run them once. It would be nice to get rid of that behavior, which we can fortunately do. https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsastartup Indicates that WSAStartup is internally refcounted, so instead of just calling it once and tracking when we need to correspondingly call WSACleanup(), just call it every time we initalize an rio_notifier object, and call WSACleanup when we tear it down. The Winsock api will take care of knowing when it actually needs to be cleaned up for us. As such we can eliminate the run_once routine, the refcount and the lock entirely. Reviewed-by: Bob Beck Reviewed-by: Nikola Pajkovsky MergeDate: Mon Jul 13 14:26:58 2026 (Merged from https://github.com/openssl/openssl/pull/31777) (cherry picked from commit f1be99832fcb614f24c68a7888a7d0269268ad00) --- ssl/rio/rio_notifier.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ssl/rio/rio_notifier.c b/ssl/rio/rio_notifier.c index ea40790d627bd..5dd42537e877c 100644 --- a/ssl/rio/rio_notifier.c +++ b/ssl/rio/rio_notifier.c @@ -10,7 +10,6 @@ #include "internal/sockets.h" #include #include -#include "internal/thread_once.h" #include "internal/rio_notifier.h" /* @@ -28,32 +27,29 @@ static int set_cloexec(int fd) #if defined(OPENSSL_SYS_WINDOWS) -static CRYPTO_ONCE ensure_wsa_startup_once = CRYPTO_ONCE_STATIC_INIT; -static int wsa_started; - static void ossl_wsa_cleanup(void) { - if (wsa_started) { - wsa_started = 0; - WSACleanup(); - } + WSACleanup(); } -DEFINE_RUN_ONCE_STATIC(do_wsa_startup) +static int do_wsa_startup(void) { WORD versionreq = 0x0202; /* Version 2.2 */ WSADATA wsadata; if (WSAStartup(versionreq, &wsadata) != 0) return 0; - wsa_started = 1; - OPENSSL_atexit(ossl_wsa_cleanup); return 1; } static ossl_inline int ensure_wsa_startup(void) { - return RUN_ONCE(&ensure_wsa_startup_once, do_wsa_startup); + return do_wsa_startup(); +} + +static void wsa_done(void) +{ + ossl_wsa_cleanup(); } #endif From 648fadb9334110e221746fa127c43d431e925149 Mon Sep 17 00:00:00 2001 From: slontis Date: Mon, 29 Jun 2026 09:50:07 +1000 Subject: [PATCH 075/189] FIPS: EC keygen - remove unnecessary self tests. In FIPS mode EC keygen was doing 3 self tests. ec_generate_key() was calling both ecdsa_keygen_pairwise_test() and ecdsa_keygen_knownanswer_test(). The KAT did a key recomputation and comparison with the generated key, as per Sp80056Ar3 section 5.6.2.1.4. These tests covered both Keygen PCT for Key Agreement and Signatures. ossl_ec_key_pairwise_check() was also being called from within ec_gen(). The advice from Atsec (lab) is that the sign/verify test within ecdsa_keygen_pairwise_test() is sufficient according to the updated rules in FIPS 140-3 IG 10.3.A Additional comment 1, Since the usage of the generated key is unknown at the time of key generation. Detected during testing of Jipher by Roshith Alankandy (Oracle). Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz MergeDate: Mon Jul 13 14:47:00 2026 (Merged from https://github.com/openssl/openssl/pull/31761) (cherry picked from commit 79373ca3bd4c26e9a4896e4c198828909cc6deec) --- crypto/ec/ec_key.c | 53 +------------------- providers/implementations/keymgmt/ec_kmgmt.c | 14 ------ test/pairwise_fail_test.c | 2 - test/recipes/30-test_pairwise_fail.t | 10 +--- 4 files changed, 3 insertions(+), 76 deletions(-) diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 8723ead41e0e7..d57ac22d5857f 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -236,56 +236,6 @@ int ossl_ec_key_gen(EC_KEY *eckey) return ret; } -/* - * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1 - * Perform a KAT by duplicating the public key generation. - * - * NOTE: This issue requires a background understanding, provided in a separate - * document; the current IG 10.3.A AC1 is insufficient regarding the PCT for - * the key agreement scenario. - * - * Currently IG 10.3.A requires PCT in the mode of use prior to use of the - * key pair, citing the PCT defined in the associated standard. For key - * agreement, the only PCT defined in SP 800-56A is that of Section 5.6.2.4: - * the comparison of the original public key to a newly calculated public key. - */ -static int ecdsa_keygen_knownanswer_test(EC_KEY *eckey, BN_CTX *ctx, - OSSL_CALLBACK *cb, void *cbarg) -{ - int len, ret = 0; - OSSL_SELF_TEST *st = NULL; - unsigned char bytes[512] = { 0 }; - EC_POINT *pub_key2 = NULL; - - st = OSSL_SELF_TEST_new(cb, cbarg); - if (st == NULL) - return 0; - - OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT_KAT, - OSSL_SELF_TEST_DESC_PCT_ECDSA); - - if ((pub_key2 = EC_POINT_new(eckey->group)) == NULL) - goto err; - - /* pub_key = priv_key * G (where G is a point on the curve) */ - if (!EC_POINT_mul(eckey->group, pub_key2, eckey->priv_key, NULL, NULL, ctx)) - goto err; - - if (BN_num_bytes(pub_key2->X) > (int)sizeof(bytes)) - goto err; - len = BN_bn2bin(pub_key2->X, bytes); - if (OSSL_SELF_TEST_oncorrupt_byte(st, bytes) - && BN_bin2bn(bytes, len, pub_key2->X) == NULL) - goto err; - ret = !EC_POINT_cmp(eckey->group, eckey->pub_key, pub_key2, ctx); - -err: - OSSL_SELF_TEST_onend(st, ret); - OSSL_SELF_TEST_free(st); - EC_POINT_free(pub_key2); - return ret; -} - /* * ECC Key generation. * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates" @@ -382,8 +332,7 @@ static int ec_generate_key(EC_KEY *eckey, int pairwise_test) void *cbarg = NULL; OSSL_SELF_TEST_get_callback(eckey->libctx, &cb, &cbarg); - ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg) - && ecdsa_keygen_knownanswer_test(eckey, ctx, cb, cbarg); + ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg); } err: /* Step (9): If there is an error return an invalid keypair. */ diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 305dc3a6b831d..aa5b3f43870f0 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -1298,20 +1298,6 @@ static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) if (gctx->group_check != NULL) ret = ret && ossl_ec_set_check_group_type_from_name(ec, gctx->group_check); -#ifdef FIPS_MODULE - if (ret > 0 - && !ossl_fips_self_testing() - && EC_KEY_get0_public_key(ec) != NULL - && EC_KEY_get0_private_key(ec) != NULL - && EC_KEY_get0_group(ec) != NULL) { - BN_CTX *bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec)); - - ret = bnctx != NULL && ossl_ec_key_pairwise_check(ec, bnctx); - BN_CTX_free(bnctx); - if (ret <= 0) - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); - } -#endif /* FIPS_MODULE */ if (ret) return ec; diff --git a/test/pairwise_fail_test.c b/test/pairwise_fail_test.c index 3173225a0c852..3446d23166e52 100644 --- a/test/pairwise_fail_test.c +++ b/test/pairwise_fail_test.c @@ -99,8 +99,6 @@ static int test_keygen_pairwise_failure(void) if (!TEST_ptr_null(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", (size_t)2048))) goto err; } else if (strncmp(pairwise_name, "ec", 2) == 0) { - if (strcmp(pairwise_name, "eckat") == 0) - type = OSSL_SELF_TEST_TYPE_PCT_KAT; if (!TEST_true(setup_selftest_pairwise_failure(type))) goto err; if (!TEST_ptr_null(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-256"))) diff --git a/test/recipes/30-test_pairwise_fail.t b/test/recipes/30-test_pairwise_fail.t index eaf0dbbb424f8..ca2d1f96e497c 100644 --- a/test/recipes/30-test_pairwise_fail.t +++ b/test/recipes/30-test_pairwise_fail.t @@ -22,7 +22,7 @@ use lib bldtop_dir('.'); plan skip_all => "These tests are unsupported in a non fips build" if disabled("fips"); -plan tests => 9; +plan tests => 8; my $provconf = srctop_file("test", "fips-and-base.cnf"); run(test(["fips_version_test", "-config", $provconf, ">=3.1.0"]), @@ -37,17 +37,11 @@ SKIP: { } SKIP: { - skip "Skip EC test because of no ec in this build", 2 + skip "Skip EC test because of no ec in this build", 1 if disabled("ec"); ok(run(test(["pairwise_fail_test", "-config", $provconf, "-pairwise", "ec"])), "fips provider ec keygen pairwise failure test"); - - skip "FIPS provider version is too old", 1 - if !$fips_exit; - ok(run(test(["pairwise_fail_test", "-config", $provconf, - "-pairwise", "eckat"])), - "fips provider ec keygen kat failure test"); } SKIP: { From b71cd13b0d9d13ec830323eeaa1322a6ea7f6c10 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 3 Jun 2026 23:44:22 +0900 Subject: [PATCH 076/189] poly1305: reject no-key update and NULL key params Poly1305 permits EVP_MAC_init(ctx, NULL, 0, ...) as part of staged initialization. If no key has been installed, update still dispatched into the uninitialized Poly1305 state, which can crash on POLY1305_ASM builds. Guard update with the same key_set check used by final and report no key set. Also reject an explicit OSSL_MAC_PARAM_KEY whose data pointer is NULL before calling Poly1305_Init(), even when the supplied size is POLY1305_KEY_SIZE. Fixes #31332 Reviewed-by: Dmitry Belyavskiy Reviewed-by: Daniel Kubec MergeDate: Mon Jul 13 15:44:48 2026 (Merged from https://github.com/openssl/openssl/pull/31382) (cherry picked from commit 95f95b59dded1ad376458152e4c8533018ee2f43) --- .../implementations/macs/poly1305_prov.c | 6 +- test/evp_extra_test.c | 69 ++++++++++++++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/providers/implementations/macs/poly1305_prov.c b/providers/implementations/macs/poly1305_prov.c index 22ff0a2837391..69d4444a58d7c 100644 --- a/providers/implementations/macs/poly1305_prov.c +++ b/providers/implementations/macs/poly1305_prov.c @@ -82,7 +82,7 @@ static size_t poly1305_size(void) static int poly1305_setkey(struct poly1305_data_st *ctx, const unsigned char *key, size_t keylen) { - if (keylen != POLY1305_KEY_SIZE) { + if (key == NULL || keylen != POLY1305_KEY_SIZE) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); return 0; } @@ -111,6 +111,10 @@ static int poly1305_update(void *vmacctx, const unsigned char *data, { struct poly1305_data_st *ctx = vmacctx; + if (!ctx->key_set) { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return 0; + } ctx->updated = 1; if (datalen == 0) return 1; diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 9a5f8f9fddbcf..fff83c3eccfa2 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -2229,20 +2229,83 @@ static int test_EVP_md_null(void) } #ifndef OPENSSL_NO_POLY1305 -/* Test that EVP_MAC_final fails for Poly1305 when no key was set */ +/* Test Poly1305 no-key failures and staged key initialization */ static int test_evp_mac_poly1305_no_key(void) { int ret = 0; EVP_MAC *mac = NULL; EVP_MAC_CTX *ctx = NULL; + /* RFC 7539 Poly1305 test vector. */ + static const unsigned char staged_data[] = "Cryptographic Forum Research Group"; + static const unsigned char expected[16] = { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }; + unsigned char no_key_data[16] = { 0 }; + unsigned char key[32] = { + 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, + 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b + }; unsigned char out[16]; + OSSL_PARAM key_params[2]; + OSSL_PARAM null_key_params[2]; size_t outl = 0; + key_params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + key, sizeof(key)); + key_params[1] = OSSL_PARAM_construct_end(); + null_key_params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + NULL, sizeof(key)); + null_key_params[1] = OSSL_PARAM_construct_end(); + if (!TEST_ptr(mac = EVP_MAC_fetch(testctx, "Poly1305", testpropq)) || !TEST_ptr(ctx = EVP_MAC_CTX_new(mac)) - || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1) - || !TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 0)) + || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1)) + goto err; + + ERR_clear_error(); + if (!TEST_int_eq(EVP_MAC_update(ctx, no_key_data, sizeof(no_key_data)), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NO_KEY_SET)) + goto err; + + /* The failed update must not block staged key initialization. */ + if (!TEST_int_eq(EVP_MAC_CTX_set_params(ctx, key_params), 1) + || !TEST_int_eq(EVP_MAC_update(ctx, staged_data, + sizeof(staged_data) - 1), + 1) + || !TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 1) + || !TEST_size_t_eq(outl, sizeof(expected)) + || !TEST_mem_eq(out, outl, expected, sizeof(expected))) + goto err; + + EVP_MAC_CTX_free(ctx); + ctx = NULL; + + if (!TEST_ptr(ctx = EVP_MAC_CTX_new(mac)) + || !TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, NULL), 1)) + goto err; + + ERR_clear_error(); + if (!TEST_int_eq(EVP_MAC_final(ctx, out, &outl, sizeof(out)), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_NO_KEY_SET)) + goto err; + + ERR_clear_error(); + if (!TEST_int_eq(EVP_MAC_init(ctx, NULL, 0, null_key_params), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), + PROV_R_INVALID_KEY_LENGTH)) goto err; + + ERR_clear_error(); + if (!TEST_int_eq(EVP_MAC_CTX_set_params(ctx, null_key_params), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), + PROV_R_INVALID_KEY_LENGTH)) + goto err; + + EVP_MAC_CTX_free(ctx); + ctx = NULL; ret = 1; err: EVP_MAC_CTX_free(ctx); From 1d6826bf9fd513d1e277f76633401395a6a1cada Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 12 Jul 2026 15:02:35 +0200 Subject: [PATCH 077/189] test: don't depend on DTLS alert delivery in sslrecords test The unknown-record-type tests (tests 5 and 6) inferred failure of a DTLS connection from TLSProxy's socket-teardown timing ($proxy_start_success == 0). This relied on the client's fatal alert reaching the peer before the client closes its socket, which is a race: DTLS alerts are best-effort and are never retransmitted (RFC 6347 section 4.2.7 / RFC 9147 section 5.10), and after the s_client shutdown drain was skipped for datagram protocols the alert can be lost during teardown, making the test flaky. Verify instead what is actually under test: that the DTLS client rejected the unrecognised record type, i.e. that s_client exited with a failure. This is a deterministic, local decision that does not depend on the alert being observed by the peer. Keep the alert observation as a best-effort diagnostic note. Capture the s_client exit status in TLSProxy (previously discarded after waitpid) and expose it via a new clientexit accessor. Assisted-by: Claude:claude-opus-4-8 Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz MergeDate: Sat Jul 18 12:54:59 2026 (Merged from https://github.com/openssl/openssl/pull/31927) --- test/recipes/70-test_sslrecords.t | 10 ++++++++-- util/perl/TLSProxy/Proxy.pm | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/test/recipes/70-test_sslrecords.t b/test/recipes/70-test_sslrecords.t index 299ecb60bea1f..3dc7762b606ad 100644 --- a/test/recipes/70-test_sslrecords.t +++ b/test/recipes/70-test_sslrecords.t @@ -208,7 +208,12 @@ sub run_tests $proxy_start_success = $proxy->start(); if ($run_test_as_dtls == 1) { - ok($proxy_start_success == 0, "Unrecognised record type in DTLS1.2"); + # DTLS alerts are best-effort (RFC 6347 section 4.2.7): the client's + # fatal alert may be lost, so we cannot rely on observing it. What we + # verify is that the client rejected the connection, i.e. exited with a + # failure. Whether we happened to see the alert is only diagnostic. + ok($proxy->clientexit != 0, "Unrecognised record type in DTLS1.2"); + note("client fatal alert observed") if $fatal_alert; } else { ok($fatal_alert, "Unrecognised record type in TLS1.2"); } @@ -228,7 +233,8 @@ sub run_tests $proxy->ciphers("AES128-SHA:\@SECLEVEL=0"); $proxy_start_success = $proxy->start(); if ($run_test_as_dtls == 1) { - ok($proxy_start_success == 0, "Unrecognised record type in DTLSv1"); + ok($proxy->clientexit != 0, "Unrecognised record type in DTLSv1"); + note("client fatal alert observed") if $fatal_alert; } else { ok($fatal_alert, "Unrecognised record type in TLSv1.1"); } diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm index c3db4e28db0f8..d2fda702bfaf9 100644 --- a/util/perl/TLSProxy/Proxy.pm +++ b/util/perl/TLSProxy/Proxy.pm @@ -177,6 +177,7 @@ sub init server_port => 0, serverpid => 0, clientpid => 0, + clientexit => 0, execute => $execute, cert => $cert, debug => $debug, @@ -215,6 +216,7 @@ sub clearClient $self->{clientflags} = ""; $self->{sessionfile} = undef; $self->{clientpid} = 0; + $self->{clientexit} = 0; $is_tls13 = 0; $ciphersuite = undef; @@ -585,6 +587,7 @@ sub clientstart $pid = $self->{clientpid}; print "Waiting for s_client process to close: $pid...\n"; waitpid($pid, 0); + $self->{clientexit} = $?; return $success; } @@ -722,6 +725,11 @@ sub clientpid my $self = shift; return $self->{clientpid}; } +sub clientexit +{ + my $self = shift; + return $self->{clientexit}; +} #Read/write accessors sub filter From 67baa1daae4067ca2c48a28c283386c87478d451 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 1 Jul 2026 23:43:18 +0900 Subject: [PATCH 078/189] x509: avoid NULL memcmp argument in nc_dn() An empty directoryName constraint has canon_enc == NULL and canon_enclen == 0. nc_dn() must not pass that pointer to memcmp(), even with a zero length. Return X509_V_OK before comparing an empty base Name. This preserves current match semantics and avoids UBSan-visible undefined behaviour. Fixes #31687 Fixes #31688 Reviewed-by: Paul Dale Reviewed-by: Daniel Kubec MergeDate: Fri Jul 10 15:51:01 2026 (cherry picked from commit fce540139a7cf4de64d9ce8e17b9180778e12f4e) Reviewed-by: Frederik Wedel-Heinen (Merged from https://github.com/openssl/openssl/pull/31921) --- crypto/x509/v3_ncons.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c index 1af2c8682046d..a22531a71043e 100644 --- a/crypto/x509/v3_ncons.c +++ b/crypto/x509/v3_ncons.c @@ -613,6 +613,12 @@ static int nc_dn(const X509_NAME *nm, const X509_NAME *base) return X509_V_ERR_OUT_OF_MEM; if (base->canon_enclen > nm->canon_enclen) return X509_V_ERR_PERMITTED_VIOLATION; + /* + * An empty base Name has no canonical encoding (canon_enc == NULL) and is + * a prefix of every Name, so it matches unconditionally. + */ + if (base->canon_enclen == 0) + return X509_V_OK; if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen)) return X509_V_ERR_PERMITTED_VIOLATION; return X509_V_OK; From 41502f7bc53f5b3621dc14f0342ad25424f99d9e Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 1 Jul 2026 23:43:18 +0900 Subject: [PATCH 079/189] test: cover empty directoryName name constraints Add NAME_CONSTRAINTS_check() coverage for empty directoryName subtrees in both excluded and permitted constraints. The tests assert the existing results in ordinary builds and catch the NULL memcmp() argument when run under UBSan. Reviewed-by: Paul Dale Reviewed-by: Daniel Kubec MergeDate: Fri Jul 10 15:51:03 2026 (cherry picked from commit 7f4ac8022492a54aedd0100af4e624600d60c590) Reviewed-by: Frederik Wedel-Heinen (Merged from https://github.com/openssl/openssl/pull/31921) --- test/x509_test.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/test/x509_test.c b/test/x509_test.c index 37928c5f008fe..62e7de79a818d 100644 --- a/test/x509_test.c +++ b/test/x509_test.c @@ -10,6 +10,7 @@ #define OPENSSL_SUPPRESS_DEPRECATED /* EVP_PKEY_get1/set1_RSA */ #include +#include #include #include #include @@ -299,6 +300,101 @@ static int test_x509_revoked_delete_last_extension(void) return ret; } +/* + * nameConstraints extnValue contents with one empty directoryName subtree. + * Empty X509_NAME has canon_enc == NULL / canon_enclen == 0. + * + * SEQUENCE { [0|1] { SEQUENCE { [4] { SEQUENCE {} } } } } + */ +static const unsigned char nc_excluded_empty_dirname[] = { + 0x30, 0x08, 0xa1, 0x06, 0x30, 0x04, 0xa4, 0x02, 0x30, 0x00 +}; +static const unsigned char nc_permitted_empty_dirname[] = { + 0x30, 0x08, 0xa0, 0x06, 0x30, 0x04, 0xa4, 0x02, 0x30, 0x00 +}; + +/* Decode a raw nameConstraints extnValue into a NAME_CONSTRAINTS object. */ +static NAME_CONSTRAINTS *nc_empty_dirname_from_der(const unsigned char *der, + unsigned int der_len) +{ + NAME_CONSTRAINTS *nc = NULL; + ASN1_OCTET_STRING *os = NULL; + X509_EXTENSION *ext = NULL; + + os = ASN1_OCTET_STRING_new(); + if (!TEST_ptr(os) + || !TEST_true(ASN1_OCTET_STRING_set(os, der, der_len))) + goto end; + ext = X509_EXTENSION_create_by_NID(NULL, NID_name_constraints, + 1 /* critical */, os); + if (!TEST_ptr(ext)) + goto end; + nc = X509V3_EXT_d2i(ext); + +end: + X509_EXTENSION_free(ext); + ASN1_OCTET_STRING_free(os); + return nc; +} + +/* Build a minimal certificate with a non-empty subject DN. */ +static X509 *nc_empty_dirname_subject(const char *cn) +{ + X509 *x = NULL; + X509_NAME *nm = NULL; + + if (!TEST_ptr(x = X509_new())) + goto err; + nm = X509_NAME_new(); + if (!TEST_ptr(nm) + || !TEST_true(X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, + (const unsigned char *)cn, -1, -1, 0)) + || !TEST_true(X509_set_subject_name(x, nm))) + goto err; + X509_NAME_free(nm); + return x; + +err: + X509_NAME_free(nm); + X509_free(x); + return NULL; +} + +/* Check an empty directoryName constraint against a non-empty subject DN. */ +static int nc_check_empty_dirname(const unsigned char *der, unsigned int der_len, + int expected) +{ + int ok = 0; + NAME_CONSTRAINTS *nc = NULL; + X509 *x = NULL; + + if (!TEST_ptr(nc = nc_empty_dirname_from_der(der, der_len)) + || !TEST_ptr(x = nc_empty_dirname_subject("leaf.example")) + || !TEST_int_eq(NAME_CONSTRAINTS_check(x, nc), expected)) + goto end; + + ok = 1; + +end: + X509_free(x); + NAME_CONSTRAINTS_free(nc); + return ok; +} + +/* Empty excluded directoryName matches the subject DN: excluded violation. */ +static int test_nc_empty_dirname_excluded(void) +{ + return nc_check_empty_dirname(nc_excluded_empty_dirname, + sizeof(nc_excluded_empty_dirname), X509_V_ERR_EXCLUDED_VIOLATION); +} + +/* Empty permitted directoryName matches the subject DN: permitted. */ +static int test_nc_empty_dirname_permitted(void) +{ + return nc_check_empty_dirname(nc_permitted_empty_dirname, + sizeof(nc_permitted_empty_dirname), X509_V_OK); +} + OPT_TEST_DECLARE_USAGE("\n") int setup_tests(void) @@ -337,6 +433,8 @@ int setup_tests(void) ADD_TEST(test_x509_crl_delete_last_extension); ADD_TEST(test_x509_revoked_delete_last_extension); ADD_TEST(test_x509_verify_with_new); + ADD_TEST(test_nc_empty_dirname_excluded); + ADD_TEST(test_nc_empty_dirname_permitted); return 1; } From eb069037197efa27f75fff90c8651be852755aca Mon Sep 17 00:00:00 2001 From: olszomal Date: Fri, 12 Jun 2026 10:52:05 +0200 Subject: [PATCH 080/189] doc: clarify pkeyutl -rawin and -digest for no-prehash signatures Complements: 5421423 "Flexible encoders for ML-DSA" Signed-off-by: olszomal Reviewed-by: Tomas Mraz Reviewed-by: Daniel Kubec MergeDate: Mon Jul 20 09:13:52 2026 (Merged from https://github.com/openssl/openssl/pull/31478) --- doc/man1/openssl-pkeyutl.pod.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in index 46b62952590e2..7a84d24b1277a 100644 --- a/doc/man1/openssl-pkeyutl.pod.in +++ b/doc/man1/openssl-pkeyutl.pod.in @@ -683,8 +683,10 @@ L, =head1 HISTORY Since OpenSSL 3.5, -the B<-digest> option implies B<-rawin>, and these two options are -no longer required when signing or verifying with an Ed25519 or Ed448 key. +the B<-digest> option implies B<-rawin>. The B<-rawin> option is no longer +required when signing or verifying with a key type that does not support a +prehash digest, such as Ed25519, Ed448, ML-DSA, or SLH-DSA. For these key +types, B<-digest> is not supported. Also since OpenSSL 3.5, the B<-kemop> option is no longer required for any of the supported algorithms, the only supported B is now the default. From 96158be18c776d936dcb391119cba3a5d59ee08c Mon Sep 17 00:00:00 2001 From: Loganaden Velvindron Date: Thu, 2 Jul 2026 09:13:45 +0400 Subject: [PATCH 081/189] ml_kem: Add a check for shared_secret Reviewed-by: Viktor Dukhovni Reviewed-by: Paul Dale Reviewed-by: Tim Hudson MergeDate: Mon Jul 20 11:28:26 2026 (Merged from https://github.com/openssl/openssl/pull/31822) --- crypto/ml_kem/ml_kem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c index 1bc3c0a0a8909..41a3a43d759fe 100644 --- a/crypto/ml_kem/ml_kem.c +++ b/crypto/ml_kem/ml_kem.c @@ -2296,11 +2296,13 @@ int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen, #endif /* Need a private key here */ - if (!ossl_ml_kem_have_prvkey(key)) + if (!ossl_ml_kem_have_prvkey(key) + || shared_secret == NULL + || slen < ML_KEM_SHARED_SECRET_BYTES) return 0; vinfo = key->vinfo; - if (shared_secret == NULL || slen != ML_KEM_SHARED_SECRET_BYTES + if (slen != ML_KEM_SHARED_SECRET_BYTES || ctext == NULL || clen != vinfo->ctext_bytes || (mdctx = EVP_MD_CTX_new()) == NULL) { (void)RAND_bytes_ex(key->libctx, shared_secret, From 0925384d85ba921b74fe2b64561d64d88b5a8b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20M=C3=BCllner?= Date: Fri, 10 Apr 2026 02:22:52 +0200 Subject: [PATCH 082/189] crypto: use void * in RISC-V digest shims MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RISC-V MD5 and SHA dispatch files use low-level digest context types that are hidden in no-deprecated builds. Switch their shim entry points to void * so they no longer depend on deprecated typed interfaces. Update the local MD5 declaration to match the untyped shim interface. Fixes: openssl/openssl#29357 Signed-off-by: Christoph Müllner Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz MergeDate: Thu Jul 23 15:43:30 2026 (Merged from https://github.com/openssl/openssl/pull/30763) (cherry picked from commit 4499e9abe162d6ef7a6600cd6573681572e431a7) --- crypto/sha/sha_riscv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/sha/sha_riscv.c b/crypto/sha/sha_riscv.c index 61ceaa22a4bd8..fb05fa886447a 100644 --- a/crypto/sha/sha_riscv.c +++ b/crypto/sha/sha_riscv.c @@ -17,9 +17,9 @@ void sha256_block_data_order_zvkb_zvknha_or_zvknhb(void *ctx, const void *in, size_t num); void sha256_block_data_order_c(void *ctx, const void *in, size_t num); -void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num); +void sha256_block_data_order(void *ctx, const void *in, size_t num); -void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num) +void sha256_block_data_order(void *ctx, const void *in, size_t num) { if (RISCV_HAS_ZVKB() && (RISCV_HAS_ZVKNHA() || RISCV_HAS_ZVKNHB()) && riscv_vlen() >= 128) { sha256_block_data_order_zvkb_zvknha_or_zvknhb(ctx, in, num); @@ -30,9 +30,9 @@ void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num) void sha512_block_data_order_zvkb_zvknhb(void *ctx, const void *in, size_t num); void sha512_block_data_order_c(void *ctx, const void *in, size_t num); -void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num); +void sha512_block_data_order(void *ctx, const void *in, size_t num); -void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num) +void sha512_block_data_order(void *ctx, const void *in, size_t num) { if (RISCV_HAS_ZVKB_AND_ZVKNHB() && riscv_vlen() >= 128) { sha512_block_data_order_zvkb_zvknhb(ctx, in, num); From dc616dec77fb42a164c547e7da1377ae37dd6480 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Sat, 20 Jun 2026 00:28:36 +1000 Subject: [PATCH 083/189] Improve TLS handling of EC point formats (4.0) The ec_point_formats extension no longer plays any role in EC certificate selection or acceptance: tls1_check_pkey_comp() with its callers in tls1_check_cert_param(), tls12_check_peer_sigalg() and tls1_check_chain() are removed. TLS 1.3 disregards ec_point_formats already, and we can decode any form a peer might send, so refusing a compressed peer cert in TLS 1.2 because we didn't advertise compressed buys nothing. A new 33-compressed-spki ssl_new test verifies that a compressed EC leaf certificate handshakes at both TLS 1.2 and TLS 1.3 without either side opting into LegacyECPointFormats. Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz MergeDate: Fri Jul 24 08:27:31 2026 (Merged from https://github.com/openssl/openssl/pull/31620) --- ssl/t1_lib.c | 59 ----------------- test/certs/server-ec-compressed-cert.pem | 12 ++++ test/certs/server-ec-compressed-key.pem | 5 ++ test/recipes/80-test_ssl_new.t | 4 +- test/ssl-tests/33-compressed-spki.cnf | 76 ++++++++++++++++++++++ test/ssl-tests/33-compressed-spki.cnf.in | 81 ++++++++++++++++++++++++ 6 files changed, 177 insertions(+), 60 deletions(-) create mode 100644 test/certs/server-ec-compressed-cert.pem create mode 100644 test/certs/server-ec-compressed-key.pem create mode 100644 test/ssl-tests/33-compressed-spki.cnf create mode 100644 test/ssl-tests/33-compressed-spki.cnf.in diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index e3268e1a952d5..a4d212c2550f0 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1817,53 +1817,6 @@ void tls1_get_formatlist(SSL_CONNECTION *s, const unsigned char **pformats, } } -/* Check a key is compatible with compression extension */ -static int tls1_check_pkey_comp(SSL_CONNECTION *s, EVP_PKEY *pkey) -{ - unsigned char comp_id; - size_t i; - int point_conv; - - /* If not an EC key nothing to check */ - if (!EVP_PKEY_is_a(pkey, "EC")) - return 1; - - /* Get required compression id */ - point_conv = EVP_PKEY_get_ec_point_conv_form(pkey); - if (point_conv == 0) - return 0; - if (point_conv == POINT_CONVERSION_UNCOMPRESSED) { - comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; - } else if (SSL_CONNECTION_IS_TLS13(s)) { - /* - * ec_point_formats extension is not used in TLSv1.3 so we ignore - * this check. - */ - return 1; - } else { - int field_type = EVP_PKEY_get_field_type(pkey); - - if (field_type == NID_X9_62_prime_field) - comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; - else if (field_type == NID_X9_62_characteristic_two_field) - comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; - else - return 0; - } - /* - * If point formats extension present check it, otherwise everything is - * supported (see RFC4492). - */ - if (s->ext.peer_ecpointformats == NULL) - return 1; - - for (i = 0; i < s->ext.peer_ecpointformats_len; i++) { - if (s->ext.peer_ecpointformats[i] == comp_id) - return 1; - } - return 0; -} - /* Return group id of a key */ static uint16_t tls1_get_group_id(EVP_PKEY *pkey) { @@ -1888,9 +1841,6 @@ static int tls1_check_cert_param(SSL_CONNECTION *s, X509 *x, int check_ee_md) /* If not EC nothing to do */ if (!EVP_PKEY_is_a(pkey, "EC")) return 1; - /* Check compression */ - if (!tls1_check_pkey_comp(s, pkey)) - return 0; group_id = tls1_get_group_id(pkey); /* * For a server we allow the certificate to not be in our list of supported @@ -2788,13 +2738,6 @@ int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t sig, EVP_PKEY *pkey) if (pkeyid == EVP_PKEY_EC) { - /* Check point compression is permitted */ - if (!tls1_check_pkey_comp(s, pkey)) { - SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, - SSL_R_ILLEGAL_POINT_COMPRESSION); - return 0; - } - /* For TLS 1.3 or Suite B check curve matches signature algorithm */ if (SSL_CONNECTION_IS_TLS13(s) || tls1_suiteb(s)) { int curve = ssl_get_EC_curve_nid(pkey); @@ -4057,8 +4000,6 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk, chain = cpk->chain; strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT; if (tls12_rpk_and_privkey(s, idx)) { - if (EVP_PKEY_is_a(pk, "EC") && !tls1_check_pkey_comp(s, pk)) - return 0; *pvalid = rv = CERT_PKEY_RPK; return rv; } diff --git a/test/certs/server-ec-compressed-cert.pem b/test/certs/server-ec-compressed-cert.pem new file mode 100644 index 0000000000000..4e97f49af2503 --- /dev/null +++ b/test/certs/server-ec-compressed-cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBrzCCATSgAwIBAgIBAjAKBggqhkjOPQQDAjAbMRkwFwYDVQQDDBBFQ0RTQSBQ +LTM4NCByb290MCAXDTI2MDYxOTE4MDA1OFoYDzIxMjYwNTI2MTgwMDU4WjAZMRcw +FQYDVQQDDA5zZXJ2ZXIuZXhhbXBsZTA5MBMGByqGSM49AgEGCCqGSM49AwEHAyIA +A4Mt9T6fKt3APp8/Frw65PDi2eMYdZK98nhBW9pA1Ccho4GIMIGFMB0GA1UdDgQW +BBTozN8kakexZEnc26PUo5K2W9ptbTAfBgNVHSMEGDAWgBQm0I8de1/cHn9BgH1j +yhx1gdaFaTAJBgNVHRMEAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD +AjAZBgNVHREEEjAQgg5zZXJ2ZXIuZXhhbXBsZTAKBggqhkjOPQQDAgNpADBmAjEA +hvcNLTyL7vamQEJet5uvOXH7NKPHlG8sbfPvGS/AQ0yk6ARdc1Y1gV6FAnmnQUhX +AjEA2HMTkh+h2ZDm68uRnhsNXIxI4dYF/nr5bdxw8XKN4P84Mg4gs37/IPoVN9jG +Y4yh +-----END CERTIFICATE----- diff --git a/test/certs/server-ec-compressed-key.pem b/test/certs/server-ec-compressed-key.pem new file mode 100644 index 0000000000000..98218fcb3cdee --- /dev/null +++ b/test/certs/server-ec-compressed-key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MGcCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcETTBLAgEBBCAb1VgxSUhJyh43soLb +FMsebjWSp/Hma3kSyw6lT4txDaEkAyIAA4Mt9T6fKt3APp8/Frw65PDi2eMYdZK9 +8nhBW9pA1Cch +-----END PRIVATE KEY----- diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index 44c674e46753d..95383108384b7 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -42,7 +42,7 @@ if (defined $ENV{SSL_TESTS}) { @conf_srcs = glob(srctop_file("test", "ssl-tests", "*.cnf.in")); # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. - plan tests => 31; + plan tests => 32; } map { s/;.*// } @conf_srcs if $^O eq "VMS"; my @conf_files = map { basename($_, ".in") } @conf_srcs; @@ -96,6 +96,7 @@ my %conf_dependent_tests = ( "28-seclevel.cnf" => disabled("tls1_2") || $no_ecx, "30-extended-master-secret.cnf" => disabled("tls1_2"), "32-compressed-certificate.cnf" => disabled("comp") || disabled("tls1_3"), + "33-compressed-spki.cnf" => disabled("tls1_2") || disabled("tls1_3") || $no_ec, ); # Add your test here if it should be skipped for some compile-time @@ -131,6 +132,7 @@ my %skip = ( "26-tls13_client_auth.cnf" => disabled("tls1_3") || ($no_ec && $no_dh), "29-dtls-sctp-label-bug.cnf" => disabled("sctp") || disabled("sock"), "32-compressed-certificate.cnf" => disabled("comp") || disabled("tls1_3"), + "33-compressed-spki.cnf" => disabled("tls1_2") || disabled("tls1_3") || $no_ec, ); foreach my $conf (@conf_files) { diff --git a/test/ssl-tests/33-compressed-spki.cnf b/test/ssl-tests/33-compressed-spki.cnf new file mode 100644 index 0000000000000..fd9816a27ef5d --- /dev/null +++ b/test/ssl-tests/33-compressed-spki.cnf @@ -0,0 +1,76 @@ +# Generated with generate_ssl_tests.pl + +num_tests = 2 + +test-0 = 0-tls12-compressed-spki +test-1 = 1-tls13-compressed-spki +# =========================================================== + +[0-tls12-compressed-spki] +ssl_conf = 0-tls12-compressed-spki-ssl + +[0-tls12-compressed-spki-ssl] +server = 0-tls12-compressed-spki-server +client = 0-tls12-compressed-spki-client + +[0-tls12-compressed-spki-server] +Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem +CipherString = DEFAULT +ClientCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem +MaxProtocol = TLSv1.2 +MinProtocol = TLSv1.2 +PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem +VerifyMode = Require + +[0-tls12-compressed-spki-client] +Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem +CipherString = ECDHE-ECDSA-AES128-GCM-SHA256 +MaxProtocol = TLSv1.2 +MinProtocol = TLSv1.2 +PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem +VerifyMode = Peer + +[test-0] +ExpectedClientCertType = P-256 +ExpectedProtocol = TLSv1.2 +ExpectedResult = Success +ExpectedServerCertType = P-256 + + +# =========================================================== + +[1-tls13-compressed-spki] +ssl_conf = 1-tls13-compressed-spki-ssl + +[1-tls13-compressed-spki-ssl] +server = 1-tls13-compressed-spki-server +client = 1-tls13-compressed-spki-client + +[1-tls13-compressed-spki-server] +Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem +CipherString = DEFAULT +ClientCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem +VerifyMode = Require + +[1-tls13-compressed-spki-client] +Certificate = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-cert.pem +CipherString = DEFAULT +MaxProtocol = TLSv1.3 +MinProtocol = TLSv1.3 +PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ec-compressed-key.pem +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem +VerifyMode = Peer + +[test-1] +ExpectedClientCertType = P-256 +ExpectedProtocol = TLSv1.3 +ExpectedResult = Success +ExpectedServerCertType = P-256 + + diff --git a/test/ssl-tests/33-compressed-spki.cnf.in b/test/ssl-tests/33-compressed-spki.cnf.in new file mode 100644 index 0000000000000..06302a46a99ed --- /dev/null +++ b/test/ssl-tests/33-compressed-spki.cnf.in @@ -0,0 +1,81 @@ +# -*- mode: perl; -*- +# Copyright 2026 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 + + +## End-to-end check that compressed-form EC leaf certificates +## (server-ec-compressed-cert.pem, P-256 named curve, SPKI bit-string +## leading byte 0x02 or 0x03, anchored to the P-384 EC root) work at +## both TLS 1.2 and TLS 1.3 in both directions: the client presents +## the same compressed leaf to a server that requires client +## authentication, exercising X.509 acceptance of compressed point +## form on both sides simultaneously. The ec_point_formats extension +## no longer affects X.509 cert selection or acceptance, so neither +## peer opts into LegacyECPointFormats; the default ec_point_formats +## lists ('uncompressed' only) and the compressed leaves coexist. + +package ssltests; +use OpenSSL::Test::Utils; + +our @tests = (); + +unless (disabled("ec") || disabled("tls1_2") || disabled("tls1_3")) { +@tests = ( + { + name => "tls12-compressed-spki", + server => { + "Certificate" => test_pem("server-ec-compressed-cert.pem"), + "PrivateKey" => test_pem("server-ec-compressed-key.pem"), + "VerifyCAFile" => test_pem("p384-root.pem"), + "ClientCAFile" => test_pem("p384-root.pem"), + "VerifyMode" => "Require", + "MinProtocol" => "TLSv1.2", + "MaxProtocol" => "TLSv1.2", + }, + client => { + "Certificate" => test_pem("server-ec-compressed-cert.pem"), + "PrivateKey" => test_pem("server-ec-compressed-key.pem"), + "VerifyCAFile" => test_pem("p384-root.pem"), + "MinProtocol" => "TLSv1.2", + "MaxProtocol" => "TLSv1.2", + "CipherString" => "ECDHE-ECDSA-AES128-GCM-SHA256", + }, + test => { + "ExpectedResult" => "Success", + "ExpectedProtocol" => "TLSv1.2", + "ExpectedServerCertType" => "P-256", + "ExpectedClientCertType" => "P-256", + }, + }, + + { + name => "tls13-compressed-spki", + server => { + "Certificate" => test_pem("server-ec-compressed-cert.pem"), + "PrivateKey" => test_pem("server-ec-compressed-key.pem"), + "VerifyCAFile" => test_pem("p384-root.pem"), + "ClientCAFile" => test_pem("p384-root.pem"), + "VerifyMode" => "Require", + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + client => { + "Certificate" => test_pem("server-ec-compressed-cert.pem"), + "PrivateKey" => test_pem("server-ec-compressed-key.pem"), + "VerifyCAFile" => test_pem("p384-root.pem"), + "MinProtocol" => "TLSv1.3", + "MaxProtocol" => "TLSv1.3", + }, + test => { + "ExpectedResult" => "Success", + "ExpectedProtocol" => "TLSv1.3", + "ExpectedServerCertType" => "P-256", + "ExpectedClientCertType" => "P-256", + }, + }, +); +} From 16b0f100e4348544ea05131a612d360bdbfc56f1 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 19 Jul 2026 10:10:14 +0900 Subject: [PATCH 084/189] Restore empty raw PKCS#1 verify-recover behavior EVP_PKEY_verify_recover() with RSA PKCS#1 v1.5 padding and no configured signature digest rejected a valid signature whose recovered payload is empty, instead of returning success with a recovered length of zero. RSA_public_decrypt() returns -1 on error and otherwise the number of recovered bytes, which may legitimately be zero for a raw PKCS#1 v1.5 signature that encodes an empty payload. Pull request #28306 ("Make error checks on RSA_public_decrypt() consistent") changed the error check in the raw, no-digest verify-recover path from "ret < 0" to "ret <= 0", so a valid zero recovered length was mistaken for an error. Restore the "< 0" check in that branch only, leaving the digest-aware PKCS#1, X9.31, PSS and ordinary verification paths untouched. Add test_RSA_verify_recover_empty_payload, which performs a complete zero-length raw PKCS#1 v1.5 sign-and-recover round trip through EVP and fails on the unmodified implementation specifically at the EVP_PKEY_verify_recover() call. OpenSSL 3.0.13 recovers the same signature and reports a zero-byte result. The behavior regressed as a result of #28306. Fixes #32000 Assisted-by: OpenCode:GLM-5.2 Reviewed-by: Paul Dale Reviewed-by: Jakub Zelenka MergeDate: Fri Jul 24 13:06:58 2026 (Merged from https://github.com/openssl/openssl/pull/32001) (cherry picked from commit 5f48317d6d847e555bf788f8b71d51ac032a6344) --- providers/implementations/signature/rsa_sig.c | 8 ++- test/evp_extra_test.c | 71 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c index 6790264a4705d..4980474ac03d8 100644 --- a/providers/implementations/signature/rsa_sig.c +++ b/providers/implementations/signature/rsa_sig.c @@ -1015,7 +1015,13 @@ static int rsa_verify_recover(void *vprsactx, } ret = RSA_public_decrypt((int)siglen, sig, rout, prsactx->rsa, prsactx->pad_mode); - if (ret <= 0) { + /* + * RSA_public_decrypt() returns -1 on error and otherwise the number + * of recovered bytes, which may legitimately be zero for a raw + * PKCS#1 v1.5 signature that encodes an empty payload. Treat only + * a negative result as an error. + */ + if (ret < 0) { ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB); return 0; } diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index fff83c3eccfa2..72cf0ea66d3de 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -4144,6 +4144,76 @@ static int test_RSA_verify_recover_rejects_short_buffer(void) return ret; } +/* + * A raw RSA PKCS#1 v1.5 signature whose recovered data is empty must be + * recovered successfully with a length of zero, not rejected as an error. + */ +static int test_RSA_verify_recover_empty_payload(void) +{ + int ret = 0; + int recovered_cap = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *sign_ctx = NULL, *verify_ctx = NULL; + unsigned char *sig = NULL, *recovered = NULL; + size_t sig_len = 0, recovered_len = 0; + /* + * The signed input has zero length, but a valid non-null address is still + * passed so the result does not depend on how lower layers treat NULL for + * zero-length data. + */ + const unsigned char empty[] = { 0 }; + + if (OSSL_PROVIDER_available(testctx, "fips")) + return TEST_skip("Test skipped for FIPS provider"); + + if (!TEST_ptr(pkey = load_example_rsa_key()) + || !TEST_ptr(sign_ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pkey, NULL)) + || !TEST_int_gt(EVP_PKEY_sign_init(sign_ctx), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_padding(sign_ctx, RSA_PKCS1_PADDING), 0) + /* + * Deliberately do not configure a signature digest so that the raw + * PKCS#1 v1.5 sign and verify-recover paths are exercised. + */ + || !TEST_int_gt(EVP_PKEY_sign(sign_ctx, NULL, &sig_len, empty, 0), 0) + || !TEST_ptr(sig = OPENSSL_malloc(sig_len)) + || !TEST_int_gt(EVP_PKEY_sign(sign_ctx, sig, &sig_len, empty, 0), 0) + || !TEST_int_gt(recovered_cap = EVP_PKEY_get_size(pkey), 0) + || !TEST_ptr(recovered = OPENSSL_malloc(recovered_cap)) + || !TEST_ptr(verify_ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pkey, NULL)) + || !TEST_int_gt(EVP_PKEY_verify_recover_init(verify_ctx), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_padding(verify_ctx, RSA_PKCS1_PADDING), + 0)) + goto done; + + /* Size-query call must succeed. */ + recovered_len = (size_t)recovered_cap; + if (!TEST_int_gt(EVP_PKEY_verify_recover(verify_ctx, NULL, + &recovered_len, sig, sig_len), + 0)) + goto done; + + /* + * The actual recovery call is essential: a NULL output buffer would only + * run the size-query path, which never decodes the signature and so would + * not reproduce the regression. + */ + recovered_len = (size_t)recovered_cap; + if (!TEST_int_gt(EVP_PKEY_verify_recover(verify_ctx, recovered, + &recovered_len, sig, sig_len), + 0) + || !TEST_size_t_eq(recovered_len, 0)) + goto done; + + ret = 1; +done: + EVP_PKEY_CTX_free(sign_ctx); + EVP_PKEY_CTX_free(verify_ctx); + EVP_PKEY_free(pkey); + OPENSSL_free(sig); + OPENSSL_free(recovered); + return ret; +} + static int test_RSA_encrypt(void) { int ret = 0; @@ -7814,6 +7884,7 @@ int setup_tests(void) ADD_TEST(test_RSA_OAEP_set_get_params); ADD_TEST(test_RSA_OAEP_set_null_label); ADD_TEST(test_RSA_verify_recover_rejects_short_buffer); + ADD_TEST(test_RSA_verify_recover_empty_payload); ADD_TEST(test_RSA_encrypt); #ifndef OPENSSL_NO_DEPRECATED_3_0 ADD_TEST(test_RSA_legacy); From f8da3aa370b1c267a2edaa335e74e0073bd658ce Mon Sep 17 00:00:00 2001 From: Brady Foster <209960252+bef15703@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:44:18 -0400 Subject: [PATCH 085/189] Update SSL_CTX_set1_curves.pod for OpenSSL 3.5 additions Added documentation of the addition of group tuples in openSSL 3.5 in HISTORY section of SSL_CTX_set1_curves.pod. CLA: trivial Reviewed-by: Viktor Dukhovni Reviewed-by: Nikola Pajkovsky MergeDate: Fri Jul 24 13:13:26 2026 (Merged from https://github.com/openssl/openssl/pull/32007) (cherry picked from commit 971b8d060e52499d6ffd2f9ca697fe23f72a629a) --- doc/man3/SSL_CTX_set1_curves.pod | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/man3/SSL_CTX_set1_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod index 3fc0b8f3309b0..1a9231e6e2c98 100755 --- a/doc/man3/SSL_CTX_set1_curves.pod +++ b/doc/man3/SSL_CTX_set1_curves.pod @@ -379,6 +379,10 @@ SSL_set1_groups_list() was added in OpenSSL 3.3. Support for B was added in OpenSSL 3.5. +OpenSSL 3.5 also introduced support for group tuples, the C<*> keyshare +prediction prefix, the C tuple separator, the C pseudo-group, +and the C<-> prefix. + OpenSSL 3.5 also introduces support for three I ECDH PQ key exchange TLS groups: B, B and B. From 3a1c8d428328f628d3ae4842fc237128e6dabc73 Mon Sep 17 00:00:00 2001 From: olszomal Date: Wed, 22 Jul 2026 12:34:07 +0200 Subject: [PATCH 086/189] DOCS: Fix KEM init function documentation Document the missing params argument for OSSL_FUNC_kem_decapsulate_init(), remove stale name references, and fix the malformed provider-keymgmt(7) link. Complements: 78c44b05945b Add HPKE DHKEM provider support for EC, X25519 and X448. Signed-off-by: olszomal Reviewed-by: Jakub Zelenka Reviewed-by: Paul Dale MergeDate: Mon Jul 27 07:57:36 2026 (Merged from https://github.com/openssl/openssl/pull/32045) --- doc/man7/provider-kem.pod | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/doc/man7/provider-kem.pod b/doc/man7/provider-kem.pod index 85b8f1a6b80aa..943f2b69dc319 100644 --- a/doc/man7/provider-kem.pod +++ b/doc/man7/provider-kem.pod @@ -32,7 +32,8 @@ provider-kem - The kem library E-E provider functions unsigned char *secret, size_t *secretlen); /* Decapsulation */ - int OSSL_FUNC_kem_decapsulate_init(void *ctx, void *provkey); + int OSSL_FUNC_kem_decapsulate_init(void *ctx, void *provkey, + const OSSL_PARAM params[]); int OSSL_FUNC_kem_auth_decapsulate_init(void *ctx, void *provkey, void *provauthkey, const OSSL_PARAM params[]); @@ -129,13 +130,13 @@ context in the I parameter and return the duplicate copy. OSSL_FUNC_kem_encapsulate_init() initialises a context for an asymmetric encapsulation given a provider side asymmetric kem context in the I -parameter, a pointer to a provider key object in the I parameter and -the I of the algorithm. +parameter, a pointer to a provider key object in the I parameter. + The I, if not NULL, should be set on the context in a manner similar to using OSSL_FUNC_kem_set_ctx_params(). The key object should have been previously generated, loaded or imported into the provider using the key management (OSSL_OP_KEYMGMT) operation (see -provider-keymgmt(7)>. +L. OSSL_FUNC_kem_auth_encapsulate_init() is similar to OSSL_FUNC_kem_encapsulate_init(), but also passes an additional authentication @@ -159,11 +160,13 @@ written to I<*secretlen>. OSSL_FUNC_kem_decapsulate_init() initialises a context for an asymmetric decapsulation given a provider side asymmetric kem context in the I -parameter, a pointer to a provider key object in the I parameter, and -a I of the algorithm. +parameter, a pointer to a provider key object in the I parameter. + +The I, if not NULL, should be set on the context in a manner similar to +using OSSL_FUNC_kem_set_ctx_params(). The key object should have been previously generated, loaded or imported into the provider using the key management (OSSL_OP_KEYMGMT) operation (see -provider-keymgmt(7)>. +L. OSSL_FUNC_kem_auth_decapsulate_init() is similar to OSSL_FUNC_kem_decapsulate_init(), but also passes an additional authentication From e23b59ee33101699e38bf44632b4cc72d64ad3f0 Mon Sep 17 00:00:00 2001 From: Adel-Ayoub Date: Fri, 3 Jul 2026 17:47:50 +0100 Subject: [PATCH 087/189] crypto/pkcs12/p12_decr.c: fix EVP_CIPHER_CTX_ctrl error checks EVP_CIPHER_CTX_ctrl() reports failure of the EVP_CTRL_AEAD_TLS1_AAD and EVP_CTRL_AEAD_SET_TAG controls as 0, not as a negative value, so the "< 0" checks on the cipher-with-MAC path cannot detect any failure. A return of 0 means a failed or unsupported control, or for EVP_CTRL_AEAD_TLS1_AAD a zero MAC length, none of which is usable here. Change both checks to "<= 0", matching the EVP_CTRL_AEAD_GET_TAG check fixed by commit 674c23d2656e in this function. Follow-up to https://github.com/openssl/openssl/pull/30923. Fixes: ea0add4a8227 "New GOST PKCS12 standard support" CLA: trivial Reviewed-by: Dmitry Belyavskiy Reviewed-by: Andrew Dinh Reviewed-by: Jakub Zelenka MergeDate: Mon Jul 27 10:25:25 2026 (Merged from https://github.com/openssl/openssl/pull/31848) --- crypto/pkcs12/p12_decr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c index 0d415e755a183..31766989fc4a0 100644 --- a/crypto/pkcs12/p12_decr.c +++ b/crypto/pkcs12/p12_decr.c @@ -55,7 +55,8 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor, if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx)) & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) { - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) < 0) { + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) + <= 0) { ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR); goto err; } @@ -70,7 +71,7 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor, inlen -= mac_len; if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)mac_len, (unsigned char *)in + inlen) - < 0) { + <= 0) { ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR); goto err; } From ae3e2ad8afc509180e29bc952ca3c965bb788fc6 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 25 Jun 2026 17:15:16 +0100 Subject: [PATCH 088/189] SSL_poll: fix abort_blocking mishandling in poll_translate()/poll_block() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When SSL_poll() has to block, poll_translate() registers each item's QUIC connection for cross-thread notification one item at a time. If an item turns out to already be ready right as it is being registered, translation sets abort_blocking and is meant to bail out so the caller retries the readout instead of actually blocking. Two bugs in that abort path: - poll_translate() returned immediately on abort_blocking without calling postpoll_translation_cleanup() for any earlier items that had already had their blocking section entered. Those items' enter/leave calls were left unbalanced, leaking into the QUIC reactor's blocking-waiter count. Fixed by routing through the existing "out" cleanup label, mirroring what the FAIL_ITEM()/error path already does for items 0..i-1. - poll_block() initializes ok = 0 and only ever sets it on the actual poll() success path. The abort_blocking branch jumped straight to "out" without setting ok, so SSL_poll() reported failure even though nothing actually went wrong; the caller's retry loop never got a chance to pick up the now-ready item. Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Saša Nedvědický Reviewed-by: Paul Yang MergeDate: Wed Jul 29 07:20:31 2026 (Merged from https://github.com/openssl/openssl/pull/31743) (cherry picked from commit d6ca7796bf66f65d0c69cb0c0806ed38ce3f3105) --- ssl/rio/poll_immediate.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/ssl/rio/poll_immediate.c b/ssl/rio/poll_immediate.c index 24b82f3a6a438..edb39b2a6c16e 100644 --- a/ssl/rio/poll_immediate.c +++ b/ssl/rio/poll_immediate.c @@ -233,7 +233,7 @@ static int poll_translate(SSL_POLL_ITEM *items, FAIL_ITEM(i); if (*abort_blocking) - return 1; + goto out; if (!SSL_get_event_timeout(ssl, &timeout, &is_infinite)) FAIL_ITEM(i++); /* need to clean up this item too */ @@ -271,7 +271,12 @@ static int poll_translate(SSL_POLL_ITEM *items, } out: - if (!ok) + /* + * On abort_blocking, the item which triggered the abort has already + * balanced its own enter/leave of the blocking section (see + * poll_translate_ssl_quic()); only items 0..i-1 still need cleanup here. + */ + if (!ok || *abort_blocking) postpoll_translation_cleanup(items, i, stride, wctx); *p_earliest_wakeup_deadline = earliest_wakeup_deadline; @@ -320,8 +325,15 @@ static int poll_block(SSL_POLL_ITEM *items, p_result_count)) goto out; - if (abort_blocking) + if (abort_blocking) { + /* + * Nothing actually failed; we just shouldn't block because an item + * may have become ready while we were setting up. The caller's + * retry loop will call poll_readout() again to pick this up. + */ + ok = 1; goto out; + } earliest_wakeup_deadline = ossl_time_min(earliest_wakeup_deadline, user_deadline); From ed4d218bcce525bcd292356e2527d0aa506239e6 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 26 Jun 2026 09:36:25 +0100 Subject: [PATCH 089/189] test: add regression test for SSL_poll() abort_blocking handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The race fixed by the previous commit (an item becoming ready in the window between poll_translate() registering it for cross-thread notification and the OS-level poll) is normally vanishingly narrow and not practical to hit by timing alone in a test. Add ossl_quic_poll_translate_test_step_cb, a test-only instrumentation hook (always NULL in production use) that poll_translate() calls between translating consecutive items. This lets a test deterministically make one item ready while an earlier item's blocking section is still entered, exercising the abort_blocking path on demand. Add the poll_abort_blocking RADIX script/test, which uses the hook to trigger this on two independent QUIC connections (so the second item's reactor is provably distinct from the first's) and checks that SSL_poll() reports success and that the first item's blocking-section entry is correctly balanced afterwards. Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Saša Nedvědický Reviewed-by: Paul Yang MergeDate: Wed Jul 29 07:20:33 2026 (Merged from https://github.com/openssl/openssl/pull/31743) (cherry picked from commit 524dd6c010a6c92b532d7febe903c4f8634f22f1) --- ssl/rio/poll_builder.h | 13 +++ ssl/rio/poll_immediate.c | 11 +++ test/radix/quic_tests.c | 176 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) diff --git a/ssl/rio/poll_builder.h b/ssl/rio/poll_builder.h index 1fe13eacbaba4..0fcd543b5935b 100644 --- a/ssl/rio/poll_builder.h +++ b/ssl/rio/poll_builder.h @@ -76,4 +76,17 @@ int ossl_rio_poll_builder_poll(RIO_POLL_BUILDER *rpb, OSSL_TIME deadline); * it is currently not needed. */ +#ifndef OPENSSL_NO_QUIC +/* + * Test instrumentation only. If set, poll_translate() (see poll_immediate.c) + * calls this with the index of each item immediately before translating it, + * once all earlier items (if any) have finished translation. This lets + * tests inject a readiness change into the gap between translation of + * consecutive items, in order to deterministically exercise the + * abort-blocking path. Always NULL in production use. + */ +extern void (*ossl_quic_poll_translate_test_step_cb)(size_t idx, void *arg); +extern void *ossl_quic_poll_translate_test_step_cb_arg; +#endif + #endif diff --git a/ssl/rio/poll_immediate.c b/ssl/rio/poll_immediate.c index edb39b2a6c16e..6807926f1ae28 100644 --- a/ssl/rio/poll_immediate.c +++ b/ssl/rio/poll_immediate.c @@ -49,6 +49,13 @@ } while (0) #ifndef OPENSSL_NO_QUIC +/* + * Test instrumentation only; see poll_builder.h. Always NULL in production + * use. + */ +void (*ossl_quic_poll_translate_test_step_cb)(size_t idx, void *arg) = NULL; +void *ossl_quic_poll_translate_test_step_cb_arg = NULL; + static int poll_translate_ssl_quic(SSL *ssl, QUIC_REACTOR_WAIT_CTX *wctx, RIO_POLL_BUILDER *rpb, @@ -216,6 +223,10 @@ static int poll_translate(SSL_POLL_ITEM *items, for (i = 0; i < num_items; ++i) { item = &ITEM_N(items, stride, i); + if (ossl_quic_poll_translate_test_step_cb != NULL) + ossl_quic_poll_translate_test_step_cb(i, + ossl_quic_poll_translate_test_step_cb_arg); + switch (item->desc.type) { case BIO_POLL_DESCRIPTOR_TYPE_SSL: ssl = item->desc.value.ssl; diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c index 50ce9e1b4229e..fd24e13507177 100644 --- a/test/radix/quic_tests.c +++ b/test/radix/quic_tests.c @@ -7,6 +7,9 @@ * https://www.openssl.org/source/license.html */ +#include "internal/quic_reactor.h" +#include "../../ssl/rio/poll_builder.h" + #if defined(_AIX) /* * Some versions of AIX define macros for events and revents for use when @@ -242,6 +245,178 @@ DEF_SCRIPT(ssl_poll, } } +/* + * Test: poll_abort_blocking + * ------------------------- + * + * SSL_poll(), when it has to block, registers each item's QUIC connection + * for cross-thread notification one item at a time (poll_translate() in + * ssl/rio/poll_immediate.c). If an item turns out to already be ready right + * as it is being registered, translation is aborted so the readout loop can + * retry instead of actually blocking. This exercises that abort path and + * checks that: + * + * - SSL_poll() reports success rather than spuriously failing, and + * - any items already registered before the abort have their blocking + * section correctly left (i.e. no leak in the QUIC reactor's blocking + * waiter count). + * + * The race between an item being registered and becoming ready is normally + * vanishingly narrow, so we use ossl_quic_poll_translate_test_step_cb (test + * instrumentation only, see ssl/rio/poll_builder.h) to deterministically + * make the second item ready immediately before poll_translate() processes + * it, while the first item is still mid-registration. + */ +struct poll_abort_test_ctx { + SSL *peer_writer; /* write here to make target ready */ + SSL *target; + uint64_t target_events; + size_t trigger_idx; + int made_ready; /* set by poll_abort_test_step_cb() on success */ +}; + +static void poll_abort_test_step_cb(size_t idx, void *arg) +{ + struct poll_abort_test_ctx *ctx = arg; + uint64_t revents = 0; + int i; + + if (idx != ctx->trigger_idx) + return; + + if (SSL_write(ctx->peer_writer, "x", 1) != 1) + return; + + /* Force the data through synchronously so target is ready by the time we return. */ + for (i = 0; i < 1000; ++i) { + if (!ossl_quic_conn_poll_events(ctx->target, ctx->target_events, + /* do_tick = */ 1, &revents)) + return; + + if (revents != 0) { + ctx->made_ready = 1; + return; + } + + OSSL_sleep(1); + } +} + +DEF_FUNC(check_poll_abort_blocking) +{ + int ok = 0; + SSL *C, *C0, *Cb0, *Lb0; + QUIC_CHANNEL *ch0; + QUIC_REACTOR *rtor0; + SSL_POLL_ITEM items[2] = { 0 }; + size_t result_count = SIZE_MAX, waiters_before, waiters_after; + struct poll_abort_test_ctx ctx; + const struct timeval z_timeout = { 0 }; + + /* + * C0 and Cb0 are streams of two independent client connections, and so + * belong to two independent QUIC_REACTORs. The bug being tested for does + * not actually require this: it reproduces just as well if all items + * share one reactor. What needs two reactors is poll_abort_test_step_cb() + * below, which forces Cb0 ready by ticking its reactor directly, on this + * thread, while C0's blocking section is still open. Doing that on C0's + * own (shared) reactor would deadlock: ossl_quic_reactor_tick() would see + * a nonzero cur_blocking_waiters left over from C0 and call + * rtor_notify_other_threads(), which waits on a condvar for some *other* + * thread to clear the notifier signal - a thread that doesn't exist here. + * Using Cb0's own, still-untouched reactor keeps that tick a no-op. + */ + REQUIRE_SSL_4(C, C0, Cb0, Lb0); + + items[0].desc = SSL_as_poll_descriptor(C0); + items[0].events = SSL_POLL_EVENT_R; + items[1].desc = SSL_as_poll_descriptor(Cb0); + items[1].events = SSL_POLL_EVENT_R; + + /* Sanity check: nothing ready yet, so SSL_poll() will need to block. */ + if (!TEST_true(SSL_poll(items, OSSL_NELEM(items), sizeof(SSL_POLL_ITEM), + &z_timeout, 0, &result_count)) + || !TEST_size_t_eq(result_count, 0)) + goto err; + + if (!TEST_ptr(ch0 = ossl_quic_conn_get_channel(C))) + goto err; + rtor0 = ossl_quic_channel_get_reactor(ch0); + waiters_before = rtor0->cur_blocking_waiters; + + ctx.peer_writer = Lb0; + ctx.target = Cb0; + ctx.target_events = items[1].events; + ctx.trigger_idx = 1; + ctx.made_ready = 0; + + ossl_quic_poll_translate_test_step_cb_arg = &ctx; + ossl_quic_poll_translate_test_step_cb = poll_abort_test_step_cb; + + result_count = SIZE_MAX; + /* + * No timeout: if the abort_blocking case were instead to actually block, + * this call would hang forever rather than fail fast. + */ + ok = TEST_true(SSL_poll(items, OSSL_NELEM(items), sizeof(SSL_POLL_ITEM), + NULL, 0, &result_count)); + + ossl_quic_poll_translate_test_step_cb = NULL; + ossl_quic_poll_translate_test_step_cb_arg = NULL; + + if (!ok) + goto err; + + ok = 0; + if (!TEST_true(ctx.made_ready) + || !TEST_size_t_ge(result_count, 1) + || !TEST_true((items[1].revents & SSL_POLL_EVENT_R) != 0)) + goto err; + + /* The first item's blocking-section entry must have been balanced. */ + waiters_after = rtor0->cur_blocking_waiters; + if (!TEST_size_t_eq(waiters_after, waiters_before)) + goto err; + + ok = 1; +err: + ossl_quic_poll_translate_test_step_cb = NULL; + ossl_quic_poll_translate_test_step_cb_arg = NULL; + return ok; +} + +DEF_SCRIPT(poll_abort_blocking, + "test that SSL_poll() correctly handles an item becoming ready while blocking is being set up") +{ + OP_SIMPLE_PAIR_CONN_ND(); + + OP_NEW_STREAM(C, C0, 0); + OP_WRITE_B(C0, "probe0"); + + OP_ACCEPT_CONN_WAIT1_ND(L, La, 0); + OP_ACCEPT_STREAM_WAIT(La, La0, 0); + OP_READ_EXPECT_B(La0, "probe0"); + + /* A second, independent client connection to the same listener. */ + OP_NEW_SSL_C(Cb); + OP_SET_PEER_ADDR_FROM(Cb, L); + OP_CONNECT_WAIT(Cb); + OP_SET_DEFAULT_STREAM_MODE(Cb, SSL_DEFAULT_STREAM_MODE_NONE); + + OP_NEW_STREAM(Cb, Cb0, 0); + OP_WRITE_B(Cb0, "probe1"); + + OP_ACCEPT_CONN_WAIT1_ND(L, Lb, 0); + OP_ACCEPT_STREAM_WAIT(Lb, Lb0, 0); + OP_READ_EXPECT_B(Lb0, "probe1"); + + OP_SELECT_SSL(0, C); + OP_SELECT_SSL(1, C0); + OP_SELECT_SSL(2, Cb0); + OP_SELECT_SSL(3, Lb0); + OP_FUNC(check_poll_abort_blocking); +} + DEF_FUNC(check_writeable) { int ok = 0; @@ -632,6 +807,7 @@ static SCRIPT_INFO *const scripts[] = { USE(simple_conn), USE(simple_thread), USE(ssl_poll), + USE(poll_abort_blocking), USE(check_cwm), USE(check_pc_flood), USE(check_ctx_cbks), From 4db90ebab383412fe2b7dc92a5b77bb19d0627ff Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 22 Jul 2026 09:13:18 +0100 Subject: [PATCH 090/189] Update CHANGES/NEWS to mention the HollowByte fix Add a previously missing CHANGES.md/NEWS.md entry for the Hollowbyte fix. Reviewed-by: Paul Dale Reviewed-by: Eugene Syromiatnikov Reviewed-by: Norbert Pocs MergeDate: Wed Jul 29 09:17:49 2026 (Merged from https://github.com/openssl/openssl/pull/32041) --- CHANGES.md | 14 ++++++++++++++ NEWS.md | 2 ++ 2 files changed, 16 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 1324b924e607b..edf00dc80f98e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -44,6 +44,20 @@ OpenSSL 3.5 ### Changes between 3.5.6 and 3.5.7 [9 Jun 2026] + * Fixed excessive allocation of the handshake message buffer (aka HollowByte) + + Previously, we would allocate a buffer large enough to hold the full size of + an incoming handshake message as advertised by the peer. This could be quite + large (although it is bounded, e.g. for ClientHello this is approximately + 128 KiB). If the peer then fails to send the full handshake message, then the + endpoint is left waiting for the remainder of the message to arrive and the + memory is still allocated (i.e. a Slowloris attack). To prevent this, we + incrementally grow the buffer as we receive the data. + + This issue was reported by Okta Red Team. + + *Matt Caswell* + * Fixed heap use-after-free in `PKCS7_verify()`. Severity: High diff --git a/NEWS.md b/NEWS.md index ef65780d2702b..d3c228eac929c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -82,6 +82,8 @@ This release incorporates the following bug fixes and mitigations: and AES-SIV modes. ([CVE-2026-45446]) + * Fixed excessive allocation of the handshake message buffer (aka HollowByte) + ### Major changes between OpenSSL 3.5.5 and OpenSSL 3.5.6 [7 Apr 2026] OpenSSL 3.5.6 is a security patch release. The most severe CVE fixed in this From 460cdd64b344bab0417f9a61beea0f29a029b315 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 27 Jul 2026 22:39:53 +0900 Subject: [PATCH 091/189] quic: fix BIO ownership in test helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SSL_set_bio() transfers ownership of cbio to the client SSL object. Clear the local pointer after the handoff so the error path does not release an SSL-owned reference before SSL_free(). Fixes #32084 Reviewed-by: Saša Nedvědický Reviewed-by: Daniel Kubec MergeDate: Wed Jul 29 09:55:49 2026 (Merged from https://github.com/openssl/openssl/pull/32086) --- test/helpers/quictestlib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index 164acc4007728..d10f4432784c3 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -311,6 +311,8 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, } SSL_set_bio(*cssl, cbio, cbio); + /* Ownership of cbio is now held by *cssl */ + cbio = NULL; if (!TEST_true(SSL_set_blocking_mode(*cssl, (flags & QTEST_FLAG_BLOCK) != 0 ? 1 : 0))) From cc56e924626c81ad9a2410fa06a286df97f5cf0f Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 15 Jul 2026 12:20:03 +0200 Subject: [PATCH 092/189] cms: fix AuthenticatedData authAttrs and unauthAttrs element type The CMS_AuthenticatedData ASN.1 template declared the authAttrs and unauthAttrs fields as X509_ALGOR, whereas per RFC 5652 section 9.1 they are [2] and [3] IMPLICIT SET OF Attribute and the CMS_AuthenticatedData structure already declares them as STACK_OF(X509_ATTRIBUTE). The implicit tags [2] and [3] were already correct, so only the element type was wrong. An Attribute (SEQUENCE { type, SET OF value }) is structurally accepted as an AlgorithmIdentifier (SEQUENCE { algorithm, ANY OPTIONAL }), so parsing did not fail; the attributes were merely misinterpreted, e.g. cms -cmsout -print rendered them as algorithm/parameter instead of decoding them as attributes. Use X509_ATTRIBUTE with the existing tags so the template matches the structure. Add a parse test using a BouncyCastle-generated AuthenticatedData message carrying an authenticated and an unauthenticated attribute, asserting both are decoded as SET OF Attribute. Assisted-by: Claude:claude-opus-4-8 Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale MergeDate: Wed Jul 29 10:49:45 2026 (Merged from https://github.com/openssl/openssl/pull/31960) --- crypto/cms/cms_asn1.c | 4 +-- test/recipes/80-test_cms.t | 25 ++++++++++++++++++- .../80-test_cms_data/authenticated_attrs.pem | 8 ++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 test/recipes/80-test_cms_data/authenticated_attrs.pem diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index fb87f6c6ad273..7fa90dfb3561b 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -257,9 +257,9 @@ ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = { ASN1_SIMPLE(CMS_AuthenticatedData, macAlgorithm, X509_ALGOR), ASN1_IMP(CMS_AuthenticatedData, digestAlgorithm, X509_ALGOR, 1), ASN1_SIMPLE(CMS_AuthenticatedData, encapContentInfo, CMS_EncapsulatedContentInfo), - ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ALGOR, 2), + ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ATTRIBUTE, 2), ASN1_SIMPLE(CMS_AuthenticatedData, mac, ASN1_OCTET_STRING), - ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ALGOR, 3) + ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ATTRIBUTE, 3) } static_ASN1_NDEF_SEQUENCE_END(CMS_AuthenticatedData) ASN1_NDEF_SEQUENCE(CMS_CompressedData) diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index ab86ef4bf2f63..0c6b301319ebe 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -53,7 +53,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) $no_rc2 = 1 if disabled("legacy"); -plan tests => 36; +plan tests => 37; ok(run(test(["pkcs7_test"])), "test pkcs7"); @@ -1004,6 +1004,29 @@ subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub { } }; +subtest "CMS parse authenticatedData authAttrs and unauthAttrs\n" => sub { + plan tests => 3; + + # BouncyCastle authenticatedData (HMAC-SHA256, KEK) carrying both an + # authenticated and an unauthenticated attribute. Per RFC 5652 these are + # SET OF Attribute, so with the CMS_AuthenticatedData template fixed to use + # X509_ATTRIBUTE they are rendered as attributes (object:/set:) rather than + # as an X509_ALGOR (algorithm:/parameter:) they were misparsed into before. + my $exit = 0; + my $dump = join "\n", + run(app(["openssl", "cms", @defaultprov, "-cmsout", "-noout", + "-print", "-inform", "PEM", + "-in", catfile($datadir, "authenticated_attrs.pem")]), + capture => 1, + statusvar => $exit); + + is($exit, 0, "parse authenticatedData with attributes"); + ok($dump =~ /authAttrs:.*?object:.*?1\.3\.6\.1\.4\.1\.5949\.99\.1.*?UTF8STRING:auth-attr-value/s, + "authAttrs parsed as SET OF Attribute"); + ok($dump =~ /unauthAttrs:.*?object:.*?1\.3\.6\.1\.4\.1\.5949\.99\.2.*?UTF8STRING:unauth-attr-value/s, + "unauthAttrs parsed as SET OF Attribute"); +}; + subtest "CAdES <=> CAdES consistency tests\n" => sub { plan tests => (scalar @smime_cms_cades_tests); diff --git a/test/recipes/80-test_cms_data/authenticated_attrs.pem b/test/recipes/80-test_cms_data/authenticated_attrs.pem new file mode 100644 index 0000000000000..4f3d212698011 --- /dev/null +++ b/test/recipes/80-test_cms_data/authenticated_attrs.pem @@ -0,0 +1,8 @@ +-----BEGIN CMS----- +MIAGCyqGSIb3DQEJEAECoIAwgAIBADFDokECAQQwBQQDwP7gMAsGCWCGSAFlAwQB +BQQoWM396pUOzWW6mFsNvr+XXTLufCrvzG3jiTOX+l3LpSXbXHhhpadw5DAMBggq +hkiG9w0CCQUAoQsGCWCGSAFlAwQCATCABgkqhkiG9w0BBwGggCSABB5IZWxsbyBB +dXRoZW50aWNhdGVkRGF0YSB3b3JsZAoAAAAAAACiIDAeBgkrBgEEAa49YwExEQwP +YXV0aC1hdHRyLXZhbHVlBCB9kCl8ic3e5461oodeDSyR7heZxtdN7G/N+oqerDIj +PqMiMCAGCSsGAQQBrj1jAjETDBF1bmF1dGgtYXR0ci12YWx1ZQAAAAAAAA== +-----END CMS----- From 7d87fe4d745cfe6a0e6d59c20264d96d672c96e7 Mon Sep 17 00:00:00 2001 From: Andrew Dinh Date: Fri, 24 Jul 2026 13:37:46 +0700 Subject: [PATCH 093/189] Fix mutcbk_inject_frames after mutation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mutcbk_inject_frames returned 0 once its one-time mutation was applied, which tells the QTX the packet send failed and tears down the connection instead of continuing the test with unmutated packets. Now it passes subsequent packets through unmodified by returning the input header, iovec, and count unchanged. Assisted-by: Claude:claude-sonnet-5 Reviewed-by: Saša Nedvědický Reviewed-by: Neil Horman Reviewed-by: Paul Dale MergeDate: Wed Jul 29 14:02:07 2026 (Merged from https://github.com/openssl/openssl/pull/32065) --- test/radix/quic_tests.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c index fd24e13507177..8501b46a7715b 100644 --- a/test/radix/quic_tests.c +++ b/test/radix/quic_tests.c @@ -490,10 +490,17 @@ static int mutcbk_inject_frames(const QUIC_PKT_HDR *hdrin, /* * make injection callback a one shot event, * callback is invoked for every packet we - * want to modify only one packet here. + * want to modify only one packet here. Returning 0 tells the QTX the + * packet send itself failed (tearing down the connection), so once + * we're done mutating we must pass subsequent packets through + * unmodified instead. */ - if (mutctx->mutctx_done) - return 0; + if (mutctx->mutctx_done) { + *hdrout = (QUIC_PKT_HDR *)hdrin; + *iovecout = iovecin; + *numout = numin; + return 1; + } mutctx->mutctx_done = 1; From e0c81d8004714e071eca5bc4b90f90ac889b5f0f Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Tue, 23 Jun 2026 17:01:34 +0100 Subject: [PATCH 094/189] Add documentation for OPENSSL_armcap Add man page documentation for OPENSSL_armcap, and link those docs in the relevant places. Fixes #17045 Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale MergeDate: Wed Jul 29 14:05:02 2026 (Merged from https://github.com/openssl/openssl/pull/31749) --- doc/build.info | 6 + doc/man1/openssl.pod | 4 +- doc/man3/OPENSSL_armcap.pod | 246 ++++++++++++++++++++++++++++++++++++ doc/man7/openssl-env.pod | 4 +- 4 files changed, 256 insertions(+), 4 deletions(-) create mode 100644 doc/man3/OPENSSL_armcap.pod diff --git a/doc/build.info b/doc/build.info index 8f20c3f59b8b7..ce2125a4d3f3a 100644 --- a/doc/build.info +++ b/doc/build.info @@ -1575,6 +1575,10 @@ DEPEND[html/man3/OPENSSL_LH_stats.html]=man3/OPENSSL_LH_stats.pod GENERATE[html/man3/OPENSSL_LH_stats.html]=man3/OPENSSL_LH_stats.pod DEPEND[man/man3/OPENSSL_LH_stats.3]=man3/OPENSSL_LH_stats.pod GENERATE[man/man3/OPENSSL_LH_stats.3]=man3/OPENSSL_LH_stats.pod +DEPEND[html/man3/OPENSSL_armcap.html]=man3/OPENSSL_armcap.pod +GENERATE[html/man3/OPENSSL_armcap.html]=man3/OPENSSL_armcap.pod +DEPEND[man/man3/OPENSSL_armcap.3]=man3/OPENSSL_armcap.pod +GENERATE[man/man3/OPENSSL_armcap.3]=man3/OPENSSL_armcap.pod DEPEND[html/man3/OPENSSL_config.html]=man3/OPENSSL_config.pod GENERATE[html/man3/OPENSSL_config.html]=man3/OPENSSL_config.pod DEPEND[man/man3/OPENSSL_config.3]=man3/OPENSSL_config.pod @@ -3463,6 +3467,7 @@ html/man3/OPENSSL_Applink.html \ html/man3/OPENSSL_FILE.html \ html/man3/OPENSSL_LH_COMPFUNC.html \ html/man3/OPENSSL_LH_stats.html \ +html/man3/OPENSSL_armcap.html \ html/man3/OPENSSL_config.html \ html/man3/OPENSSL_fork_prepare.html \ html/man3/OPENSSL_gmtime.html \ @@ -4141,6 +4146,7 @@ man/man3/OPENSSL_Applink.3 \ man/man3/OPENSSL_FILE.3 \ man/man3/OPENSSL_LH_COMPFUNC.3 \ man/man3/OPENSSL_LH_stats.3 \ +man/man3/OPENSSL_armcap.3 \ man/man3/OPENSSL_config.3 \ man/man3/OPENSSL_fork_prepare.3 \ man/man3/OPENSSL_gmtime.3 \ diff --git a/doc/man1/openssl.pod b/doc/man1/openssl.pod index 635b52aeb1208..077fc76c53d49 100644 --- a/doc/man1/openssl.pod +++ b/doc/man1/openssl.pod @@ -722,8 +722,8 @@ For information about specific commands, see L, L, and L. For information about querying or specifying CPU architecture flags, see -L, L, L, -and L. +L, L, L, +L and L. =head1 SEE ALSO diff --git a/doc/man3/OPENSSL_armcap.pod b/doc/man3/OPENSSL_armcap.pod new file mode 100644 index 0000000000000..78c8d3fbedc9d --- /dev/null +++ b/doc/man3/OPENSSL_armcap.pod @@ -0,0 +1,246 @@ +=pod + +=head1 NAME + +OPENSSL_armcap - the Arm processor capabilities vector + +=head1 SYNOPSIS + + env OPENSSL_armcap=... + +=head1 DESCRIPTION + +libcrypto supports a range of Arm instruction set extensions. These +extensions are represented by bits in the Arm processor capabilities vector. +When libcrypto initializes, it stores the results returned by Arm CPU +capabilities detection logic in the Arm processor capabilities vector. The +CPU capabilities detection methods are OS-dependent, using a combination of +information gathered by the kernel during boot, and probe functions that attempt +to execute instructions and trap illegal instruction signals with a signal +handler. + +To override the set of extensions available to an application, set the +B environment variable before starting the application. The +environment variable is assigned a numerical value that denotes the bits in +the Arm processor capabilities vector. The arm_arch.h header file defines +the possible values, which are explained in detail below. + +Multiple extensions are enabled by logically OR-ing the values that represent +the desired extensions. + +B: Attempting to executing an instruction from an extension that the +target CPU does not support will result in an illegal instruction exception +(SIGILL). + +Please note that not all possible values in the Arm processor capabilities +vector are actual processor capabilities. Some values represent OpenSSL +performance preferences for some implementations which only make sense on +specific CPUs. + +The following extensions are defined: + +=over 4 + +=item 0x0001 + +Name: B + +Meaning: Indicates support for the Armv7 Neon SIMD extensions on the processor. + +Effect: Enables various Armv7 Neon SIMD implementations. + +=item 0x00002 + +Name: B + +Meaning: Indicates support for the Armv7 system timer on the processor. + +Effect: This is used as a seed for some random number generators. + +=item 0x00004 + +Name: B + +Meaning: Indicates support for the Armv8.0 AES hardware-acceleration extensions +on the processor. + +Effect: Enables various Armv8.0 AES hardware-accelerated implementations. + +=item 0x00008 + +Name: B + +Meaning: Indicates support for the Armv8.0 SHA1 hardware-acceleration extensions +on the processor. + +Effect: Enables various Armv8.0 SHA1 hardware-accelerated implementations. + +=item 0x00010 + +Name: B + +Meaning: Indicates support for the Armv8.0 SHA256 hardware-acceleration +extensions on the processor. + +Effect: Enables various Armv8.0 SHA256 hardware-accelerated implementations. + +=item 0x00020 + +Name: B + +Meaning: Indicates support for the Armv8.0 polynomial multiplication +hardware-acceleration extensions on the processor. + +Effect: Used to hardware-accelerate polynomial multiplication, for example in +AES-GCM. + +=item 0x00040 + +Name: B + +Meaning: Indicates support for the Armv8.2 SHA512 hardware-acceleration +extensions on the processor. + +Effect: Enables Armv8.2 SHA512 hardware-accelerated implementations. + +=item 0x00080 + +Name: B + +Meaning: Indicates support for the Armv8.0 hardware identification extensions on +the processor. + +Effect: Allows implementations to change their behaviour, dependant on the +processor platform in order to achieve better performance. + +=item 0x00100 + +Name: B + +Meaning: Indicates support for the Armv8.5 hardware random number generation +extensions on the processor. + +Effect: Enables hardware random number generation on supported AArch64 +processors. + +=item 0x00200 + +Name: B + +Meaning: Indicates support for the Armv8.2 SM3 hardware-acceleration extensions +on the processor. + +Effect: Enables Armv8.2 SM3 hardware-accelerated implementations. + +=item 0x00400 + +Name: B + +Meaning: Indicates support for the Armv8.2 SM4 hardware-acceleration extensions +on the processor. + +Effect: Enables Armv8.2 SM4 hardware-accelerated implementations. + +=item 0x00800 + +Name: B + +Meaning: Indicates support for the Armv8.2 SHA3 hardware-acceleration extensions +on the processor. + +Effect: Enables SHA3 hardware-accelerated implementations (see also +ARMV8_HAVE_SHA3_AND_WORTH_USING). + +=item 0x01000 + +Name: B + +Meaning: Indicates support for the Arm EOR3 instruction, which is a part of the +Armv8.2 SHA3 extensions, and enables 8x Loop unrolling in the AES-CTR +implementation. + +Effect: Enables the 8x loop unrolling utilising EOR3 implementation of AES-CTR +on platforms that support the SHA3 extension and have enough vector bandwidth. + +=item 0x02000 + +Name: B + +Meaning: Indicates support for the Armv8.2 SVE hardware extension on the +processor. + +Effect: Enables various Armv8.2 SVE implementations. + +=item 0x04000 + +Name: B + +Meaning: Indicates support for the Armv9.0 SVE2 hardware extension on the +processor. + +Effect: Enables various Armv9.0 SVE2 implementations. + +=item 0x08000 + +Name: B + +Meaning: Indicates support for the Armv8.2 SHA3 hardware-acceleration extensions +on the processor, and that the hardware bandwidth is sufficient for it to be +worth using. + +Effect: On certain Apple platforms, although the SHA3 extension is supported, it +is actually slower than other implementations. This flag disables the +hardware-accelerated SHA3 implementations on these platforms. + +=item 0x10000 + +Name: B + +Meaning: Indicates support for the Arm EOR3 instruction, which is a part of the +Armv8.2 SHA3 extensions, and enables 12x loop unrolling in the AES-CTR +implementation. + +Effect: Enables the 12x loop unrolling utilising EOR3 implementation of AES-CTR +on platforms that support the extension and have enough vector bandwidth. + +=item 0x20000 + +Name: B + +Meaning: Indicates support for the Armv9.0 SVE2 hardware extension, and enables +its use in the Poly1305 implementation. + +Effect: Enables the Armv9.0 SVE2 Poly1305 implementation if SVE2 is enabled, the +vector length is greater than 128 bits, and the vector length is a power of 2. + +=back + +=head1 RETURN VALUES + +Not available. + +=head1 EXAMPLES + +Check currently detected capabilities: + + $ openssl info -cpusettings + OPENSSL_armcap=0x987d + +The detected capabilities in the above example indicate that ARMV7_NEON, +ARMV8_AES, ARMV8_SHA1, ARMV8_SHA256, ARMV8_PMULL, ARMV8_SHA512, ARMV8_SHA3, +ARMV8_UNROLL8_EOR3, and ARMV8_HAVE_SHA3_AND_WORTH_USING are enabled. + +Disable all instruction set extensions: + + export OPENSSL_armcap=0x00 + +=head1 COPYRIGHT + +Copyright 2026 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 +L. + +=cut diff --git a/doc/man7/openssl-env.pod b/doc/man7/openssl-env.pod index 5647af84f9634..8e2b391fcd913 100644 --- a/doc/man7/openssl-env.pod +++ b/doc/man7/openssl-env.pod @@ -182,8 +182,8 @@ OpenSSL supports a number of different algorithm implementations for various machines and, by default, it determines which to use based on the processor capabilities and run time feature enquiry. These environment variables can be used to exert more control over this selection process. -See L, L, L, -and L. +See L, L, L, +L and L. =item B, B, B From 079dccafc95932c4ac6f871f2c6eefb0f50f69a0 Mon Sep 17 00:00:00 2001 From: olszomal Date: Tue, 26 May 2026 09:01:57 +0200 Subject: [PATCH 095/189] doc: fix rsa_oaep_md default digest documentation Document that rsa_oaep_md defaults to SHA1, matching the current implementation. Note: SoftHSM currently supports only SHA1/MGF1-SHA1 with RSA-OAEP encryption. Reviewed-by: Jakub Zelenka Reviewed-by: Paul Dale Reviewed-by: Eugene Syromiatnikov MergeDate: Wed Jul 29 16:46:32 2026 (Merged from https://github.com/openssl/openssl/pull/31295) (cherry picked from commit 178f835eaff839b314164da488772f37c23c907a) --- doc/man1/openssl-pkeyutl.pod.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in index 7a84d24b1277a..11744c5181e8f 100644 --- a/doc/man1/openssl-pkeyutl.pod.in +++ b/doc/man1/openssl-pkeyutl.pod.in @@ -379,7 +379,7 @@ explicitly set in PSS mode then the signing digest is used. =item BI Sets the digest used for the OAEP hash function. If not explicitly set then -SHA256 is used. +SHA1 is used. =item BI From 453eaaa9e6bb1304730abacfbb73d51868cb6ab9 Mon Sep 17 00:00:00 2001 From: Abel Thomas Date: Thu, 9 Jul 2026 14:22:50 +0200 Subject: [PATCH 096/189] pkcs7: null-guard enveloped and signedAndEnveloped arms in PKCS7_stream Dereferences of `p7->d.enveloped->enc_data` and `p7->d.signed_and_enveloped->enc_data` crash with UBSan when the union member is NULL after parsing a minimal/malformed input. Mirror the guard added for the signed arm in PR #30351. Added unit-tests to validate the change. Fixes: #31682 Reviewed-by: Andrew Dinh Reviewed-by: Jakub Zelenka MergeDate: Wed Jul 29 16:51:46 2026 (Merged from https://github.com/openssl/openssl/pull/31716) (cherry picked from commit 32f5a5183c7f55d5dcf42f433d38c5946c1d0b7e) --- crypto/pkcs7/pk7_lib.c | 8 +++++++ test/pkcs7_test.c | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index edf1f6cb698dc..0f9e77f8eef48 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -727,6 +727,10 @@ int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) break; case NID_pkcs7_signedAndEnveloped: + if (p7->d.signed_and_enveloped == NULL || p7->d.signed_and_enveloped->enc_data == NULL) { + ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); + break; + } os = p7->d.signed_and_enveloped->enc_data->enc_data; if (os == NULL) { os = ASN1_OCTET_STRING_new(); @@ -735,6 +739,10 @@ int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) break; case NID_pkcs7_enveloped: + if (p7->d.enveloped == NULL || p7->d.enveloped->enc_data == NULL) { + ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); + break; + } os = p7->d.enveloped->enc_data->enc_data; if (os == NULL) { os = ASN1_OCTET_STRING_new(); diff --git a/test/pkcs7_test.c b/test/pkcs7_test.c index d2fbdb73bb382..01cbf6a7493b0 100644 --- a/test/pkcs7_test.c +++ b/test/pkcs7_test.c @@ -411,6 +411,54 @@ static int pkcs7_inner_content_verify_test(void) } #endif /* OPENSSL_NO_EC */ +static int pkcs7_stream_enveloped_no_content_test(void) +{ + int ret = 0; + PKCS7 *p7 = NULL; + BIO *sink = NULL; + BIO *bio = NULL; + + const unsigned char data_enveloped_no_body[] = { 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03 }; + const unsigned char *ptr_env_no_body = data_enveloped_no_body; + + ret = TEST_ptr(p7 = d2i_PKCS7(NULL, &ptr_env_no_body, + sizeof(data_enveloped_no_body))) + && TEST_ptr(sink = BIO_new(BIO_s_null())) + && TEST_ptr_null(bio = BIO_new_PKCS7(sink, p7)) + && TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), + PKCS7_R_NO_CONTENT); + + BIO_free(bio); + BIO_free(sink); + PKCS7_free(p7); + return ret; +} + +static int pkcs7_stream_enveloped_signed_no_content_test(void) +{ + int ret = 0; + PKCS7 *p7 = NULL; + BIO *sink = NULL; + BIO *bio = NULL; + + const unsigned char data_enveloped_signed_no_body[] = { 0x30, 0x0b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x04 }; + const unsigned char *ptr_env_signed_no_body = data_enveloped_signed_no_body; + + ret = TEST_ptr(p7 = d2i_PKCS7(NULL, &ptr_env_signed_no_body, + sizeof(data_enveloped_signed_no_body))) + && TEST_ptr(sink = BIO_new(BIO_s_null())) + && TEST_ptr_null(bio = BIO_new_PKCS7(sink, p7)) + && TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), + PKCS7_R_NO_CONTENT); + + BIO_free(bio); + BIO_free(sink); + PKCS7_free(p7); + return ret; +} + int setup_tests(void) { ADD_TEST(pkcs7_issuer_and_serial_negative_idx_test); @@ -418,5 +466,7 @@ int setup_tests(void) ADD_TEST(pkcs7_verify_test); ADD_TEST(pkcs7_inner_content_verify_test); #endif /* OPENSSL_NO_EC */ + ADD_TEST(pkcs7_stream_enveloped_no_content_test); + ADD_TEST(pkcs7_stream_enveloped_signed_no_content_test); return 1; } From bb5e1258b09354c67176b9b708ca3b564d8e2f52 Mon Sep 17 00:00:00 2001 From: Kurt Roeckx Date: Tue, 14 Jul 2026 19:20:21 +0200 Subject: [PATCH 097/189] Add value_barrier in MOD_EXP_CTIME_COPY_FROM_PREBUF Without it, compilers can figure out the possible values and optimize based on it. Reviewed-by: Andrew Dinh Reviewed-by: Paul Dale Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz MergeDate: Wed Jul 29 17:04:46 2026 (Merged from https://github.com/openssl/openssl/pull/31957) (cherry picked from commit f8c26111bab30399d0c9262269089639ff8e4746) --- crypto/bn/bn_exp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 44931f803802c..efea3f94cf588 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -573,8 +573,9 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, BN_ULONG acc = 0; for (j = 0; j < xstride; j++) { - acc |= ((table[j + 0 * xstride] & y0) | (table[j + 1 * xstride] & y1) | (table[j + 2 * xstride] & y2) | (table[j + 3 * xstride] & y3)) - & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + acc |= ((table[j + 0 * xstride] & value_barrier_bn(y0)) | (table[j + 1 * xstride] & value_barrier_bn(y1)) + | (table[j + 2 * xstride] & value_barrier_bn(y2)) | (table[j + 3 * xstride] & value_barrier_bn(y3))) + & value_barrier_bn((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); } b->d[i] = acc; From 0157f0c0057e691e6284db3242b994606410341c Mon Sep 17 00:00:00 2001 From: Kurt Roeckx Date: Tue, 14 Jul 2026 19:40:42 +0200 Subject: [PATCH 098/189] Add value_barrier in BN_consttime_swap Without it, compilers can figure out the possible values and optimize based on it. Reviewed-by: Andrew Dinh Reviewed-by: Paul Dale Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz MergeDate: Wed Jul 29 17:04:47 2026 (Merged from https://github.com/openssl/openssl/pull/31957) (cherry picked from commit 1d7a8dd73ff9e0fc197611433b9b60b4b5f5465c) --- crypto/bn/bn_lib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 9dc443f5b7827..f22f6f49fb4bd 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -966,11 +966,11 @@ void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) condition = ((~condition & ((condition - 1))) >> (BN_BITS2 - 1)) - 1; - t = (a->top ^ b->top) & condition; + t = (a->top ^ b->top) & value_barrier_bn(condition); a->top ^= t; b->top ^= t; - t = (a->neg ^ b->neg) & condition; + t = (a->neg ^ b->neg) & value_barrier_bn(condition); a->neg ^= t; b->neg ^= t; @@ -998,13 +998,13 @@ void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) #define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP) - t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition; + t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & value_barrier_bn(condition); a->flags ^= t; b->flags ^= t; /* conditionally swap the data */ for (i = 0; i < nwords; i++) { - t = (a->d[i] ^ b->d[i]) & condition; + t = (a->d[i] ^ b->d[i]) & value_barrier_bn(condition); a->d[i] ^= t; b->d[i] ^= t; } From dd4f804e6d2dadcdd2c2a0ecd16d8f8e85635f60 Mon Sep 17 00:00:00 2001 From: Kurt Roeckx Date: Wed, 15 Jul 2026 15:44:38 +0200 Subject: [PATCH 099/189] Apply suggestion from @andrewkdinh Co-authored-by: Andrew Dinh Reviewed-by: Andrew Dinh Reviewed-by: Paul Dale Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz MergeDate: Wed Jul 29 17:04:49 2026 (Merged from https://github.com/openssl/openssl/pull/31957) (cherry picked from commit 33482fbddcf137dde9bd84ae12f2f02cbc358c78) --- crypto/bn/bn_exp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index efea3f94cf588..ddcd89e2d4bc5 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -552,7 +552,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, BN_ULONG acc = 0; for (j = 0; j < width; j++) { - acc |= table[j] & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + acc |= table[j] & value_barrier_bn((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); } b->d[i] = acc; From 8d46334ee4ef29011f9ae65297cd3b334e6bb367 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 29 Apr 2026 18:39:37 +0900 Subject: [PATCH 100/189] Fix false success on zero BIO write The TLS record layer treated BIO_write returning 0 as success unless the BIO retry flag was set. For a write with data pending in the write buffer, this could report success to the application while leaving record data pending internally. Capture the pending buffer length before the transport write. If a positive length write returns zero, return retry when the BIO retry flag is set and fatal otherwise. Do not queue an SSL reason for the fatal zero-without-retry case: a custom BIO can return zero without retry without this implying an SSL library or protocol error, so SSL_get_error() reports SSL_ERROR_SYSCALL with an empty error queue. Preserve the KTLS empty fragment case where the pending length is already zero and a zero byte write is expected to succeed. For DTLS, the same zero return without retry condition is now treated as fatal; the failed buffer is still dropped in the existing DTLS write error path. This intentionally tightens the previous behavior, which could treat the zero return as success. Add regression coverage with a custom BIO that returns 0 without setting retry for a positive length write. Fixes #31009 Reviewed-by: Jakub Zelenka Reviewed-by: Matt Caswell Reviewed-by: Andrew Dinh MergeDate: Mon Aug 3 12:44:56 2026 (Merged from https://github.com/openssl/openssl/pull/31021) --- ssl/record/methods/tls_common.c | 24 +++++++++--- test/helpers/ssltestlib.c | 61 ++++++++++++++++++++++++++++++ test/helpers/ssltestlib.h | 3 ++ test/sslapitest.c | 66 +++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 6 deletions(-) diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c index da3c6d850fbf8..70dbfab3d26cb 100644 --- a/ssl/record/methods/tls_common.c +++ b/ssl/record/methods/tls_common.c @@ -1919,13 +1919,14 @@ int tls_retry_write_records(OSSL_RECORD_LAYER *rl) { int i, ret; TLS_BUFFER *thiswb; - size_t tmpwrit = 0; + size_t tmpwrit = 0, left; if (rl->nextwbuf >= rl->numwpipes) return OSSL_RECORD_RETURN_SUCCESS; for (;;) { thiswb = &rl->wbuf[rl->nextwbuf]; + left = TLS_BUFFER_get_left(thiswb); clear_sys_error(); if (rl->bio != NULL) { @@ -1935,13 +1936,24 @@ int tls_retry_write_records(OSSL_RECORD_LAYER *rl) return ret; } i = BIO_write(rl->bio, (char *)&(TLS_BUFFER_get_buf(thiswb)[TLS_BUFFER_get_offset(thiswb)]), - (unsigned int)TLS_BUFFER_get_left(thiswb)); + (unsigned int)left); if (i >= 0) { tmpwrit = i; - if (i == 0 && BIO_should_retry(rl->bio)) - ret = OSSL_RECORD_RETURN_RETRY; - else + if (i == 0 && left != 0) { + if (BIO_should_retry(rl->bio)) { + ret = OSSL_RECORD_RETURN_RETRY; + } else { + /* + * Treat this as a fatal I/O condition. Do not queue an + * SSL reason: a zero return with no retry flag may come + * from a custom BIO and does not imply an SSL library + * or protocol error. + */ + ret = OSSL_RECORD_RETURN_FATAL; + } + } else { ret = OSSL_RECORD_RETURN_SUCCESS; + } } else { if (BIO_should_retry(rl->bio)) { ret = OSSL_RECORD_RETURN_RETRY; @@ -1964,7 +1976,7 @@ int tls_retry_write_records(OSSL_RECORD_LAYER *rl) * Treat i == 0 as success rather than an error for zero byte * writes to permit this case. */ - if (i >= 0 && tmpwrit == TLS_BUFFER_get_left(thiswb)) { + if (i >= 0 && tmpwrit == left) { TLS_BUFFER_set_left(thiswb, 0); TLS_BUFFER_add_offset(thiswb, tmpwrit); if (++(rl->nextwbuf) < rl->numwpipes) diff --git a/test/helpers/ssltestlib.c b/test/helpers/ssltestlib.c index 0f9b83865d864..7173415a7217b 100644 --- a/test/helpers/ssltestlib.c +++ b/test/helpers/ssltestlib.c @@ -43,11 +43,13 @@ static int tls_dump_puts(BIO *bp, const char *str); #define BIO_TYPE_MEMPACKET_TEST 0x81 #define BIO_TYPE_ALWAYS_RETRY 0x82 #define BIO_TYPE_MAYBE_RETRY (0x83 | BIO_TYPE_FILTER) +#define BIO_TYPE_NO_RETRY_ZERO (0x84 | BIO_TYPE_FILTER) static BIO_METHOD *method_tls_dump = NULL; static BIO_METHOD *meth_mem = NULL; static BIO_METHOD *meth_always_retry = NULL; static BIO_METHOD *meth_maybe_retry = NULL; +static BIO_METHOD *meth_no_retry_zero = NULL; static int retry_err = -1; /* Note: Not thread safe! */ @@ -856,6 +858,10 @@ static int maybe_retry_new(BIO *bi); static int maybe_retry_free(BIO *a); static int maybe_retry_write(BIO *b, const char *in, int inl); static long maybe_retry_ctrl(BIO *b, int cmd, long num, void *ptr); +static int no_retry_zero_new(BIO *bi); +static int no_retry_zero_free(BIO *a); +static int no_retry_zero_write(BIO *b, const char *in, int inl); +static long no_retry_zero_ctrl(BIO *b, int cmd, long num, void *ptr); const BIO_METHOD *bio_s_maybe_retry(void) { @@ -942,6 +948,61 @@ static long maybe_retry_ctrl(BIO *bio, int cmd, long num, void *ptr) } } +const BIO_METHOD *bio_s_no_retry_zero(void) +{ + if (meth_no_retry_zero == NULL) { + if (!TEST_ptr(meth_no_retry_zero = BIO_meth_new(BIO_TYPE_NO_RETRY_ZERO, + "No Retry Zero")) + || !TEST_true(BIO_meth_set_write(meth_no_retry_zero, + no_retry_zero_write)) + || !TEST_true(BIO_meth_set_ctrl(meth_no_retry_zero, + no_retry_zero_ctrl)) + || !TEST_true(BIO_meth_set_create(meth_no_retry_zero, + no_retry_zero_new)) + || !TEST_true(BIO_meth_set_destroy(meth_no_retry_zero, + no_retry_zero_free))) + return NULL; + } + return meth_no_retry_zero; +} + +void bio_s_no_retry_zero_free(void) +{ + BIO_meth_free(meth_no_retry_zero); +} + +static int no_retry_zero_new(BIO *bio) +{ + BIO_set_init(bio, 1); + return 1; +} + +static int no_retry_zero_free(BIO *bio) +{ + BIO_set_data(bio, NULL); + BIO_set_init(bio, 0); + return 1; +} + +static int no_retry_zero_write(BIO *bio, const char *in, int inl) +{ + BIO_clear_retry_flags(bio); + return 0; +} + +static long no_retry_zero_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + BIO *next = BIO_next(bio); + + switch (cmd) { + case BIO_CTRL_FLUSH: + return next == NULL ? 1 : BIO_ctrl(next, cmd, num, ptr); + + default: + return next == NULL ? 0 : BIO_ctrl(next, cmd, num, ptr); + } +} + int create_ssl_ctx_pair(OSSL_LIB_CTX *libctx, const SSL_METHOD *sm, const SSL_METHOD *cm, int min_proto_version, int max_proto_version, SSL_CTX **sctx, SSL_CTX **cctx, diff --git a/test/helpers/ssltestlib.h b/test/helpers/ssltestlib.h index 7db8fd3248c5b..d8bb3bfe62f8a 100644 --- a/test/helpers/ssltestlib.h +++ b/test/helpers/ssltestlib.h @@ -59,6 +59,9 @@ void set_always_retry_err_val(int err); const BIO_METHOD *bio_s_maybe_retry(void); void bio_s_maybe_retry_free(void); +const BIO_METHOD *bio_s_no_retry_zero(void); +void bio_s_no_retry_zero_free(void); + /* Packet types - value 0 is reserved */ #define INJECT_PACKET 1 #define INJECT_PACKET_IGNORE_REC_SEQ 2 diff --git a/test/sslapitest.c b/test/sslapitest.c index 3da9e99752030..8174eeedc627f 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -12621,6 +12621,70 @@ static int test_data_retry(void) return testresult; } +/* + * Test that a BIO returning 0 without a retry flag for a write with a positive + * length is not treated as a successful write. + */ +static int test_data_write_zero_no_retry(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + BIO *bzero = BIO_new(bio_s_no_retry_zero()); + const SSL_METHOD *smeth = TLS_server_method(); + const SSL_METHOD *cmeth = TLS_client_method(); + unsigned char inbuf[1] = { 0 }; + size_t written; + unsigned long errcode; + int err, min_version = 0, max_version = 0, testresult = 0; + + if (tst == 1) { +#if !defined(OPENSSL_NO_DTLS) && !defined(OPENSSL_NO_DTLS1_2) + smeth = DTLS_server_method(); + cmeth = DTLS_client_method(); + min_version = max_version = DTLS1_2_VERSION; +#else + BIO_free(bzero); + return TEST_skip("DTLS 1.2 not supported"); +#endif + } + + if (!TEST_ptr(bzero)) + goto end; + + if (!TEST_true(create_ssl_ctx_pair(libctx, smeth, cmeth, min_version, + max_version, &sctx, &cctx, cert, privkey))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, + NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + SSL_set0_wbio(clientssl, bzero); + bzero = NULL; + + ERR_clear_error(); + if (!TEST_false(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written))) + goto end; + + err = SSL_get_error(clientssl, 0); + errcode = ERR_get_error(); + if (!TEST_int_eq(err, SSL_ERROR_SYSCALL) + || !TEST_ulong_eq(errcode, 0)) + goto end; + + testresult = 1; +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + BIO_free_all(bzero); + return testresult; +} + struct resume_servername_cb_data { int i; SSL_CTX *cctx; @@ -14369,6 +14433,7 @@ int setup_tests(void) ADD_TEST(test_rstate_string); ADD_ALL_TESTS(test_handshake_retry, 16); ADD_TEST(test_data_retry); + ADD_ALL_TESTS(test_data_write_zero_no_retry, 2); ADD_ALL_TESTS(test_multi_resume, 5); ADD_ALL_TESTS(test_select_next_proto, OSSL_NELEM(next_proto_tests)); #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG) @@ -14416,6 +14481,7 @@ void cleanup_tests(void) bio_s_mempacket_test_free(); bio_s_always_retry_free(); bio_s_maybe_retry_free(); + bio_s_no_retry_zero_free(); OSSL_PROVIDER_unload(defctxnull); OSSL_LIB_CTX_free(libctx); } From 88cdff90e4af0f0b6732ba4bb395b0e8a831edb7 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 3 Aug 2026 22:47:08 +0900 Subject: [PATCH 101/189] ssl: Remove shadowed variable in write retry path Commit 8d46334ee4ef "Fix false success on zero BIO write" introduced a function-scope left variable while the app-buffer recovery block already declared one. This breaks builds using -Werror=shadow. Assign the current buffer length to the existing function-scope variable in the recovery block. This preserves the previous re-read at that point while eliminating the shadowed declaration. Fixes: 8d46334ee4ef "Fix false success on zero BIO write" Reviewed-by: Viktor Dukhovni Reviewed-by: Andrew Dinh Reviewed-by: Jakub Zelenka Reviewed-by: Eugene Syromiatnikov MergeDate: Mon Aug 3 15:46:22 2026 (Merged from https://github.com/openssl/openssl/pull/32153) (cherry picked from commit a2eea872d0af948e5b889083f248e270d7326be7) --- ssl/record/methods/tls_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c index 70dbfab3d26cb..e00ad084cbd9c 100644 --- a/ssl/record/methods/tls_common.c +++ b/ssl/record/methods/tls_common.c @@ -1994,9 +1994,9 @@ int tls_retry_write_records(OSSL_RECORD_LAYER *rl) */ if (TLS_BUFFER_is_app_buffer(thiswb) && (rl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) != 0) { - size_t left = TLS_BUFFER_get_left(thiswb); unsigned char *buf; + left = TLS_BUFFER_get_left(thiswb); buf = OPENSSL_malloc(left); if (buf == NULL) { RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); From 3d9ddf4b9c4eb592f8198f9b96dfab1dad5958f3 Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Fri, 11 Jul 2025 14:46:24 +0200 Subject: [PATCH 102/189] util/other.syms: sort OPENSSL_*cap lexicographically, add missing variables The list includes OPENSSL_ia32cap, OPENSSL_ppccap, OPENSSL_riscvcap, and OPENSSL_s390xcap, but not OPENSSL_armcap or OPENSSL_sparcv9cap; fix that. This is a backport of commit 5e34e6a57396 "util/other.syms: sort OPENSSL_*cap lexicographically, add missing variables" from openssl-env(7) update patch set[1]; OPENSSL_ppccap has been added separately in commit 17411f0c42c6 "other.syms: Add OPENSSL_ppccap as it is now documented" (instead of backporting this commit, for some reason). [1] https://github.com/openssl/openssl/pull/28025 Complements: e0c81d800471 "Add documentation for OPENSSL_armcap" Complements: 17411f0c42c6 "other.syms: Add OPENSSL_ppccap as it is now documented" Original-Commit: 5e34e6a57396 "util/other.syms: sort OPENSSL_*cap lexicographically, add missing variables" Original-PR: https://github.com/openssl/openssl/pull/28025 Signed-off-by: Eugene Syromiatnikov Reviewed-by: Bob Beck Reviewed-by: Viktor Dukhovni MergeDate: Wed Aug 5 12:18:19 2026 (Merged from https://github.com/openssl/openssl/pull/32157) --- util/other.syms | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/util/other.syms b/util/other.syms index ba188d46c7960..299dd6e84d998 100644 --- a/util/other.syms +++ b/util/other.syms @@ -2,10 +2,12 @@ # that don't appear in lib*.num -- because they are define's, in # assembly language, etc. # +OPENSSL_armcap environment OPENSSL_ia32cap environment OPENSSL_ppccap environment -OPENSSL_s390xcap environment OPENSSL_riscvcap environment +OPENSSL_s390xcap environment +OPENSSL_sparcv9cap environment OPENSSL_MALLOC_FD environment OPENSSL_MALLOC_FAILURES environment OPENSSL_instrument_bus assembler From 2a2c5643eb9a5af91c2b826a817e2422292d29fd Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Mon, 20 Jul 2026 09:44:53 +0200 Subject: [PATCH 103/189] Add ossl_list_TYPE_join(head, tail) function The function appends list tail to list head. List tail becomes empty after the function returns. Reviewed-by: Eugene Syromiatnikov Reviewed-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs MergeDate: Thu Aug 6 11:58:58 2026 (Merged from https://github.com/openssl/openssl/pull/32031) --- doc/internal/man3/DEFINE_LIST_OF.pod | 11 +++++-- include/internal/list.h | 29 ++++++++++++++++++ test/list_test.c | 46 ++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/doc/internal/man3/DEFINE_LIST_OF.pod b/doc/internal/man3/DEFINE_LIST_OF.pod index d886defc43fb9..6291a2d91062c 100644 --- a/doc/internal/man3/DEFINE_LIST_OF.pod +++ b/doc/internal/man3/DEFINE_LIST_OF.pod @@ -8,7 +8,7 @@ ossl_list_TYPE_is_empty, ossl_list_TYPE_num, ossl_list_TYPE_head, ossl_list_TYPE_tail, ossl_list_TYPE_next, ossl_list_TYPE_prev, ossl_list_TYPE_remove, ossl_list_TYPE_insert_head, ossl_list_TYPE_insert_tail, -ossl_list_TYPE_insert_before, ossl_list_TYPE_after +ossl_list_TYPE_insert_before, ossl_list_TYPE_after, ossl_list_TYPE_join - doubly linked list =head1 SYNOPSIS @@ -38,6 +38,7 @@ ossl_list_TYPE_insert_before, ossl_list_TYPE_after void ossl_list_TYPE_insert_before(OSSL_LIST(name) *list, type *existing, type *elem); void ossl_list_TYPE_insert_after(OSSL_LIST(name) *list, type *existing, type *elem); + void ossl_list_TYPE_join(OSSL_LIST(name) *lh, OSSL_LIST(name) *lt); =head1 DESCRIPTION @@ -90,6 +91,10 @@ B_insert_after>() inserts the element I, which must not be in the list, into the I immediately after the I element. +B_join<()> joins list B with list B. +List B is appended to list B. The list B becomes empty, +as all its members are part of B after the function returns. + =head1 RETURN VALUES B_is_empty>() returns nonzero if the list is empty and zero @@ -124,7 +129,9 @@ the specified element in the list. =head1 HISTORY -The functions described here were all added in OpenSSL 3.2. +ossl_list_TYPE_join() was added in OpenSSL 4.1, 4.0.2, 3.6.4, 3.5.8, and 3.4.7. + +The rest of the functions described here was added in OpenSSL 3.2. =head1 COPYRIGHT diff --git a/include/internal/list.h b/include/internal/list.h index 8bb0b741bed12..cd43471409f53 100644 --- a/include/internal/list.h +++ b/include/internal/list.h @@ -194,6 +194,35 @@ list->omega = elem; \ list->num_elems++; \ } \ + static ossl_unused ossl_inline void \ + ossl_list_##name##_join(OSSL_LIST(name) * lh, OSSL_LIST(name) * lt) \ + { \ + OSSL_LIST_DBG(type * _p); /* local variable '_p' when debug */ \ + if (lt == NULL || lh == NULL || lt->num_elems == 0 || lh == lt) \ + return; \ + /* \ + * let's be optimistic about size_t overflow here: it can not happen. \ + */ \ + lh->num_elems += lt->num_elems; \ + if (lh->omega == NULL) { \ + assert(lh->alpha == NULL); \ + lh->omega = lt->omega; \ + lh->alpha = lt->alpha; \ + } else { \ + if (lt->alpha != NULL) \ + ((type *)lt->alpha)->ossl_list_##name.prev = lh->omega; \ + ((type *)lh->omega)->ossl_list_##name.next = lt->alpha; \ + } \ + OSSL_LIST_DBG(for (_p = (type *)lt->alpha; \ + assert(_p == NULL || _p->ossl_list_##name.list == lt), _p != NULL; \ + _p = _p->ossl_list_##name.next) \ + _p->ossl_list_##name.list \ + = lh); \ + lh->omega = lt->omega; \ + lt->alpha = NULL; \ + lt->omega = NULL; \ + lt->num_elems = 0; \ + } \ struct ossl_list_st_##name #define DEFINE_LIST_OF(name, type) \ diff --git a/test/list_test.c b/test/list_test.c index 9deb57c4b91a9..7798ea68348ed 100644 --- a/test/list_test.c +++ b/test/list_test.c @@ -175,9 +175,55 @@ static int test_insert(void) return 1; } +static int test_join(void) +{ + OSSL_LIST(int) + l_h, l_t; + INTL elem_h[20]; + INTL elem_t[20]; + int i; + + ossl_list_int_init(&l_h); + ossl_list_int_init(&l_t); + ossl_list_int_join(&l_h, &l_t); + if (!TEST_size_t_eq(ossl_list_int_num(&l_t), 0)) + return 0; + + for (i = 0; i < (int)OSSL_NELEM(elem_h); i++) { + ossl_list_int_init_elem(&elem_h[i]); + elem_h[i].n = i; + ossl_list_int_insert_head(&l_h, &elem_h[i]); + } + + for (i = 0; i < (int)OSSL_NELEM(elem_t); i++) { + ossl_list_int_init_elem(&elem_t[i]); + elem_t[i].n = i + 10; + ossl_list_int_insert_head(&l_t, &elem_t[i]); + } + + ossl_list_int_join(NULL, NULL); + + ossl_list_int_join(NULL, &l_t); + if (!TEST_size_t_eq(ossl_list_int_num(&l_t), OSSL_NELEM(elem_t))) + return 0; + + ossl_list_int_join(&l_h, NULL); + if (!TEST_size_t_eq(ossl_list_int_num(&l_h), OSSL_NELEM(elem_h))) + return 0; + + ossl_list_int_join(&l_h, &l_t); + if (!TEST_size_t_eq(ossl_list_int_num(&l_h), OSSL_NELEM(elem_h) + OSSL_NELEM(elem_t))) + return 0; + + if (!TEST_true(ossl_list_int_is_empty(&l_t))) + return 0; + + return 1; +} int setup_tests(void) { ADD_TEST(test_fizzbuzz); ADD_TEST(test_insert); + ADD_TEST(test_join); return 1; } From 1c4aa2ec079771f87fde0a7cba9c5093bc666ecf Mon Sep 17 00:00:00 2001 From: slontis Date: Wed, 5 Aug 2026 12:06:40 +1000 Subject: [PATCH 104/189] FIPS: key gen PCT tests no longer cause FIPS provider to enter a unrecoverable error state. Reviewed-by: Viktor Dukhovni Reviewed-by: Paul Dale MergeDate: Fri Aug 7 09:58:28 2026 (Merged from https://github.com/openssl/openssl/pull/32191) --- crypto/dsa/dsa_key.c | 1 - crypto/ec/ec_key.c | 1 - crypto/rsa/rsa_gen.c | 1 - providers/implementations/keymgmt/dh_kmgmt.c | 4 +--- providers/implementations/keymgmt/ecx_kmgmt.c | 2 -- providers/implementations/keymgmt/ml_dsa_kmgmt.c | 8 ++------ providers/implementations/keymgmt/ml_kem_kmgmt.c | 4 ---- providers/implementations/keymgmt/slh_dsa_kmgmt.c | 4 +--- 8 files changed, 4 insertions(+), 21 deletions(-) diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index aa69c3eea8fb8..a07f866a218a7 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -198,7 +198,6 @@ static int dsa_keygen(DSA *dsa) ok = dsa_keygen_pairwise_test(dsa, cb, cbarg) && dsa_keygen_knownanswer_test(dsa, ctx, cb, cbarg); if (!ok) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); BN_free(dsa->pub_key); BN_clear_free(dsa->priv_key); dsa->pub_key = NULL; diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index d57ac22d5857f..8dbbdc91a1e50 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -337,7 +337,6 @@ static int ec_generate_key(EC_KEY *eckey, int pairwise_test) err: /* Step (9): If there is an error return an invalid keypair. */ if (!ok) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); BN_clear(eckey->priv_key); if (eckey->pub_key != NULL) EC_POINT_set_to_infinity(group, eckey->pub_key); diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c index 554f9d349b857..5b407696092ab 100644 --- a/crypto/rsa/rsa_gen.c +++ b/crypto/rsa/rsa_gen.c @@ -636,7 +636,6 @@ static int rsa_keygen(OSSL_LIB_CTX *libctx, RSA *rsa, int bits, int primes, OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); ok = rsa_keygen_pairwise_test(rsa, stcb, stcbarg); if (!ok) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); /* Clear intermediate results */ BN_clear_free(rsa->d); BN_clear_free(rsa->p); diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index 8a1afe7907b1a..a56f1569b93c2 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -793,10 +793,8 @@ static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) #ifdef FIPS_MODULE if (!ossl_fips_self_testing()) { ret = ossl_dh_check_pairwise(dh, 0); - if (ret <= 0) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); + if (ret <= 0) goto end; - } } #endif /* FIPS_MODULE */ } diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index 54af7a6a39568..42a0b9d7aa677 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -811,7 +811,6 @@ static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)) return key; if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); ossl_ecx_key_free(key); return NULL; } @@ -844,7 +843,6 @@ static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)) return key; if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); ossl_ecx_key_free(key); return NULL; } diff --git a/providers/implementations/keymgmt/ml_dsa_kmgmt.c b/providers/implementations/keymgmt/ml_dsa_kmgmt.c index 5ebeaae662bf2..8b08c3c9d0d8e 100644 --- a/providers/implementations/keymgmt/ml_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/ml_dsa_kmgmt.c @@ -283,10 +283,8 @@ static int ml_dsa_import(void *keydata, int selection, const OSSL_PARAM params[] #ifdef FIPS_MODULE if (res > 0) { res = ml_dsa_pairwise_test(key); - if (!res) { + if (!res) ossl_ml_dsa_key_reset(key); - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT_IMPORT); - } } #endif /* FIPS_MODULE */ return res; @@ -483,10 +481,8 @@ static void *ml_dsa_gen(void *genctx, int evp_type) goto err; } #ifdef FIPS_MODULE - if (!ml_dsa_pairwise_test(key)) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); + if (!ml_dsa_pairwise_test(key)) goto err; - } #endif return key; err: diff --git a/providers/implementations/keymgmt/ml_kem_kmgmt.c b/providers/implementations/keymgmt/ml_kem_kmgmt.c index d95f021eef707..1f5dd1e64ce4d 100644 --- a/providers/implementations/keymgmt/ml_kem_kmgmt.c +++ b/providers/implementations/keymgmt/ml_kem_kmgmt.c @@ -477,9 +477,6 @@ static int ml_kem_import(void *vkey, int selection, const OSSL_PARAM params[]) res = ml_kem_key_fromdata(key, params, include_private); if (res > 0 && include_private && !ml_kem_pairwise_test(key, key->prov_flags)) { -#ifdef FIPS_MODULE - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT_IMPORT); -#endif ossl_ml_kem_key_reset(key); res = 0; } @@ -780,7 +777,6 @@ static void *ml_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg) if (genok) { #ifdef FIPS_MODULE if (!ml_kem_pairwise_test(key, ML_KEM_KEY_FIXED_PCT)) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); ossl_ml_kem_key_free(key); return NULL; } diff --git a/providers/implementations/keymgmt/slh_dsa_kmgmt.c b/providers/implementations/keymgmt/slh_dsa_kmgmt.c index 8a676213903f5..0edc067298054 100644 --- a/providers/implementations/keymgmt/slh_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/slh_dsa_kmgmt.c @@ -366,10 +366,8 @@ static void *slh_dsa_gen(void *genctx, const char *alg) gctx->entropy, gctx->entropy_len)) goto err; #ifdef FIPS_MODULE - if (!slh_dsa_fips140_pairwise_test(key, ctx)) { - ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); + if (!slh_dsa_fips140_pairwise_test(key, ctx)) goto err; - } #endif /* FIPS_MODULE */ ossl_slh_dsa_hash_ctx_free(ctx); return key; From f10e9176e6ac7944e55ea33ef0ac4cfb01036f4e Mon Sep 17 00:00:00 2001 From: Greensi7 Date: Tue, 4 Aug 2026 15:26:32 +0200 Subject: [PATCH 105/189] Fix NULL dereference in v2i_AUTHORITY_KEYID() X509V3_EXT_d2i() may return NULL on malformed input or on allocation failure. v2i_AUTHORITY_KEYID() passed that NULL to ASN1_STRING_length_ex() causing NULL dereference. Found by x509v3 fuzzer. Example fuzzer input: ``` [default] subjectKeyIdentifier = DER:05:00 authorityKeyIdentifier = keyid ``` Reviewed-by: Milan Broz Reviewed-by: Viktor Dukhovni MergeDate: Fri Aug 7 14:03:05 2026 (Merged from https://github.com/openssl/openssl/pull/32177) --- crypto/x509/v3_akid.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crypto/x509/v3_akid.c b/crypto/x509/v3_akid.c index 08c751b77cfde..06b79c26d3aa5 100644 --- a/crypto/x509/v3_akid.c +++ b/crypto/x509/v3_akid.c @@ -173,7 +173,9 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1); if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL && !(same_issuer && !ss)) { - ikeyid = X509V3_EXT_d2i(ext); + if ((ikeyid = X509V3_EXT_d2i(ext)) == NULL) + goto err; + if (ASN1_STRING_length(ikeyid) == 0) /* indicating "none" */ { ASN1_OCTET_STRING_free(ikeyid); ikeyid = NULL; From c3a30b9594fedde8829144d68ed5fac3385daa9f Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Wed, 22 Apr 2026 22:48:02 +1000 Subject: [PATCH 106/189] Fix data type of SM2 EC_PUB_X/Y params The provider's gettable-params list advertised types that didn't match what the getter implementation supported, so fetching either coordinate tripped "incompatible type". Nothing in-tree was asking; the follow-up commit adds a test that detects the problem. Reviewed-by: Tim Hudson Reviewed-by: Andrew Dinh Reviewed-by: Nikola Pajkovsky MergeDate: Sat Aug 8 14:25:57 2026 (Merged from https://github.com/openssl/openssl/pull/30938) --- providers/implementations/keymgmt/ec_kmgmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index aa5b3f43870f0..a61d912207edc 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -847,8 +847,8 @@ static const OSSL_PARAM sm2_known_gettable_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL), EC_IMEXPORTABLE_DOM_PARAMETERS, EC_IMEXPORTABLE_PUBLIC_KEY, - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0), - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0), EC_IMEXPORTABLE_PRIVATE_KEY, OSSL_PARAM_END }; From 174d17940fc081fe6deafb1e6f4896faf13bac4e Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Wed, 27 May 2026 21:51:56 +1000 Subject: [PATCH 107/189] Expand and refactor test_evp_extra2 The "expand" part adds a algorithm-independent probe that walks every gettable OSSL_PARAM of an EVP_PKEY in two passes -- first a size query, then a real fetch. This is exercised for each algorithm. In the SM2 case it catches the gettable-params/getter type mismatch fixed in the preceding commit: reverting that commit trips the probe for SM2. The "refactor" part replaces the per-algorithm test code with a single PKEY_TEST_SPEC table of (name, optional prefab DER, optional keygen params), driven through pkey_from_spec(). The key-selection and gettable tests no longer involve any algorithm-specific code. Reviewed-by: Tim Hudson Reviewed-by: Andrew Dinh Reviewed-by: Nikola Pajkovsky MergeDate: Sat Aug 8 14:26:04 2026 (Merged from https://github.com/openssl/openssl/pull/30938) --- test/evp_extra_test2.c | 515 +++++++++++++++++++++++++++++++---------- 1 file changed, 392 insertions(+), 123 deletions(-) diff --git a/test/evp_extra_test2.c b/test/evp_extra_test2.c index b951b8c32d3aa..f7be80b11bc2c 100644 --- a/test/evp_extra_test2.c +++ b/test/evp_extra_test2.c @@ -178,6 +178,115 @@ static const unsigned char kExampleRSAKeyPKCS8[] = { 0x20, 0x1b, 0xe5, 0xdf }; +/* + * An RSA-PSS 2048-bit private key in ASN.1 DER form. Used by the + * table-driven checks instead of keygen to save CI cycles (RSA keygen + * at this size is slow). Generated with: + * > openssl genpkey -quiet -algorithm rsa-pss -outform DER > rsa-pss.der + * > xxd -i < rsa-pss.der + * Of course, never use this key for anything but tests. + */ +static const unsigned char kExampleRSAPSSKeyDER[] = { + 0x30, 0x82, 0x04, 0xba, 0x02, 0x01, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x04, 0x82, 0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, + 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa3, 0x32, 0x24, 0xdb, 0x9b, 0xec, 0x8f, 0x18, 0xbe, + 0xeb, 0xef, 0x9b, 0x0e, 0x06, 0x11, 0x78, 0x26, 0x66, 0x2b, 0x75, 0xff, 0x79, 0x50, 0xa9, + 0x96, 0xb2, 0xdf, 0xe1, 0x71, 0x2f, 0x8f, 0x3f, 0x08, 0x16, 0x3f, 0x53, 0x5a, 0x2c, 0x7c, + 0xbb, 0xb9, 0xa2, 0x54, 0x2c, 0x81, 0xaf, 0x58, 0xd1, 0xb4, 0xfe, 0xd6, 0x2a, 0x5c, 0x47, + 0xfe, 0x20, 0xf0, 0xce, 0xdc, 0xfe, 0x08, 0x7f, 0x3a, 0x24, 0xcd, 0xa0, 0x87, 0xcb, 0x0e, + 0xd7, 0xcf, 0xee, 0x26, 0x12, 0x1f, 0xdb, 0x8b, 0x0f, 0x12, 0x32, 0x05, 0x73, 0x8f, 0x60, + 0xfa, 0x75, 0x49, 0xb5, 0x50, 0x2d, 0x45, 0x72, 0x8b, 0x1d, 0x7f, 0xd3, 0x47, 0x2c, 0x5b, + 0x0e, 0x24, 0x28, 0xe2, 0xc6, 0x01, 0x74, 0x10, 0xbe, 0xe4, 0xc7, 0xd2, 0xe5, 0xf4, 0x90, + 0x10, 0xc0, 0x28, 0x66, 0xed, 0xc4, 0x84, 0xac, 0xb2, 0x01, 0x8e, 0x8a, 0xd1, 0x86, 0x82, + 0x77, 0x89, 0xd8, 0x64, 0xaa, 0xca, 0x1d, 0x27, 0x3e, 0xfd, 0x78, 0x4e, 0xd7, 0x8d, 0xc5, + 0x25, 0xab, 0xb1, 0xfb, 0x94, 0x86, 0xa1, 0x3d, 0xc4, 0x8d, 0x62, 0x5e, 0x59, 0x13, 0x25, + 0xb7, 0x77, 0x20, 0x7e, 0x0a, 0xf8, 0xd0, 0x4f, 0xf4, 0x9c, 0x6f, 0x19, 0x67, 0xe7, 0x6f, + 0x62, 0xd9, 0xc9, 0xe5, 0x97, 0x90, 0xaa, 0xd5, 0x94, 0x98, 0x61, 0xb7, 0xf9, 0xfc, 0x86, + 0x45, 0xd8, 0x6f, 0x37, 0x35, 0x51, 0x0d, 0x9f, 0xb0, 0x9f, 0xd5, 0x1b, 0x10, 0x87, 0xa2, + 0xb9, 0xe0, 0x5e, 0xc9, 0x6b, 0x1b, 0x5d, 0xf3, 0x3a, 0x16, 0x4a, 0x79, 0x25, 0xcf, 0x95, + 0xfc, 0xca, 0x8a, 0x7a, 0xac, 0x49, 0xd9, 0x36, 0xa5, 0x45, 0xc4, 0x9a, 0x01, 0x60, 0xed, + 0x8b, 0xcf, 0x66, 0xf2, 0xfb, 0x98, 0x93, 0x69, 0x84, 0xf2, 0xa8, 0x02, 0x12, 0x4d, 0x7b, + 0x48, 0xa1, 0xfb, 0x4d, 0x59, 0x96, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, + 0x00, 0x0f, 0x43, 0x65, 0xda, 0x1a, 0x53, 0xbe, 0x30, 0x78, 0xce, 0xd5, 0x4a, 0xa1, 0xbd, + 0xa4, 0x8d, 0xa1, 0xbd, 0xc5, 0x8b, 0xd4, 0x38, 0x92, 0xf8, 0x41, 0x8d, 0x7a, 0x4d, 0xfa, + 0x09, 0x92, 0x32, 0xb9, 0x7d, 0x67, 0x2f, 0xd3, 0x0b, 0xbd, 0x20, 0xcb, 0xa4, 0x68, 0x8d, + 0xff, 0x15, 0x18, 0xd0, 0x08, 0x47, 0x1b, 0x5d, 0xbb, 0xe2, 0xc9, 0xdc, 0x67, 0xd9, 0x59, + 0x26, 0xf3, 0x41, 0x7e, 0xfd, 0x29, 0x34, 0x3d, 0xef, 0x1a, 0x74, 0xc9, 0xd0, 0x42, 0xc4, + 0x48, 0x31, 0x7e, 0xe8, 0x8a, 0x71, 0x9e, 0x3b, 0xe8, 0x29, 0x90, 0x53, 0x3e, 0xf1, 0x13, + 0xce, 0x20, 0x24, 0x2d, 0xe9, 0xb4, 0xe6, 0x5c, 0x4e, 0x44, 0x37, 0xe6, 0xde, 0xe2, 0x12, + 0xd5, 0xd8, 0xf6, 0xa5, 0xfb, 0xfc, 0xca, 0x77, 0x52, 0x6f, 0xd4, 0xf9, 0x3b, 0xee, 0x20, + 0x87, 0xd4, 0x46, 0xd8, 0xa1, 0x37, 0xa5, 0x39, 0x22, 0x5e, 0xb6, 0x2c, 0xe8, 0x49, 0xf4, + 0x78, 0x07, 0x23, 0xba, 0x19, 0x6e, 0x25, 0xb6, 0x7b, 0x2b, 0x9d, 0x7e, 0x19, 0x26, 0x95, + 0xe7, 0x20, 0xb8, 0x21, 0xd1, 0xf5, 0xb9, 0x6d, 0xa6, 0x2a, 0xcb, 0x46, 0xe4, 0x62, 0x71, + 0x63, 0xe1, 0xa0, 0x77, 0x1d, 0xf7, 0x10, 0xf6, 0x1e, 0x70, 0x27, 0x72, 0xf8, 0x68, 0x19, + 0x6d, 0x84, 0xa1, 0x46, 0xcd, 0x52, 0x0f, 0x86, 0x77, 0x7a, 0x92, 0x5c, 0xc6, 0x39, 0xc2, + 0x67, 0x12, 0xb0, 0x68, 0x6c, 0xe0, 0x19, 0xde, 0x61, 0xeb, 0x39, 0x1f, 0x14, 0xd0, 0xc7, + 0xd6, 0x77, 0xc2, 0x83, 0x9e, 0xe2, 0xa3, 0x3a, 0x22, 0x02, 0x45, 0xf1, 0x10, 0x86, 0x77, + 0x4a, 0x95, 0xf3, 0x75, 0x90, 0x22, 0x9b, 0xb2, 0xcd, 0xcd, 0x2f, 0x27, 0xff, 0xe7, 0xac, + 0x9c, 0xdb, 0x85, 0x31, 0xeb, 0x2b, 0xfa, 0x8f, 0x9e, 0xbe, 0x92, 0x1a, 0xcd, 0xd3, 0x98, + 0x1a, 0x75, 0x02, 0x81, 0x81, 0x00, 0xd5, 0x06, 0xa1, 0x08, 0x41, 0x02, 0xab, 0x3a, 0x00, + 0xf5, 0x74, 0x5f, 0xb7, 0xf0, 0xa7, 0x9d, 0x0a, 0x26, 0x32, 0x7e, 0x48, 0xa4, 0xf7, 0xbe, + 0xcf, 0xba, 0x27, 0x2a, 0x7d, 0x60, 0xd2, 0x16, 0x59, 0xc3, 0xf0, 0x78, 0x33, 0x3a, 0x36, + 0x86, 0xb5, 0xd4, 0x29, 0x25, 0x23, 0x5a, 0xeb, 0x5a, 0x96, 0x82, 0xfc, 0x08, 0x08, 0x1c, + 0xcc, 0xed, 0xb3, 0xf1, 0x27, 0xca, 0x1c, 0xa8, 0xe8, 0x36, 0x77, 0xa4, 0x57, 0x9a, 0x1d, + 0xde, 0x2b, 0x3b, 0xc3, 0x41, 0x7c, 0x58, 0x33, 0x11, 0x3b, 0xee, 0x7a, 0xc9, 0xe9, 0x4b, + 0xa2, 0x3b, 0xc3, 0x68, 0x19, 0x6a, 0x00, 0x7c, 0x59, 0x90, 0x77, 0x11, 0xed, 0x47, 0x4a, + 0x5a, 0xfe, 0x3a, 0x29, 0x3a, 0xad, 0x80, 0xe9, 0xff, 0xce, 0x07, 0x3f, 0x80, 0x5f, 0x98, + 0x14, 0x1a, 0xf0, 0x9c, 0xc7, 0x8d, 0x42, 0x06, 0xc4, 0xf8, 0x89, 0xe3, 0xe0, 0x23, 0x02, + 0x81, 0x81, 0x00, 0xc4, 0x1e, 0x20, 0x31, 0xfa, 0xe7, 0x6a, 0xa5, 0x18, 0xbe, 0xce, 0x45, + 0x15, 0x97, 0x67, 0x5f, 0xd0, 0xc6, 0x0f, 0xa2, 0x6c, 0x68, 0x5e, 0xe9, 0xca, 0x48, 0x8c, + 0x46, 0x08, 0x06, 0xc1, 0xe9, 0xac, 0x8c, 0x01, 0x55, 0xc7, 0xf2, 0x02, 0x98, 0x2b, 0x8d, + 0x4e, 0x24, 0x2d, 0x56, 0x7b, 0x40, 0x24, 0x28, 0xaa, 0x4a, 0xf7, 0x83, 0x88, 0x38, 0xa5, + 0x03, 0x2b, 0xb3, 0x1c, 0x4a, 0x95, 0x70, 0xf6, 0x80, 0xcc, 0x21, 0xd0, 0xab, 0x8a, 0x10, + 0xb2, 0xa6, 0x1a, 0x27, 0xb6, 0xae, 0x24, 0xed, 0xa9, 0xfe, 0xfc, 0x74, 0x7f, 0x97, 0x9b, + 0xe1, 0xc2, 0x46, 0x48, 0xed, 0x5f, 0x2f, 0x9e, 0x54, 0x77, 0x1f, 0x61, 0x46, 0x24, 0x08, + 0x7e, 0xb5, 0x63, 0xa1, 0xe2, 0x6f, 0x58, 0xc8, 0x76, 0x98, 0x8a, 0x9a, 0xa5, 0xb9, 0x15, + 0xfb, 0xf4, 0xb8, 0xfd, 0x84, 0xb6, 0xbc, 0x5f, 0x59, 0xfa, 0x3d, 0x02, 0x81, 0x80, 0x2a, + 0x97, 0x43, 0xb4, 0xf1, 0xc2, 0x85, 0xd7, 0x77, 0xff, 0x9b, 0x3f, 0xd3, 0xf7, 0xe2, 0x9b, + 0x2c, 0x3f, 0x4c, 0xd3, 0x20, 0xd5, 0x12, 0xcf, 0x6c, 0x9a, 0xcc, 0x5f, 0xdb, 0x67, 0x73, + 0x39, 0x92, 0xc2, 0xf1, 0x1e, 0x27, 0x27, 0xd9, 0x64, 0xff, 0x8f, 0xa6, 0x96, 0x4d, 0x46, + 0x4d, 0x4d, 0xf4, 0x4f, 0xc5, 0xf2, 0x19, 0x25, 0x20, 0xf7, 0xd9, 0x85, 0x3a, 0xae, 0x57, + 0x22, 0x92, 0x22, 0xe9, 0xb2, 0xca, 0xec, 0xfe, 0x51, 0xc0, 0x15, 0x17, 0xc9, 0xcd, 0x01, + 0x99, 0x5c, 0x35, 0xbe, 0x4d, 0x80, 0x77, 0x0b, 0x6f, 0x29, 0x41, 0xbd, 0x5b, 0x6f, 0x6d, + 0x1f, 0x6f, 0x8c, 0xc9, 0xb1, 0xa4, 0xde, 0x1f, 0x08, 0xa8, 0x51, 0x9a, 0x92, 0xa7, 0xc3, + 0xe1, 0x85, 0x0a, 0x7d, 0x3a, 0x7e, 0x01, 0x1e, 0xd7, 0xce, 0x37, 0x13, 0x31, 0x76, 0x95, + 0x9f, 0xe2, 0xdb, 0xca, 0x3d, 0xec, 0x3f, 0x02, 0x81, 0x80, 0x73, 0x99, 0x66, 0x54, 0xcf, + 0x96, 0x34, 0xd0, 0x58, 0x03, 0xb0, 0x46, 0x1c, 0x72, 0x00, 0x27, 0x04, 0x42, 0x9a, 0xd8, + 0x9c, 0x99, 0xf0, 0xc8, 0x51, 0xc9, 0xed, 0x95, 0x22, 0x0a, 0x09, 0xa7, 0x19, 0x63, 0xf5, + 0x2d, 0x81, 0x0b, 0xef, 0xe7, 0x8e, 0x54, 0x5e, 0x69, 0x08, 0xa8, 0x5f, 0x41, 0xf1, 0x8e, + 0x5e, 0xc2, 0x8d, 0x9e, 0xe4, 0x5e, 0xaf, 0x35, 0x6d, 0x3e, 0xc8, 0x40, 0x56, 0x52, 0x1d, + 0x9a, 0xd1, 0xb8, 0x64, 0xed, 0x98, 0x16, 0x3b, 0x97, 0x98, 0xf7, 0x2b, 0xc0, 0xfe, 0x57, + 0x70, 0xca, 0xb2, 0x38, 0x61, 0x35, 0x16, 0x57, 0x3e, 0x52, 0x7b, 0x8e, 0x1f, 0x7b, 0x4c, + 0x12, 0x71, 0x9c, 0xf7, 0x93, 0x86, 0x8d, 0xd3, 0x52, 0x4c, 0x06, 0x12, 0x18, 0x9b, 0xf6, + 0x9d, 0xa1, 0x50, 0xa1, 0xd3, 0x69, 0x83, 0xc1, 0xde, 0x00, 0x64, 0xbf, 0x23, 0x8f, 0x69, + 0x8c, 0xf9, 0xe9, 0x02, 0x81, 0x80, 0x02, 0xce, 0x66, 0x6b, 0x32, 0x73, 0x62, 0x60, 0x27, + 0x3e, 0x38, 0x1d, 0xd8, 0x70, 0xdb, 0x4e, 0x32, 0xf7, 0x7a, 0x7b, 0x22, 0x7b, 0x9b, 0xd7, + 0x49, 0x4f, 0x5b, 0x9b, 0xaa, 0x2c, 0x5b, 0x99, 0x22, 0x1e, 0x6e, 0x7e, 0x19, 0x8a, 0xf1, + 0x97, 0xfe, 0x3f, 0xcd, 0x9e, 0xa4, 0x46, 0xf0, 0x9a, 0x62, 0x0f, 0x1a, 0xcd, 0x77, 0xe1, + 0x88, 0xe1, 0x9a, 0x22, 0x84, 0x1b, 0xbf, 0xf0, 0x71, 0xf4, 0x64, 0xfd, 0xd5, 0xaa, 0xb4, + 0x28, 0xdc, 0xef, 0xd9, 0xec, 0x29, 0x11, 0xc4, 0x58, 0x0f, 0xeb, 0x3c, 0x41, 0x66, 0x4a, + 0x98, 0x18, 0x26, 0xfe, 0x3e, 0x7e, 0xc3, 0x36, 0xfa, 0xbc, 0x64, 0x69, 0x1f, 0xce, 0x1c, + 0xc1, 0xb5, 0xe9, 0xa8, 0x78, 0xf7, 0x6d, 0xb6, 0x0c, 0x58, 0x29, 0xe2, 0xbf, 0xd0, 0xbe, + 0x2e, 0x10, 0xfa, 0x74, 0x02, 0x9b, 0x48, 0xa5, 0xc9, 0x74, 0xed, 0xed, 0x7d, 0xa8 +}; + +#ifndef OPENSSL_NO_DH +static char group_ffdhe2048[] = "ffdhe2048"; +static const OSSL_PARAM dhx_keygen_params[] = { + OSSL_PARAM_utf8_string("group", group_ffdhe2048, + sizeof(group_ffdhe2048) - 1), + OSSL_PARAM_END +}; +#endif + +#ifndef OPENSSL_NO_EC +static char group_p256[] = "P-256"; +static const OSSL_PARAM ec_keygen_params[] = { + OSSL_PARAM_utf8_string("group", group_p256, sizeof(group_p256) - 1), + OSSL_PARAM_END +}; +#endif + #ifndef OPENSSL_NO_DH static const unsigned char kExampleDHPrivateKeyDER[] = { 0x30, 0x82, 0x02, 0x26, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x17, 0x06, @@ -296,49 +405,73 @@ static APK_DATA keydata[] = { static int pkey_has_private(EVP_PKEY *key, const char *privtag, int use_octstring) { - int ret = 0; - if (use_octstring) { - unsigned char buf[64]; - - ret = EVP_PKEY_get_octet_string_param(key, privtag, buf, sizeof(buf), - NULL); + /* + * Existence probe only: pass NULL buffer, ignore the returned size. + * Avoids hard-coded fixed buffers that would cap at 64 bytes and + * fail for PQC private keys (ML-DSA-44 is ~2.5 KB). + */ + return EVP_PKEY_get_octet_string_param(key, privtag, NULL, 0, NULL); } else { BIGNUM *bn = NULL; + int ret = EVP_PKEY_get_bn_param(key, privtag, &bn); - ret = EVP_PKEY_get_bn_param(key, privtag, &bn); BN_free(bn); + return ret; } - return ret; } +/* + * Private-component tags we know about, in lookup order. Extend this + * list if a new algorithm adopts a different convention; do_pkey_tofrom + * _data_select() scans it on each key and only needs one match. + */ +static const char *const pkey_priv_tags[] = { + OSSL_PKEY_PARAM_PRIV_KEY, /* DH, DSA, EC, ECX, SM2, ML-*, SLH-DSA */ + OSSL_PKEY_PARAM_RSA_D, /* RSA, RSA-PSS */ +}; + static int do_pkey_tofrom_data_select(EVP_PKEY *key, const char *keytype) { int ret = 0; OSSL_PARAM *pub_params = NULL, *keypair_params = NULL; + const OSSL_PARAM *priv = NULL; EVP_PKEY *fromkey = NULL, *fromkeypair = NULL; EVP_PKEY_CTX *fromctx = NULL; - const char *privtag = strcmp(keytype, "RSA") == 0 ? "d" : "priv"; - const int use_octstring = strcmp(keytype, "X25519") == 0; + const char *privtag; + int use_octstring; + size_t t; /* - * Select only the public key component when using EVP_PKEY_todata() and - * check that the resulting param array does not contain a private key. + * Export the full keypair first so we can discover the algorithm's + * private-component tag from the emitted params rather than hand-coding + * it per keytype. */ - if (!TEST_int_eq(EVP_PKEY_todata(key, EVP_PKEY_PUBLIC_KEY, &pub_params), 1) - || !TEST_ptr_null(OSSL_PARAM_locate(pub_params, privtag))) + if (!TEST_int_eq(EVP_PKEY_todata(key, EVP_PKEY_KEYPAIR, &keypair_params), 1)) + goto end; + + for (t = 0; t < OSSL_NELEM(pkey_priv_tags); t++) + if ((priv = OSSL_PARAM_locate(keypair_params, pkey_priv_tags[t])) != NULL) + break; + if (priv == NULL) { + TEST_error("%s: KEYPAIR todata() emitted no known private component", + keytype); goto end; + } + privtag = priv->key; + use_octstring = priv->data_type == OSSL_PARAM_OCTET_STRING; + /* - * Select the keypair when using EVP_PKEY_todata() and check that - * the param array contains a private key. + * Select only the public key via EVP_PKEY_todata(): the private tag we + * just learned must be absent. */ - if (!TEST_int_eq(EVP_PKEY_todata(key, EVP_PKEY_KEYPAIR, &keypair_params), 1) - || !TEST_ptr(OSSL_PARAM_locate(keypair_params, privtag))) + if (!TEST_int_eq(EVP_PKEY_todata(key, EVP_PKEY_PUBLIC_KEY, &pub_params), 1) + || !TEST_ptr_null(OSSL_PARAM_locate(pub_params, privtag))) goto end; /* - * Select only the public key when using EVP_PKEY_fromdata() and check that - * the resulting key does not contain a private key. + * Round-trip: importing only the public selection from the full keypair + * params must yield a key that has no private component. */ if (!TEST_ptr(fromctx = EVP_PKEY_CTX_new_from_name(mainctx, keytype, NULL)) || !TEST_int_eq(EVP_PKEY_fromdata_init(fromctx), 1) @@ -347,10 +480,8 @@ static int do_pkey_tofrom_data_select(EVP_PKEY *key, const char *keytype) 1) || !TEST_false(pkey_has_private(fromkey, privtag, use_octstring))) goto end; - /* - * Select the keypair when using EVP_PKEY_fromdata() and check that - * the resulting key contains a private key. - */ + + /* Round-trip: a full keypair import must carry the private component. */ if (!TEST_int_eq(EVP_PKEY_fromdata(fromctx, &fromkeypair, EVP_PKEY_KEYPAIR, keypair_params), 1) @@ -366,35 +497,135 @@ static int do_pkey_tofrom_data_select(EVP_PKEY *key, const char *keytype) return ret; } -#ifndef OPENSSL_NO_DH -static int test_dh_tofrom_data_select(void) +/* + * Pass every advertised gettable parameter through EVP_PKEY_get_params() + * as a probe, twice: once with NULL data (size negotiation), then again + * with storage allocated for the advertised type. Either fetch must + * succeed as a whole. Pass 2 is what exercises the type-matching + * branches in the per-type OSSL_PARAM setters: a NULL-data probe + * succeeds before those branches are reached, which is why this check + * would otherwise miss gettable-table / getter mismatches (an entry + * advertised as OCTET_STRING whose getter populates it as a BIGNUM). + * + * The provider is free to leave individual entries unmodified, e.g. + * private-key data on a public-only key; only whole-fetch failure + * is treated as a regression. + */ +static int do_pkey_all_gettables_probe(EVP_PKEY *pkey, const char *keytype) { - int ret; - OSSL_PARAM params[2]; - EVP_PKEY *key = NULL; - EVP_PKEY_CTX *gctx = NULL; -#ifndef OPENSSL_NO_DEPRECATED_3_0 - const DH *dhkey; - const BIGNUM *privkey; -#endif + int ret = 0; + const OSSL_PARAM *gettable; + OSSL_PARAM *probe = NULL; + void **storage = NULL; + size_t n = 0, i; + int need_refetch = 0; - params[0] = OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0); - params[1] = OSSL_PARAM_construct_end(); - ret = TEST_ptr(gctx = EVP_PKEY_CTX_new_from_name(mainctx, "DHX", NULL)) - && TEST_int_gt(EVP_PKEY_keygen_init(gctx), 0) - && TEST_true(EVP_PKEY_CTX_set_params(gctx, params)) - && TEST_int_gt(EVP_PKEY_generate(gctx, &key), 0) - && TEST_true(do_pkey_tofrom_data_select(key, "DHX")); -#ifndef OPENSSL_NO_DEPRECATED_3_0 - ret = ret && TEST_ptr(dhkey = EVP_PKEY_get0_DH(key)) - && TEST_ptr(privkey = DH_get0_priv_key(dhkey)) - && TEST_int_le(BN_num_bits(privkey), 225); -#endif - EVP_PKEY_free(key); - EVP_PKEY_CTX_free(gctx); + if (!TEST_ptr(gettable = EVP_PKEY_gettable_params(pkey))) + goto err; + + while (gettable[n].key != NULL) + n++; + if (!TEST_ptr(probe = OPENSSL_zalloc((n + 1) * sizeof(*probe))) + || (n > 0 + && !TEST_ptr(storage = OPENSSL_zalloc(n * sizeof(*storage))))) + goto err; + + for (i = 0; i < n; i++) { + /* + * Copy the advertised entry as a template, then reset the + * data fields to the "probe" state. For OCTET_PTR / UTF8_PTR + * the setter writes *data directly (no size negotiation), + * so hand it a pointer slot up front. + */ + probe[i] = gettable[i]; + probe[i].data = NULL; + probe[i].data_size = 0; + probe[i].return_size = OSSL_PARAM_UNMODIFIED; + if (gettable[i].data_type == OSSL_PARAM_OCTET_PTR + || gettable[i].data_type == OSSL_PARAM_UTF8_PTR) { + if (!TEST_ptr(storage[i] = OPENSSL_zalloc(sizeof(void *)))) + goto err; + probe[i].data = storage[i]; + } + } + probe[n] = OSSL_PARAM_construct_end(); + + /* Pass 1: NULL-data probe populates return_size for sized entries. */ + if (!TEST_true(EVP_PKEY_get_params(pkey, probe))) { + TEST_info("%s: Pass 1 (size probe) failed", keytype); + goto err; + } + + /* Allocate storage for each populated sized entry. */ + for (i = 0; i < n; i++) { + size_t need; + + if (!OSSL_PARAM_modified(&probe[i])) + continue; + switch (probe[i].data_type) { + case OSSL_PARAM_INTEGER: + case OSSL_PARAM_UNSIGNED_INTEGER: + case OSSL_PARAM_OCTET_STRING: + case OSSL_PARAM_REAL: + need = probe[i].return_size; + if (!TEST_ptr(storage[i] = OPENSSL_malloc(need == 0 ? 1 : need))) + goto err; + probe[i].data = storage[i]; + probe[i].data_size = need; + probe[i].return_size = OSSL_PARAM_UNMODIFIED; + need_refetch = 1; + break; + case OSSL_PARAM_UTF8_STRING: + /* Leave room for a trailing NUL beyond return_size. */ + need = probe[i].return_size + 1; + if (!TEST_ptr(storage[i] = OPENSSL_malloc(need))) + goto err; + probe[i].data = storage[i]; + probe[i].data_size = need; + probe[i].return_size = OSSL_PARAM_UNMODIFIED; + need_refetch = 1; + break; + default: + /* PTR types were populated in Pass 1; unknown types left as-is. */ + break; + } + } + + /* + * Pass 2: real fetch, with typed storage. This is what actually + * catches advertised-vs-populated type mismatches: the per-type + * OSSL_PARAM_set_*() setters only enforce data_type when data is + * non-NULL. + */ + if (need_refetch && !TEST_true(EVP_PKEY_get_params(pkey, probe))) { + TEST_info("%s: Pass 2 (real fetch) failed", keytype); + goto err; + } + ret = 1; +err: + if (storage != NULL) + for (i = 0; i < n; i++) + OPENSSL_free(storage[i]); + OPENSSL_free(storage); + OPENSSL_free(probe); return ret; } +/* + * Composite check: exercise both the selection-mask semantics of + * todata/fromdata and the advertised-vs-populated type consistency of + * every gettable parameter on the given key. The individual helpers are + * algorithm-agnostic, so this driver works for any asymmetric EVP_PKEY. + * Each keytype-specific test function reduces to (a) key generation and + * (b) invoking this driver. + */ +static int do_pkey_checks(EVP_PKEY *key, const char *keytype) +{ + return do_pkey_tofrom_data_select(key, keytype) + && do_pkey_all_gettables_probe(key, keytype); +} + +#ifndef OPENSSL_NO_DH static int test_dh_paramgen(void) { int ret; @@ -559,57 +790,7 @@ static int test_ec_d2i_i2d_pubkey(void) return ret; } -static int test_ec_tofrom_data_select(void) -{ - int ret; - EVP_PKEY *key = NULL; - - ret = TEST_ptr(key = EVP_PKEY_Q_keygen(mainctx, NULL, "EC", "P-256")) - && TEST_true(do_pkey_tofrom_data_select(key, "EC")); - EVP_PKEY_free(key); - return ret; -} - -#ifndef OPENSSL_NO_ECX -static int test_ecx_tofrom_data_select(void) -{ - int ret; - EVP_PKEY *key = NULL; - - ret = TEST_ptr(key = EVP_PKEY_Q_keygen(mainctx, NULL, "X25519")) - && TEST_true(do_pkey_tofrom_data_select(key, "X25519")); - EVP_PKEY_free(key); - return ret; -} -#endif -#endif - -#ifndef OPENSSL_NO_SM2 -static int test_sm2_tofrom_data_select(void) -{ - int ret; - EVP_PKEY *key = NULL; - - ret = TEST_ptr(key = EVP_PKEY_Q_keygen(mainctx, NULL, "SM2")) - && TEST_true(do_pkey_tofrom_data_select(key, "SM2")); - EVP_PKEY_free(key); - return ret; -} -#endif - -static int test_rsa_tofrom_data_select(void) -{ - int ret; - EVP_PKEY *key = NULL; - const unsigned char *pdata = kExampleRSAKeyDER; - int pdata_len = sizeof(kExampleRSAKeyDER); - - ret = TEST_ptr(key = d2i_AutoPrivateKey_ex(NULL, &pdata, pdata_len, - mainctx, NULL)) - && TEST_true(do_pkey_tofrom_data_select(key, "RSA")); - EVP_PKEY_free(key); - return ret; -} +#endif /* OPENSSL_NO_EC */ /* This is the equivalent of test_d2i_AutoPrivateKey in evp_extra_test */ static int test_d2i_AutoPrivateKey_ex(int i) @@ -1069,7 +1250,9 @@ static const unsigned char dsa_pub[] = { 0xcc, 0xe2, 0x46, 0xce, 0xf5, 0x6d, 0xd8, 0x18, 0x91, 0xc4, 0x20, 0xbf, 0x07, 0x48, 0x45, 0xfd }; +#endif +#ifndef OPENSSL_NO_DSA static int do_check_params(OSSL_PARAM key_params[], int expected) { EVP_PKEY_CTX *gen_ctx = NULL, *check_ctx = NULL; @@ -1116,20 +1299,6 @@ static int do_check_int(OSSL_PARAM params[], const char *key, int expected) && TEST_int_eq(val, expected); } -static int test_dsa_tofrom_data_select(void) -{ - int ret; - EVP_PKEY *key = NULL; - const unsigned char *pkeydata = dsa_key; - - ret = TEST_ptr(key = d2i_AutoPrivateKey_ex(NULL, &pkeydata, sizeof(dsa_key), - mainctx, NULL)) - && TEST_true(do_pkey_tofrom_data_select(key, "DSA")); - - EVP_PKEY_free(key); - return ret; -} - static int test_dsa_todata(void) { EVP_PKEY *pkey = NULL; @@ -1483,6 +1652,112 @@ static int evp_test_name_parsing(void) return 1; } +/* + * Table-driven driver for do_pkey_checks(). Each entry names the + * algorithm and supplies either (a) a prefabricated DER blob, loaded + * via d2i_AutoPrivateKey_ex(), or (b) an optional OSSL_PARAM array + * passed to EVP_PKEY_CTX_set_params() before EVP_PKEY_generate(). + * The downstream checks are algorithm-agnostic; only the per-algorithm + * inputs live in this table. + */ +typedef struct pkey_test_spec_st { + const char *name; /* algorithm name for keygen or logging */ + const unsigned char *der; /* prefab private key DER, or NULL */ + uint32_t der_len; /* size of the DER blob when set */ + const OSSL_PARAM *params; /* keygen params, or NULL for defaults */ +} PKEY_TEST_SPEC; + +static const PKEY_TEST_SPEC pkey_test_specs[] = { +#ifndef OPENSSL_NO_DH + { "DHX", NULL, 0, dhx_keygen_params }, +#endif +#ifndef OPENSSL_NO_DSA + { "DSA", dsa_key, sizeof(dsa_key), NULL }, +#endif + { "RSA", kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER), NULL }, + { "RSA-PSS", kExampleRSAPSSKeyDER, sizeof(kExampleRSAPSSKeyDER), NULL }, +#ifndef OPENSSL_NO_EC + { "EC", NULL, 0, ec_keygen_params }, +#ifndef OPENSSL_NO_ECX + { "X25519", NULL, 0, NULL }, + { "ED25519", NULL, 0, NULL }, +#endif +#ifndef OPENSSL_NO_SM2 + { "SM2", NULL, 0, NULL }, +#endif +#endif +#ifndef OPENSSL_NO_ML_KEM + { "ML-KEM-512", NULL, 0, NULL }, +#endif +#ifndef OPENSSL_NO_ML_DSA + { "ML-DSA-44", NULL, 0, NULL }, +#endif +#ifndef OPENSSL_NO_SLH_DSA + { "SLH-DSA-SHA2-128f", NULL, 0, NULL }, +#endif +}; + +static EVP_PKEY *pkey_from_spec(OSSL_LIB_CTX *libctx, + const PKEY_TEST_SPEC *spec) +{ + EVP_PKEY *key = NULL; + EVP_PKEY_CTX *gctx = NULL; + + if (spec->der != NULL) { + const unsigned char *p = spec->der; + + return d2i_AutoPrivateKey_ex(NULL, &p, spec->der_len, libctx, NULL); + } + + if ((gctx = EVP_PKEY_CTX_new_from_name(libctx, spec->name, NULL)) == NULL + || EVP_PKEY_keygen_init(gctx) <= 0 + || (spec->params != NULL + && EVP_PKEY_CTX_set_params(gctx, spec->params) <= 0) + || EVP_PKEY_generate(gctx, &key) <= 0) { + EVP_PKEY_free(key); + key = NULL; + } + EVP_PKEY_CTX_free(gctx); + return key; +} + +static int test_pkey_by_spec(int i) +{ + EVP_PKEY *key = pkey_from_spec(mainctx, &pkey_test_specs[i]); + int ret = TEST_ptr(key) + && do_pkey_checks(key, pkey_test_specs[i].name); + + EVP_PKEY_free(key); + return ret; +} + +#if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0) +/* + * DHX keygen with group "ffdhe2048" reduces the private exponent modulo + * the sub-group order, so the exposed BN_num_bits() should not exceed + * the sub-group size. This tail check is DHX-specific and therefore + * does not fit the generic spec-table driver. + */ +static int test_dh_priv_bits(void) +{ + static const PKEY_TEST_SPEC dhx_spec = { + "DHX", NULL, 0, dhx_keygen_params + }; + int ret; + EVP_PKEY *key; + const DH *dhkey; + const BIGNUM *privkey; + + if (!TEST_ptr(key = pkey_from_spec(mainctx, &dhx_spec))) + return 0; + ret = TEST_ptr(dhkey = EVP_PKEY_get0_DH(key)) + && TEST_ptr(privkey = DH_get0_priv_key(dhkey)) + && TEST_int_le(BN_num_bits(privkey), 225); + EVP_PKEY_free(key); + return ret; +} +#endif + int setup_tests(void) { if (!test_get_libctx(&mainctx, &nullprov, NULL, NULL, NULL)) { @@ -1497,28 +1772,22 @@ int setup_tests(void) ADD_TEST(test_new_keytype); #ifndef OPENSSL_NO_EC ADD_ALL_TESTS(test_d2i_PrivateKey_ex, 2); - ADD_TEST(test_ec_tofrom_data_select); -#ifndef OPENSSL_NO_ECX - ADD_TEST(test_ecx_tofrom_data_select); -#endif ADD_TEST(test_ec_d2i_i2d_pubkey); #else ADD_ALL_TESTS(test_d2i_PrivateKey_ex, 1); #endif -#ifndef OPENSSL_NO_SM2 - ADD_TEST(test_sm2_tofrom_data_select); -#endif #ifndef OPENSSL_NO_DSA ADD_TEST(test_dsa_todata); - ADD_TEST(test_dsa_tofrom_data_select); ADD_ALL_TESTS(test_dsa_fromdata_digest_prop, 2); #endif #ifndef OPENSSL_NO_DH - ADD_TEST(test_dh_tofrom_data_select); ADD_TEST(test_dh_paramgen); ADD_TEST(test_dh_paramfromdata); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + ADD_TEST(test_dh_priv_bits); +#endif #endif - ADD_TEST(test_rsa_tofrom_data_select); + ADD_ALL_TESTS(test_pkey_by_spec, OSSL_NELEM(pkey_test_specs)); ADD_TEST(test_pkey_todata_null); ADD_TEST(test_pkey_export_null); From a201731333daee5a13d9ca7f010a230b0f467a63 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Thu, 30 Jul 2026 23:12:26 +1000 Subject: [PATCH 108/189] Reject clearly degenerate RSASVE parameters. - A public exponent <= 1 - Ciphertext <= 1 or equal to n-1, where n is the public modulus. Reviewed-by: Nikola Pajkovsky Reviewed-by: Bob Beck MergeDate: Mon Aug 10 06:27:45 2026 (Merged from https://github.com/openssl/openssl/pull/32124) (cherry picked from commit 69de45cd12e51d69a098b7c81c2bd7ee80f060b5) --- crypto/rsa/rsa_ossl.c | 5 +- providers/implementations/kem/rsa_kem.c | 13 +++ test/evp_extra_test.c | 132 ++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 4 deletions(-) diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c index 2fcf02a9ab05d..ba195e71874e7 100644 --- a/crypto/rsa/rsa_ossl.c +++ b/crypto/rsa/rsa_ossl.c @@ -567,7 +567,6 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, if (BN_bin2bn(from, (int)flen, f) == NULL) goto err; -#ifdef FIPS_MODULE /* * See SP800-56Br2, section 7.1.2.1 * RSADP: 1 < f < (n – 1) @@ -588,9 +587,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } - } else -#endif - { + } else { if (BN_ucmp(f, rsa->n) >= 0) { ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; diff --git a/providers/implementations/kem/rsa_kem.c b/providers/implementations/kem/rsa_kem.c index 78925809d9853..c74dcffc77175 100644 --- a/providers/implementations/kem/rsa_kem.c +++ b/providers/implementations/kem/rsa_kem.c @@ -131,6 +131,7 @@ static int rsakem_init(void *vprsactx, void *vrsa, const char *desc) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + const BIGNUM *e = NULL; int protect = 0; if (!ossl_prov_is_running()) @@ -146,6 +147,18 @@ static int rsakem_init(void *vprsactx, void *vrsa, RSA_free(prsactx->rsa); prsactx->rsa = vrsa; + /* + * Reject the trivial public exponent e <= 1. The FIPS module enforces the + * full SP 800-56B §6.4.1.1 constraints via ossl_fips_ind_rsa_key_check() + * below; non-FIPS callers wanting the complete §6.4.2 vetting can use + * EVP_PKEY_public_check(). + */ + RSA_get0_key(prsactx->rsa, NULL, &e, NULL); + if (e == NULL || BN_cmp(e, BN_value_one()) <= 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + return 0; + } + OSSL_FIPS_IND_SET_APPROVED(prsactx) if (!rsakem_set_ctx_params(prsactx, params)) return 0; diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 72cf0ea66d3de..c44c748752676 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -1494,6 +1494,135 @@ static int test_evp_get_ec_pub(void) return ret; } +/* + * RSASVE (SP 800-56B 7.2) must reject mathematically degenerate inputs: + * a public exponent e <= 1, and a ciphertext c in {0, 1, n - 1}. Outside + * the FIPS module these were previously accepted; the checks now apply to + * every build, so exercise them in the default provider. + */ + +/* + * With e <= 1 the RSA public operation is the identity (or worse), so + * encapsulation setup must reject the key with PROV_R_INVALID_KEY. idx + * selects the exponent: 0 or 1. + */ +static int test_rsasve_degenerate_exponent(int idx) +{ + EVP_PKEY *rsakey = NULL; + EVP_PKEY *pubkey = NULL; + EVP_PKEY_CTX *genctx = NULL; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + BIGNUM *n = NULL; + BIGNUM *e = NULL; + int testresult = 0; + + /* Borrow a real modulus; only the exponent is degenerate. */ + if (!TEST_ptr(rsakey = load_example_rsa_key()) + || !TEST_true(EVP_PKEY_get_bn_param(rsakey, OSSL_PKEY_PARAM_RSA_N, &n))) + goto err; + + if (!TEST_ptr(e = BN_new()) + || !TEST_true(BN_set_word(e, (BN_ULONG)idx))) /* idx is 0 or 1 */ + goto err; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e)) + || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) + goto err; + + if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(testctx, "RSA", NULL)) + || !TEST_int_gt(EVP_PKEY_fromdata_init(genctx), 0) + || !TEST_int_gt(EVP_PKEY_fromdata(genctx, &pubkey, EVP_PKEY_PUBLIC_KEY, + params), + 0)) + goto err; + + ERR_clear_error(); + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pubkey, NULL)) + || !TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY)) + goto err; + + testresult = 1; +err: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_CTX_free(genctx); + EVP_PKEY_free(pubkey); + EVP_PKEY_free(rsakey); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + BN_free(e); + BN_free(n); + return testresult; +} + +/* + * A ciphertext c in {0, 1, n - 1} is a fixed point or trivial case of RSADP, + * so RSASVE recovery must reject it. idx selects the ciphertext: 0, 1, or + * n - 1. The ciphertext length must equal the modulus length. + */ +static int test_rsasve_degenerate_ciphertext(int idx) +{ + EVP_PKEY *rsakey = NULL; + EVP_PKEY_CTX *ctx = NULL; + BIGNUM *n = NULL; + unsigned char *ct = NULL; + unsigned char *secret = NULL; + size_t ctlen = 0; + size_t secretlen = 0; + int expected_reason = 0; + int testresult = 0; + + if (!TEST_ptr(rsakey = load_example_rsa_key()) + || !TEST_true(EVP_PKEY_get_bn_param(rsakey, OSSL_PKEY_PARAM_RSA_N, &n))) + goto err; + + ctlen = secretlen = (size_t)EVP_PKEY_get_size(rsakey); + if (!TEST_ptr(ct = OPENSSL_zalloc(ctlen)) + || !TEST_ptr(secret = OPENSSL_malloc(secretlen))) + goto err; + + switch (idx) { + case 0: /* c = 0 */ + expected_reason = RSA_R_DATA_TOO_SMALL; + break; + case 1: /* c = 1 */ + ct[ctlen - 1] = 1; + expected_reason = RSA_R_DATA_TOO_SMALL; + break; + case 2: /* c = n - 1 */ + if (!TEST_true(BN_sub_word(n, 1)) + || !TEST_int_eq(BN_bn2binpad(n, ct, (int)ctlen), (int)ctlen)) + goto err; + expected_reason = RSA_R_DATA_TOO_LARGE_FOR_MODULUS; + break; + default: + goto err; + } + + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(testctx, rsakey, NULL)) + || !TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1) + || !TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE"), 1)) + goto err; + + ERR_clear_error(); + if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen, ct, ctlen), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), expected_reason)) + goto err; + + testresult = 1; +err: + OPENSSL_free(secret); + OPENSSL_free(ct); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(rsakey); + BN_free(n); + return testresult; +} + /* Test that using a legacy EC key with only a private key in it works */ #ifndef OPENSSL_NO_DEPRECATED_3_0 static int test_EC_priv_only_legacy(void) @@ -7973,6 +8102,9 @@ int setup_tests(void) ADD_ALL_TESTS(test_aead_oneshot_roundtrip, 2 * OSSL_NELEM(aead_oneshot_cfgs)); + ADD_ALL_TESTS(test_rsasve_degenerate_exponent, 2); + ADD_ALL_TESTS(test_rsasve_degenerate_ciphertext, 3); + /* Test cases for CVE-2026-45446 */ ADD_TEST(test_aes_gcm_siv_empty_data); ADD_TEST(test_aes_siv_ctx_reuse); From c3ec94753c83e1be42fe6f0849d5d11320677fa4 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Mon, 10 Aug 2026 10:00:08 +0200 Subject: [PATCH 109/189] move the test code outside of the #ifdef during the test backportg, the test was accidentally placed into ifdef Fixes: 69de45cd12e5 ("Reject clearly degenerate RSASVE parameters.") Signed-off-by: Nikola Pajkovsky Reviewed-by: Tomas Mraz Reviewed-by: Eugene Syromiatnikov MergeDate: Mon Aug 10 10:34:32 2026 (Merged from https://github.com/openssl/openssl/pull/32261) (cherry picked from commit 190a56c010a306d8e03216a1db5c4d495f52cb94) --- test/evp_extra_test.c | 258 +++++++++++++++++++++--------------------- 1 file changed, 129 insertions(+), 129 deletions(-) diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index c44c748752676..fb013b0c0647c 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -1125,6 +1125,135 @@ static int test_selection(EVP_PKEY *pkey, int selection) } #endif /* !OPENSSL_NO_DH || !OPENSSL_NO_DSA || !OPENSSL_NO_EC */ +/* + * RSASVE (SP 800-56B 7.2) must reject mathematically degenerate inputs: + * a public exponent e <= 1, and a ciphertext c in {0, 1, n - 1}. Outside + * the FIPS module these were previously accepted; the checks now apply to + * every build, so exercise them in the default provider. + */ + +/* + * With e <= 1 the RSA public operation is the identity (or worse), so + * encapsulation setup must reject the key with PROV_R_INVALID_KEY. idx + * selects the exponent: 0 or 1. + */ +static int test_rsasve_degenerate_exponent(int idx) +{ + EVP_PKEY *rsakey = NULL; + EVP_PKEY *pubkey = NULL; + EVP_PKEY_CTX *genctx = NULL; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + BIGNUM *n = NULL; + BIGNUM *e = NULL; + int testresult = 0; + + /* Borrow a real modulus; only the exponent is degenerate. */ + if (!TEST_ptr(rsakey = load_example_rsa_key()) + || !TEST_true(EVP_PKEY_get_bn_param(rsakey, OSSL_PKEY_PARAM_RSA_N, &n))) + goto err; + + if (!TEST_ptr(e = BN_new()) + || !TEST_true(BN_set_word(e, (BN_ULONG)idx))) /* idx is 0 or 1 */ + goto err; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e)) + || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) + goto err; + + if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(testctx, "RSA", NULL)) + || !TEST_int_gt(EVP_PKEY_fromdata_init(genctx), 0) + || !TEST_int_gt(EVP_PKEY_fromdata(genctx, &pubkey, EVP_PKEY_PUBLIC_KEY, + params), + 0)) + goto err; + + ERR_clear_error(); + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pubkey, NULL)) + || !TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY)) + goto err; + + testresult = 1; +err: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_CTX_free(genctx); + EVP_PKEY_free(pubkey); + EVP_PKEY_free(rsakey); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + BN_free(e); + BN_free(n); + return testresult; +} + +/* + * A ciphertext c in {0, 1, n - 1} is a fixed point or trivial case of RSADP, + * so RSASVE recovery must reject it. idx selects the ciphertext: 0, 1, or + * n - 1. The ciphertext length must equal the modulus length. + */ +static int test_rsasve_degenerate_ciphertext(int idx) +{ + EVP_PKEY *rsakey = NULL; + EVP_PKEY_CTX *ctx = NULL; + BIGNUM *n = NULL; + unsigned char *ct = NULL; + unsigned char *secret = NULL; + size_t ctlen = 0; + size_t secretlen = 0; + int expected_reason = 0; + int testresult = 0; + + if (!TEST_ptr(rsakey = load_example_rsa_key()) + || !TEST_true(EVP_PKEY_get_bn_param(rsakey, OSSL_PKEY_PARAM_RSA_N, &n))) + goto err; + + ctlen = secretlen = (size_t)EVP_PKEY_get_size(rsakey); + if (!TEST_ptr(ct = OPENSSL_zalloc(ctlen)) + || !TEST_ptr(secret = OPENSSL_malloc(secretlen))) + goto err; + + switch (idx) { + case 0: /* c = 0 */ + expected_reason = RSA_R_DATA_TOO_SMALL; + break; + case 1: /* c = 1 */ + ct[ctlen - 1] = 1; + expected_reason = RSA_R_DATA_TOO_SMALL; + break; + case 2: /* c = n - 1 */ + if (!TEST_true(BN_sub_word(n, 1)) + || !TEST_int_eq(BN_bn2binpad(n, ct, (int)ctlen), (int)ctlen)) + goto err; + expected_reason = RSA_R_DATA_TOO_LARGE_FOR_MODULUS; + break; + default: + goto err; + } + + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(testctx, rsakey, NULL)) + || !TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1) + || !TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE"), 1)) + goto err; + + ERR_clear_error(); + if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen, ct, ctlen), 0) + || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), expected_reason)) + goto err; + + testresult = 1; +err: + OPENSSL_free(secret); + OPENSSL_free(ct); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(rsakey); + BN_free(n); + return testresult; +} + /* * Test combinations of private, public, missing and private + public key * params to ensure they are all accepted @@ -1494,135 +1623,6 @@ static int test_evp_get_ec_pub(void) return ret; } -/* - * RSASVE (SP 800-56B 7.2) must reject mathematically degenerate inputs: - * a public exponent e <= 1, and a ciphertext c in {0, 1, n - 1}. Outside - * the FIPS module these were previously accepted; the checks now apply to - * every build, so exercise them in the default provider. - */ - -/* - * With e <= 1 the RSA public operation is the identity (or worse), so - * encapsulation setup must reject the key with PROV_R_INVALID_KEY. idx - * selects the exponent: 0 or 1. - */ -static int test_rsasve_degenerate_exponent(int idx) -{ - EVP_PKEY *rsakey = NULL; - EVP_PKEY *pubkey = NULL; - EVP_PKEY_CTX *genctx = NULL; - EVP_PKEY_CTX *ctx = NULL; - OSSL_PARAM_BLD *bld = NULL; - OSSL_PARAM *params = NULL; - BIGNUM *n = NULL; - BIGNUM *e = NULL; - int testresult = 0; - - /* Borrow a real modulus; only the exponent is degenerate. */ - if (!TEST_ptr(rsakey = load_example_rsa_key()) - || !TEST_true(EVP_PKEY_get_bn_param(rsakey, OSSL_PKEY_PARAM_RSA_N, &n))) - goto err; - - if (!TEST_ptr(e = BN_new()) - || !TEST_true(BN_set_word(e, (BN_ULONG)idx))) /* idx is 0 or 1 */ - goto err; - - if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n)) - || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e)) - || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) - goto err; - - if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(testctx, "RSA", NULL)) - || !TEST_int_gt(EVP_PKEY_fromdata_init(genctx), 0) - || !TEST_int_gt(EVP_PKEY_fromdata(genctx, &pubkey, EVP_PKEY_PUBLIC_KEY, - params), - 0)) - goto err; - - ERR_clear_error(); - if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pubkey, NULL)) - || !TEST_int_eq(EVP_PKEY_encapsulate_init(ctx, NULL), 0) - || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), PROV_R_INVALID_KEY)) - goto err; - - testresult = 1; -err: - EVP_PKEY_CTX_free(ctx); - EVP_PKEY_CTX_free(genctx); - EVP_PKEY_free(pubkey); - EVP_PKEY_free(rsakey); - OSSL_PARAM_free(params); - OSSL_PARAM_BLD_free(bld); - BN_free(e); - BN_free(n); - return testresult; -} - -/* - * A ciphertext c in {0, 1, n - 1} is a fixed point or trivial case of RSADP, - * so RSASVE recovery must reject it. idx selects the ciphertext: 0, 1, or - * n - 1. The ciphertext length must equal the modulus length. - */ -static int test_rsasve_degenerate_ciphertext(int idx) -{ - EVP_PKEY *rsakey = NULL; - EVP_PKEY_CTX *ctx = NULL; - BIGNUM *n = NULL; - unsigned char *ct = NULL; - unsigned char *secret = NULL; - size_t ctlen = 0; - size_t secretlen = 0; - int expected_reason = 0; - int testresult = 0; - - if (!TEST_ptr(rsakey = load_example_rsa_key()) - || !TEST_true(EVP_PKEY_get_bn_param(rsakey, OSSL_PKEY_PARAM_RSA_N, &n))) - goto err; - - ctlen = secretlen = (size_t)EVP_PKEY_get_size(rsakey); - if (!TEST_ptr(ct = OPENSSL_zalloc(ctlen)) - || !TEST_ptr(secret = OPENSSL_malloc(secretlen))) - goto err; - - switch (idx) { - case 0: /* c = 0 */ - expected_reason = RSA_R_DATA_TOO_SMALL; - break; - case 1: /* c = 1 */ - ct[ctlen - 1] = 1; - expected_reason = RSA_R_DATA_TOO_SMALL; - break; - case 2: /* c = n - 1 */ - if (!TEST_true(BN_sub_word(n, 1)) - || !TEST_int_eq(BN_bn2binpad(n, ct, (int)ctlen), (int)ctlen)) - goto err; - expected_reason = RSA_R_DATA_TOO_LARGE_FOR_MODULUS; - break; - default: - goto err; - } - - if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(testctx, rsakey, NULL)) - || !TEST_int_eq(EVP_PKEY_decapsulate_init(ctx, NULL), 1) - || !TEST_int_eq(EVP_PKEY_CTX_set_kem_op(ctx, "RSASVE"), 1)) - goto err; - - ERR_clear_error(); - if (!TEST_int_eq(EVP_PKEY_decapsulate(ctx, secret, &secretlen, ct, ctlen), 0) - || !TEST_int_eq(ERR_GET_REASON(ERR_get_error()), expected_reason)) - goto err; - - testresult = 1; -err: - OPENSSL_free(secret); - OPENSSL_free(ct); - EVP_PKEY_CTX_free(ctx); - EVP_PKEY_free(rsakey); - BN_free(n); - return testresult; -} - /* Test that using a legacy EC key with only a private key in it works */ #ifndef OPENSSL_NO_DEPRECATED_3_0 static int test_EC_priv_only_legacy(void) From d10f83754393be34d5a2df48605955b554980ddc Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 4 Aug 2026 18:00:37 +0200 Subject: [PATCH 110/189] statem: fix missing SSLfatal in TLSv1.3 ticket construction tls_construct_new_session_ticket() assumed ssl_session_dup() calls SSLfatal() on failure but it never does, unlike all its other call sites which call SSLfatal() themselves. An allocation failure there made the construct function return CON_FUNC_ERROR without entering the fatal state, tripping the check_fatal assertion in write_state_machine() on debug builds. Assisted-by: Claude:claude-fable-5 Reviewed-by: Matt Caswell Reviewed-by: Frederik Wedel-Heinen Reviewed-by: Tomas Mraz MergeDate: Mon Aug 10 13:55:51 2026 (Merged from https://github.com/openssl/openssl/pull/32183) (cherry picked from commit d271efc353856df91d28c8f54ead56b298c852f0) --- ssl/statem/statem_srvr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index b2f8a0ebc43d2..3c7d2ac433713 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -4251,7 +4251,7 @@ CON_FUNC_RETURN tls_construct_new_session_ticket(SSL_CONNECTION *s, WPACKET *pkt SSL_SESSION *new_sess = ssl_session_dup(s->session, 0); if (new_sess == NULL) { - /* SSLfatal already called */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB); goto err; } From 28b27fe53b975e7a86310c9becffd738482b8ddb Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 30 Jul 2026 09:27:01 -0400 Subject: [PATCH 111/189] Fix FIPS to require a derivation function FIPS-140-3 requires that if a CTR-DRBG is allocated from the fips provider that either: a) The entropy source must be NIST validated and exist within the FIPS boundary or b) The CTR-DRBG must use a derivation function with an entropy source outside the FIPS boundary Given that we have no approved noise source inside the FIPS boundary, we need to enforce the fact that FIPS allocated CTR-DRBGS only allocate instances in which a derivation function is requested (i.e. the USE_DF parameter is asserted and set to one) Follow path b, and ensure that FIPS CTR-DRBG allocations assert the use of USE_DF or fail if an allocation does not Reviewed-by: Viktor Dukhovni Reviewed-by: Andrew Dinh MergeDate: Mon Aug 10 14:00:06 2026 (Merged from https://github.com/openssl/openssl/pull/32249) --- providers/implementations/rands/drbg_ctr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c index d42f085857136..b7b20e12f81aa 100644 --- a/providers/implementations/rands/drbg_ctr.c +++ b/providers/implementations/rands/drbg_ctr.c @@ -588,6 +588,18 @@ static int drbg_ctr_init(PROV_DRBG *drbg) drbg->strength = keylen * 8; drbg->seedlen = keylen + 16; +#ifdef FIPS_MODULE + /* + * FIPS requires that we use a derivation function since our + * entropy source is outside the fips boundary + */ + if (ctr->use_df == 0) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_DERIVATION_FUNCTION_INIT_FAILED, + "FIPS requires the use of a derivation function"); + goto err; + } +#endif + if (ctr->use_df) { /* df initialisation */ static const unsigned char df_key[32] = { From e12d71f09a4cd41ca45920fe589b99df3b85532a Mon Sep 17 00:00:00 2001 From: Pauli Date: Sun, 9 Aug 2026 14:28:39 +1000 Subject: [PATCH 112/189] evp_test: condition CTR-DRBG tests on FIPS version when the df is not used Newer versions require the use of the derivation function and non-use is an error. This means a number of tests must be inhibited in such situations. Reviewed-by: Viktor Dukhovni Reviewed-by: Andrew Dinh Reviewed-by: Neil Horman MergeDate: Mon Aug 10 14:00:08 2026 (Merged from https://github.com/openssl/openssl/pull/32249) --- test/recipes/30-test_evp_data/evprand.txt | 145 +++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/test/recipes/30-test_evp_data/evprand.txt b/test/recipes/30-test_evp_data/evprand.txt index 9756859c0e80e..bf7db44030023 100644 --- a/test/recipes/30-test_evp_data/evprand.txt +++ b/test/recipes/30-test_evp_data/evprand.txt @@ -27,7 +27,6 @@ EntropyPredictionResistanceA.0 = C0535ACD3D715A0B1453AB3447D53D9131C939AEE1D9CA2 EntropyPredictionResistanceB.0 = 9FBC48890273FCAFCA1904B6486D1877CAD91EB601E979259506F93BA462AC17D8676C570B2231D4D98EC617C4826573 Output.0 = 19CED57563D065B606DA27DD5E8DE83B93BB7C8F8B02D0288F475550C3F44B77 - # Test vectors come from: # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip @@ -3561,6 +3560,7 @@ AdditionalInputA.14 = 84922c0335a0ead609e5a92cfc4a225bd3c7c01ab4580b786338e1caa3 AdditionalInputB.14 = 34b034ca643bbfd2fcc57c9b53e0f9b3fd6a73454f1823dfe7b7076ec73fd956 Output.14 = 6caa4475189ee00ddc54910f8723b0e5b8d3d0c321ce7f2ac7194d134a0a31d96b102dd58e092e08f8a008f05c4f2afb2901c6e29549d3a720aa2b1d1f461bb9 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -3596,6 +3596,7 @@ Output.13 = e2b531ea43c513a1564fa65e9a68d43c875137773102941d0ef544c84e3689b82eac Entropy.14 = 727c0ac75a99bb1a318e4fe2fe0f2e312b3b61d82b2e5071acfb4a36bc8258c1 Output.14 = f595ee1af437fe1bed8d451088b788f1cd599f2b0c47feac1fb5c6efbf7a14a8ab0ea11a3569a3c23b2a9702b415bda355c15afd275c0d67b38bcfb54ab13f70 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -3661,6 +3662,7 @@ AdditionalInputA.14 = 170a92d093d30f939b3eac628a18bab5faf86b3a5d91f30cfd0beafdec AdditionalInputB.14 = fd0349af015037cdbb52983155c89fc59f37d512543559c3ee6589f7b93861f6 Output.14 = 0273a1317f3dd36877a505ca2e440445094d3c702c4ff5f4a07daa3f810d8d7a4f4b9c54dce169a1307fbdc5d197e6a3edc3ea737bedc1c9857aa0e9f87943e2 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -3711,6 +3713,7 @@ Entropy.14 = 22d1d8c8bde76a239d032804717face16d77b51170d0f53ccbcca4eaff4fb315 PersonalisationString.14 = 5d3a7d40fdf95b98454bca03c6fcbf6abf3807de75171b55bab2db5a3f5f12f2 Output.14 = 1007e11f48e3c4813fddd67310db56d67a49fe93e45e61b37ba81485df6a62ee57ca41fa1d987f467c2939790a20421c2b4f70b28fb0b90bbeab1ac0ae884f1a +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -3791,6 +3794,7 @@ AdditionalInputA.14 = 1eed7463c004c94b600245f4967af955919d0f325a2baf2e9c5f6e1504 AdditionalInputB.14 = 6eace0fdabf1bc84d08eaa4afcbebd502f1d83847d2e86a1e68147b3b15a76cf Output.14 = da59c09259ecc1d61e05d3198f349904df1468ffaf85f5d6cc57489e2785e54e710413674bd2ac41896ce9010d9588446e7540b35519c4689a5818ace7dbe0a8 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -3826,6 +3830,7 @@ Output.13 = 78b32d396f5a919f5ccb9be2afaf5f6212d75bf084e99357e28ccc98d433696455b1 Entropy.14 = 42cb183d2a04c89c69efbcec08bee2003b9a1cd56878a774f0162bf70f2c708f Output.14 = cb4afdec033b42949ebbb27245fd33c1503c1278027e11a1f050e04080abe4850821b71ed5a6bd83da6bde8e56c5faed49da26887028bab807d1ad055e2a8a27 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -3891,6 +3896,7 @@ AdditionalInputA.14 = eb2888119b0020cff3ac53cbb81d8576457a863fb087f91c795c297f68 AdditionalInputB.14 = ad80f4ecff758da0a5beed20a9d851fcca2ad4ea0d54af619470e3cf3033a04a Output.14 = e2105e60f2f2fceb27c882caebb0c1eca543c359947c4319c503efa82ed5cb63640f627c82217260f0203220435c842d7993623a2b05e26e1ed1d03f68ab3cb1 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -3941,6 +3947,7 @@ Entropy.14 = 3acd2c23bbae4d02cc9e4bb548e264f43e35764b446595bfe1e45165d42c770a PersonalisationString.14 = afb8203d4f7900c35d7bb454a83c5f2667ab506a68b710011c0be67055dfc3eb Output.14 = 02664c0570c4d3c468d16cc7c8b99da7a7f1752249e30f2833b1b7cd32a4df3c23454621d79119a9aaccc52d3f9055dbde98e773c26d4dace09ce9be1f1f61b2 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4021,6 +4028,7 @@ AdditionalInputA.14 = f57cf314188b397797caa30733cdabd5ab2a90562cab9be5f812bbd482 AdditionalInputB.14 = 93839acaa271af55ec6c8464ac2ba8bc1c61584008b5d908b200d8048edc0562 Output.14 = 38a3dd584a68bd037c5d5be4a103083e1d4bbd8a845ac1832e4c545e942bb5232ccec9df2abaaf0870d1f75d3bf85aa9323b5eedc26a73ade2ddade69fcaf6d4 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4056,6 +4064,7 @@ Output.13 = e6e345a50ced3cc68ae24ed9ad8cdb482815284e66f9b0151fdd75d13c9758663c4d Entropy.14 = ab875886827197b784b137726f1f5862c016e2c8780452fe98f4eeb68f71aca5 Output.14 = b6634452661b019afbf2e9b6e20b8be7d9cab739383de8636404c275dc495f54fbf23205dbf843afebbc4e88c6ee126f729cc407ccbbe792e3319230f23023d1 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4121,6 +4130,7 @@ AdditionalInputA.14 = dacdc1a5c9b4215da6b1520c227724ffc888945a3cf1db2d2ff5c48266 AdditionalInputB.14 = f291eac0295f5e0936542010df7ca9c417cd78f7a109655e9050fd502ad91d4c Output.14 = 70b881acd434f90da8788bfe77226132c8a3f2544293b0ef7408559575ff0e52a17aff11b9601a4765e2ab0cc90f19f69fb4485554ec0b17ceabde960a56655d +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4171,6 +4181,7 @@ Entropy.14 = 0c4564ba254455b6557aec1cfee2b2b726d2c4f45379267f0e27d11c6f1edc7f PersonalisationString.14 = 46aefb024c6acdc9297d5019109310de558f6afcca730c8414c54f4e574fab1e Output.14 = c94894d56985d73ac516c1249cea3d8e79b67dcdb2bf24b830d52f9e1fbdd8bdb37a546c4ffe13186ceb0a230a14ee1be0e409eb19eef018e54f79c3ddd4fbd4 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4251,6 +4262,7 @@ AdditionalInputA.14 = 959a1aed8c1b0af637b8c0d0dfd600b0d5dcbcac12bc8cb160a2a0ee7f AdditionalInputB.14 = fdbb472c9f368a44f92bab4bd993c7f39d4e61c6503f69c205191d86bc1b2944 Output.14 = fa2f2a566b99ae810b2b95092da67bb16fa185013ad0c83a845b48cf4fa55f7017ed944d08b57d6813700fb60a30a2a2f976f8b9761516ef137e3e3a078312f9 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4286,6 +4298,7 @@ Output.13 = 9ab8f2730cd5039a1c78f837ccaf7747b27ca425b07728933e61bc39b5c09fd63a0f Entropy.14 = 397427acb3683af13636a70fa2d9ff5b6d032f9fc6197d62ce1027517cb66268 Output.14 = 2c6b5c5682187740fb566ca60644052b2e0bc3285a399e8127ae53fafa3d5286680416772e552a2cbce4a523f26e7e7e45827a291b61a8b6fc7836e3a14e694a +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4351,6 +4364,7 @@ AdditionalInputA.14 = 534589895777f502aa3712aeed8013d343a824584774d92f9b0668201d AdditionalInputB.14 = a97742c1e0c816626e67ebc81ba3987378499b75212b194bb56a6746029866b0 Output.14 = 8057f97b49700edc8ebf7bbc798e6eae639a443e4c8e935cd06ebf9e9bdb803cd3121a0602b32f088e7906abaa68b28b942e84bb09d13d565490d20295c520a6 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4401,6 +4415,7 @@ Entropy.14 = 315bbe530ecfa44eb27250f6d20f4b6c648e42c61f6faed6fe483f26f6f8427f PersonalisationString.14 = efa10fa5bc1e445c031620ebb37e7552c2dfa08307dfe53c1b8e74ec55050356 Output.14 = c592d9e7b67415d09dfc46d3039b3afc1ce66afa98e8793437cfcb5ab3a122c636f0a84edc04099d3819d7fa30d196880d9199de17f7170de725f3650ef34b19 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -4481,6 +4496,7 @@ AdditionalInputA.14 = 36551ef09232d2199547aaefecaaad217443d616433d9d169bd8cd3eae AdditionalInputB.14 = 9e57a4e96ace483dbc3c226d2723c9258063278140d220c4fd023c77fb20b84c Output.14 = ca43dcecdab689549bc4493a38a6a017f6048270e5d70d0d7576a2ab764d922bc346e30f42dc5a73ea6a210d2eba9bee5b5afe3c66867a68ab3fe0d08f511101 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4516,6 +4532,7 @@ Output.13 = 20d734ab5611a39d6ccaf8941d254804c36ba8bf206bf10d82f721ba9548b9f7cc10 Entropy.14 = 8dc5a9e8e9458f841dae788d24bb5fb192ef1ffaccd991f89f2b5d3ba57c1471612496c7d9cdd174 Output.14 = fd74a7b15c9af2ea140a2d0e353c3387b389144dda5779c69f299917dfb19de6ad60dd440c14c010ca161436243bf9d33a6649339a3543b8e71789621da7ab7b +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4581,6 +4598,7 @@ AdditionalInputA.14 = 79b75fe104f0d7c86bbe311585198f82350a13c4a7e450cfb86e440c00 AdditionalInputB.14 = 6f20134564e79c7eb530727f5b649996c89d7bd54ebac095c19a162348fce468782f0324f2138c84 Output.14 = d00f784a9613677023d27a4350efc4cc28f95a3928c4c8da67063ee59de5d2da13a3090f580e61fff1af27a8f4ba9418e07d856a996e836a89062064bac7a9cc +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4631,6 +4649,7 @@ Entropy.14 = 0ac627692b28d31e347179c8ee9e508e2b3ffbedae4009414b3b72e76a3739f0292 PersonalisationString.14 = 946fb7e5c3cbf3d198f19135b1a71a241ee892ac5a0316f57eae7076a4d99bf0e77fe23e81258cca Output.14 = 00007f407f75335a351d31d2754366f8f220ef2f9688a87e9d6aac59fa9f36be824b9bc7409ea991d3e0a7c411854b3701c84abdd7a696406dd13331e2785455 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4711,6 +4730,7 @@ AdditionalInputA.14 = 1564d70c91a7f72151a4483b9eba35b52c196656ff96875d7c59c6d116 AdditionalInputB.14 = c2731fd38e65f8e724378ad4e01359512cb473dd9854fc2303e61c2d197caad69b12fde14aed66b6 Output.14 = c68d3e5697f36c9db2535b05226aa118e00fdab95ca2cdbd37421298d46d2054e900b82ccb63227a23380e4a2e93327718cca3b9f5fc9c3949adabd723bd4313 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4746,6 +4766,7 @@ Output.13 = ba6649f527ef2d09cacf926d81abd456d4b43800dbf77de69bb9e2229cb6e3ac29c7 Entropy.14 = 62efa359ebd31d3c499353a5ab5f3b70a34c5f39c508231eae5f3ee20e17834b88fb804a32a268a1 Output.14 = 20dbd757317220a9a5b2394b495efe5e12cc7b759c877bfeed6425cd64146ee90c455c50b2243972b43015f69a015f1a4953e84a089d38171f9a6fd47b8d4870 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4811,6 +4832,7 @@ AdditionalInputA.14 = 612b0fa86e20fcfaafb14424d1ea3092c9be131efaddff1bd9bf0c9f53 AdditionalInputB.14 = afc244f8c93dd4578bd193226d7ed321f96dfeafe8b491684e53a0fa7d5cfb95dc3cb7739df80279 Output.14 = 64806feb8e212b2b5def3375d83075a0cccecf2a8f0fd38a8ff4700a3152d2044b65e555f5a6171b10d72b6b6139ecd29309dd09e132ae88fa9a6adb500a03db +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4861,6 +4883,7 @@ Entropy.14 = a59c31d7354eec799ecaba8193466aaa928025b162ff442ad2a4e0f9b65409f105d PersonalisationString.14 = 7b56fc016f55fe0ba21f9cc53b962e215e4ecd3dff487af67b275a19cde4afa74724a747358fd1fb Output.14 = aacfaf0360c415de87b92d74381be991f4a41bdd61175bccdd7c8dd19cd3f7076b485e95b1e9ae60ffb9b778f6470e5fe3a54092c6db3b909a4d9e5a8cb96ef5 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4941,6 +4964,7 @@ AdditionalInputA.14 = 6cff7528b843b2efb40336bdcaa9629be2720bfa509a330430c36d5935 AdditionalInputB.14 = e0843ca3385ed55f56d51343dd718dbd1a3705d7b8a3a5cb7b955c9070ef1faf74382a9130a6803c Output.14 = 9052a75eb225ac7522cb141245e0592a334cdc8e194f5249a5843e6efb6398db1b8ae97a15829efa4685cb4f1435d022424cc7854d34743bb2d861866fff51c1 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -4976,6 +5000,7 @@ Output.13 = 2cb651524a6b094c93e8d1caf33bef269d267eaae0849c359b52d34640f14ad4a7fe Entropy.14 = 689f2f61670360472b24f8ad360fe08e249b59ec0cc4675b08ac0793dae6956db8f63108574ef0c2 Output.14 = 0897856129a42d785b60d770836a68198bc76e29840abb0802ba9d471acf8b8bff3f02e1a1c34015ad51ce85969b12ea65236bc12d349c03f2031fde19cb22c2 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -5041,6 +5066,7 @@ AdditionalInputA.14 = a0c8fb5bc632cec6f7f7a385587f27ee3ef3dfeb5aa13d978049c3d4a8 AdditionalInputB.14 = d2c1ec49b1b0f810ae9a71fe5d93ffa4004e05cf8ffb1e1eacc146c37b3af5258b4e46222cf33914 Output.14 = f3ef4c192e85dccd2df5b1c5f791daca65363d5f79bd490b7d9232b19c6059aaebc494dea3615295f407aec1af3b867a6d94abdcc41f68d2d9afbee19647f748 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -5091,6 +5117,7 @@ Entropy.14 = 2d0c45bdccac3a972fe401601379d5e5f6173edea823d53186829f343c0d1c843a6 PersonalisationString.14 = 9345dc1ee7c428a961f2b787e6f9487f938062afd5fe3b3ceb04ba8445b1118a8e2e30b3f0bcc299 Output.14 = 3d6f9140fdb46cc1a04ae987dda91a18a7eb59240c6b4292f64c8445f27f1f72a2d80e8463da01409cbf28416986ed8a85e8b9c4caa4541688aede1b6905b384 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -5171,6 +5198,7 @@ AdditionalInputA.14 = 28cb3cecec5705c020d8a3edb8079e004050d480efee70faec7e1b00e2 AdditionalInputB.14 = bf2d138b18cd6f6c698901db8b605b598b0c3ec9fb0b14f9b586b791ab6976717fcdda68e42e083c Output.14 = febe358e4daf7e1938d8c0756ae39531b1bc497e603f91c7aa2203327604144eb442ad2efee1fe9b1bbcf33a5eafa94c3c04d583631b91fe550daf227d5cc05d +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -5206,6 +5234,7 @@ Output.13 = 0ad3c8e5ad0cd1f3308f882f9aa0aa5f290d93b4a2045ceb867991f2640c5276156b Entropy.14 = 1f5f78458959b3cabd57a556a8e70c364bab260ad5572fca41fc2bb64335fb888a31cdb37deef5d1 Output.14 = 0c4436f75415d0eec411f5ba0d96fe333161c2d6faa30f6d806dc457b4123b7b2b65cf7bd8f4e699c563ec0c6f45ee37c31b3c6c11c28927b77d53053b0057a7 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -5271,6 +5300,7 @@ AdditionalInputA.14 = 320c3202d710d62b04bed6cc1d45b6a3fa306522b94cb7037ae7ed6609 AdditionalInputB.14 = bf6b78f3552fab90333117fd2fcfac3af10c5e4dc0dedc581b0b15b6aa579e576fd8b10a099d05e1 Output.14 = e9690cf3a6a69e92e56b8f793c2a27d2ed3c321e61c2e59b99b8aebae74aeb9f810348529386037ff4f1a9f525aff494f8817b087d67817c9a7547e56109224a +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -5321,6 +5351,7 @@ Entropy.14 = cf9477ba033c5d2324dd97b69cfe59d66ae7f7327aa928ed1ad36c2d9d63be731ff PersonalisationString.14 = 215a3e638fa6a74d91592b07fa08f8d4983c6ad0820a908ba735ac5bcee68c3f670f6fcf4d05b25c Output.14 = acade190508f25724a3c7dd4d960bee088cb6152f31a537295a8ff4b85af94a0ff006be9ce2f541b8237f6a7fc62a4bb8e41ac6979a6f112b57158aa6eca347f +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -5401,6 +5432,7 @@ AdditionalInputA.14 = 8b981ec9ca88b1493e7ff3b90c02da6f478bfa573f5a0354941dfedb86 AdditionalInputB.14 = 829e75a58edd00d86269ef332e6744723b289f7df8f1c0bbf70222b542b9014e2d0cdd6aaec8c194 Output.14 = 8c4aa794af3d7d4d684006808c98c11d8146b11fd062c69cac019f1913c457b49d423b5ec683f19143eab372079a6df551fc686d9d6f9ce5f64ef619186f816b +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5436,6 +5468,7 @@ Output.13 = a0ea3af0cc95103ba3e89e5e4a6b792bfb19eef9580255ed76e71ed0e5325848497d Entropy.14 = b7f7e4e68356b2ac2c2c0075c0ef5ec6f5a6f225a18db00830261a95765771eba739a7cf8a1126c58994c43b2d28024a Output.14 = a15e8cc437a600a51dcfb778afa23d577d0e56b004f56eeb286e6c949d982bdb9353cbc63d33d7d397ceb4fea51a6df0b4d6d4cd32b9065bc4110d790c610e44 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5501,6 +5534,7 @@ AdditionalInputA.14 = 67cd37e14222e5966d243bb44aabb32b0750220f75546953981631b948 AdditionalInputB.14 = 1c0f67ce459099f3993bc8ee4a4550d3e7dec1a5225280ecdb00ac68e17c7cf40afc5e6794208e5742c0012e87d5711c Output.14 = 26167ff9820aa23ab61f7872e007dd25d58c7f82eacb9474280731a550c8b899e08074d910d576939f87e90018987e0bff48da03aaabaa9b7faeaddd65fdf5e2 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5551,6 +5585,7 @@ Entropy.14 = 4e37ee8649a86dd0bab8785a1e3acbd2c3a57ca346d0e31476490e49b588b928232 PersonalisationString.14 = 61334cdc8735332925221a6318987403a4c1c936c0a8066cbfbb1a84510bac2bb37ea52d6ba9f4e1a93269473f4566cb Output.14 = 8bf9c263c12a19c50525fb70cfe56980b26957e5c295f7546244ce6b7b1b90b24ce3cffc5536e96d973b192a77f878eb5e6987e1055475a0abd00312d7a65dd3 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5631,6 +5666,7 @@ AdditionalInputA.14 = 781c2441577ac05fc069f0f988e150d7e983bbb49810eeac8b5d98fc5d AdditionalInputB.14 = 7598eabea8e516eb2d111441e94a98bb37916f291e3107dd991e7798ed896dc99b1a405443f7c781b98adc8ba9750696 Output.14 = eae935bf9ea3174c0d7da0359c175cc6bbb91ecf9357e7748011fba02fd52205df0a87a44eb4ccb6015b266ed3bb9be4d0d403838bacd42757cd34216d71989f +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5666,6 +5702,7 @@ Output.13 = d39cb66ae64219a8de99b4f63daa8536defeaa53a055a66ec3de18c41673fc926b1a Entropy.14 = 100e176574bd55438477f0153ed04b6cf221bf6c1fcd7141aba10c80d71eb2e16bc8213aed689f44ef57807334dc3d12 Output.14 = b4315cc4470d4c50a15836f218b21c96668d32eafc1649cf6c92b96f0716aa54582a31a1c5f597b80f62102622369e422d98c34d1498cb9bc01d418a4d232074 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5731,6 +5768,7 @@ AdditionalInputA.14 = cd4cb3a8e0f1f8a67577d71339e6c4f40a291cdd22d5a19aafe0f7c99e AdditionalInputB.14 = 0203e75cce2d2e81ec441ba73b3129c6ae5067733bc0031614cbc8fc92d599523ad30da2ea253c06c48293befb14ab71 Output.14 = 927c1e64d9f3acfdd74e7afeb9ab2280f37ce9c1839f8cec8c32db7676fab057620144d34c8382bcb904e85af45d348e10bb2e5708268343595ffc08dd258c00 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5781,6 +5819,7 @@ Entropy.14 = 4e6768b663b1838fbd56c78b002c08c28121662238456ea93c4b286f4a1d6aa2a1f PersonalisationString.14 = 47c24038732c32baf7e1e71fb0b74b74ec055adb88f8cf111fc27598ea74872fde608266a8f49105282c2ca7093acea2 Output.14 = b1ce96d86e77a251c4fffe5de31e9199a19fa242b03b005cf0b6a23ea3a0c5b87edcbc77d0019f24d8c0594a4edba054b32d2c9e5e2f0893c424b11887b0be48 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5861,6 +5900,7 @@ AdditionalInputA.14 = 0e2ec484d8866adc065b4f11d3760b4d276e2cf9c066b226311e7c7806 AdditionalInputB.14 = 9fdfcb7460ce5b9913ffb9889696df7abe28aad40eba3b675d7508cca1c98faaa27dd5f52997dd6f251a68e86f966fb1 Output.14 = 66d6b1693a3ca1cb6169858390741bae3285e0c28604d064b57f3aa2ef9a569bec22884ccc5cd315d3f3847c680c3481bcae423cb105ea47956f62cf8c2c5d29 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5896,6 +5936,7 @@ Output.13 = 47b6dc1f9fc7ba68973e15b489e46b94b4ba58e23d6691a6e8311dd82a6187252e10 Entropy.14 = 80ffeccaddab35221cba00ff374728dab8f91f3e5498622704c050e3e13a2b0bdd2f913672e896a979974c52067e2a05 Output.14 = 0292bdaf725f469307e76e3ef5bed03470f6bdfc22e4d7f0661bd1b87696c9da201bbbdca6a22344ea88ffc7325370863b4cfb105740165eaed9c6e73b06a4e8 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -5961,6 +6002,7 @@ AdditionalInputA.14 = 8ca625e0daf65ecb70ccc63bbe88720ece7a415b12542c59db488bd056 AdditionalInputB.14 = e511e77b98df72d3e4c175b58b7182fa729a61649659ff117d9b4c514cf694fea2731b170d0babbf6b6bf8198be6d932 Output.14 = d9d3ac1480323439e9f8f09a54b3668684890fad51ad314c8e14bf0fdb429738b8955e3d2d928f2403f20caca2065795c0adaa30a5c4683a08d83074633be8f2 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -6011,6 +6053,7 @@ Entropy.14 = 409bc372b8738c80ac35721bbb8e806ddc93e816c8fab98d1d0f2a053f959601667 PersonalisationString.14 = 975da7439df9a5b76f8ae5201da35692fd46d277787f8a73b08201e6547ba72de26ba7725ad44a11f742e6c2b57c0e9f Output.14 = 01fe7c18b85ede519740ed4068af24b4baaaa7d727b05241af481ec843c20bfce41e4bb131cf03a504aecd5409d03f6b5b84d22f0e1042b66e5d99d4339742fd +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -6091,6 +6134,7 @@ AdditionalInputA.14 = b0bf3ae2cfe4d3fae5573781456b3725a59598d52ffdd081b412106481 AdditionalInputB.14 = b94a9134257079c16192066b6e3e50d63d58dec6632524114e6bce3415db5abfe0c89108cf2fd6478a97079f5190f1c5 Output.14 = ac7c1a00228f6a7a0620d00dca7dd38e53c71d31aace470703e4d8911b071b5ae517af60ff9f2aa570b18d35b2dcf8af0ee14ba646f2be35571c7cec44ec88d4 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -6126,6 +6170,7 @@ Output.13 = dbeb1de34b0e6f1c96cf4afd1e1230e434bcb1a5497f797871e16aa3f60f8dbcb4b3 Entropy.14 = c1fdb2167e6db331a3e796c83c8b10352650c20cdcc41b859f8b0059f2638bdceca6120928c3311b6b8d764a67b47192 Output.14 = b9ec753ca46bdc1058f5b77a9d1d9d7090d0b70f8b9995658b8d5abcb68462a09c59cf404bc4a625037b52ba10e336c2bbd049a507fdb95e32d09904a2482f97 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -6191,6 +6236,7 @@ AdditionalInputA.14 = c839973b79c3eea5db7107ca7cae1c012cdd59a50e58b7461ed7921178 AdditionalInputB.14 = 3cde5a2f6e19fb4a4493830016cd86afcb7a8db49a2abf6077ebb5314dd12a2d1fe9d3601c125c41c3e9af4603ee8f8b Output.14 = e61a4d439b4bb1ccdc810ef7a0019e5e88321ab6687f6564d5f70c0afb1633d50da63d6d1b1919b724b57ee926d63a80ac20f1ff06c4932456c70e8b64db43f8 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -6241,6 +6287,7 @@ Entropy.14 = 7ce9977cb80634f0503deee2afb8230c57408c83bf5bf41d2d62d4daa4c492fa60b PersonalisationString.14 = d862039cc2c297d63529a33f38a6e5660a06919a044c7e746ff238b65321d2a233a9a9c7b3534c932a8881ad38d31f65 Output.14 = f17b61f1c3caae331160b714504b9c058ac345f07a5a26034dbfd7fef5013b52cae3e2cd357095b623065ec5cb557001887b17f9b6f9476d5449ac7d81d5abd3 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -27303,6 +27350,7 @@ AdditionalInputA.14 = 639824768081b8f8d09b9b4eb51c0bd1ea5666067ade2628d45e727213 AdditionalInputB.14 = 7492ada1c96f7b2de329cd54651bde17b4fc69471280931180bbdecaa2889435 Output.14 = 5c37c829eee0a9acf2ec0af816c7974a09994e744c070f58d4fcc216491a35be0d32854cc4bf6956ea5c43370c02084dd30a66fda089f5c47b4975d59a01a022 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27353,6 +27401,7 @@ Entropy.14 = 8ecdbf1cba26eae45f70ccfec0e42d6139be57f131ff60898a3b63968acf28ac ReseedEntropy.14 = 8d860dcf67fbee47f33ed5273ff81956335d9152085f184f8427ad4234f95661 Output.14 = 8049f3fe2e62883f71cc43873b9775bf60a97c070370f9757c51488b050c00959d085ddd8f8e3702aa4cd6ff19b6c62685afb7792eb003c07bbcc9f4a026d138 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27448,6 +27497,7 @@ AdditionalInputA.14 = 9e0abd6fee611320de52bc48e56f5f17bf180e596d258031e3666066bc AdditionalInputB.14 = 5612694e4260dc91ba87ee97656f1436cec1f711536bdbf61064026673bb398b Output.14 = 02bb0c1e3abb2993383cc9cf2f32c148d785dde27df3a8dbd3ecc73ea4e884cd427061423e0736a95dd3202e6336cfac40311b8f08aaa88a90baa2f93999694b +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27513,6 +27563,7 @@ PersonalisationString.14 = 48882b0a263582f0c6bb8288ba894d7141e665aa0c084c7d99eaa ReseedEntropy.14 = 34cc10a3d71398efec3c5854ef82a77a0b6bfcaf841ad9a1d5c7bf05aeed9082 Output.14 = cac26b07204eea9a41e4289302d0da8f36ea200dacd2435f1bb1c1235cb362497eeb87aea2889aa1093d13d2cee25eb11e28229c39acdf894122425b5948cae2 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27623,6 +27674,7 @@ AdditionalInputA.14 = 1550ac6da1742834c705b4dad61c37fc33e7d786f76b553ab324bf543f AdditionalInputB.14 = 77ef7c3f819de78c243351a71bbb460936064738fcb75acfc214c884ff172311 Output.14 = 1030bfc7cc645d6e2d6b2a3f2e97979ab999d70252c15504d71d02c5842c34cf63b94c512e162726acfb1492ccb525ea56e4ca1b54daaac2284e558cb4936931 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27673,6 +27725,7 @@ Entropy.14 = ac5668ac054f732d2bcd88561642c5a7ca98c68e341cf0cf18873fea93ef33fe ReseedEntropy.14 = 4a4d088beb9843e4622cdb0c5a6851587f2b472dc5d734211409bacec7b2ac06 Output.14 = b2013a363f3ee01ab8573f3e3eed32285108c3ed3bf231c066176ed901e4d6ffaaf0cfd12d63d7c19f6c460baf434a1d6a552c62274bcb7469f7009c0beab972 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27768,6 +27821,7 @@ AdditionalInputA.14 = cc92f09a3b12f29d9e73253c261e828196fa540a9024632665c6c25a41 AdditionalInputB.14 = 53113703a3362b3eefb0c12587fa25a620e09e0cb63acb3f7b74471618cc0d05 Output.14 = eef4850d91b63508bdf3257c4b66c8c022a6869cc8d9473e5f579d103c67225c04e3994f14c31ff0e328c1adddc8d8f6b1f2e70409325a353eec19c420352b7c +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27833,6 +27887,7 @@ PersonalisationString.14 = a48f64c672f37649b12630157e15b9364ee7548984d94171b2a29 ReseedEntropy.14 = c4933f8a2af99389732cbd0120b697b9ad99e4821f4610b66c18d9da0e28bd00 Output.14 = 77dc9c1b636acd5b76a3453b168479ce947f4fc1401ccad4dc61d4630370ce21d29017244cee50644e3654e702b623e20ff49861890781a6bdb68e5cf3a7216b +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27943,6 +27998,7 @@ AdditionalInputA.14 = 2537ee73b566f7febc51963ea96691994fdb150d42db58204f95be45b4 AdditionalInputB.14 = 2f4dd1698f26af2a921d4f4aceda1c15ac71fff62ff7bb5ea6a993a29a8dc199 Output.14 = f1b46b0276bbd75eec0792e9998ce83022c8ff2f00ee9947760c6b2bed3f6a19bff58a0a92093a57b5ac949cc4028fe31e2a6262125994e6e30dbb4b7faa6d4a +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -27993,6 +28049,7 @@ Entropy.14 = d083e222d8159740044707c76bd9ec4436202ac778f63646e5b1e88f21ddc13f ReseedEntropy.14 = b7b714550798c888a5026b0b7801c0923ae60a2858cabb6d6972d66115f40eda Output.14 = 227a88583bb137f082967af04c27cb464a6332720b759b435d4a7e26349f56f4bb447695c06295e838a6c86fc3867006217c94bb5cc99b3c44bfe541fc77503c +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -28088,6 +28145,7 @@ AdditionalInputA.14 = ee0d3e9c178d53f9957ec0877ac719694197e8bdffedf8fe59c57a0cf6 AdditionalInputB.14 = 2545d30f8b974a21fa54146a14a566bc0156a015bdde60f3f2b9e186f6181f5d Output.14 = 7cd2003034f235e209cb0d73ab442234016a04c830752721998146c2f6f27d92300b47fa3ee72b46378092feb175583894b6f7004362f724ef145fe03c941d42 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -28153,6 +28211,7 @@ PersonalisationString.14 = 41b9b8e2d9a7945ffcf2631bf7d668648993c0f4859ea22de4279 ReseedEntropy.14 = cecd9d0ac5cb7ea4cda4566b873bcefc2db068ee41774a6861a21bc69cbe1814 Output.14 = 9d7209b625d5df31a949fbf15bf6e4515e42e6eb03909dd6d7ff4e001a8408c704901ca2b2121c079e36c28aed7a786aa356b6f3c75b87d4c78a2d06371de356 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -28263,6 +28322,7 @@ AdditionalInputA.14 = adc0707f3a06e767ea80f0882ebc015b79f0228547d22eb5a635b244a7 AdditionalInputB.14 = 8372a1277f0eb84cadd53df4a6cc619cfca029f84d9bea48beca8cc8060528cc Output.14 = 86cde22dae3a1af947d76cd15e4df0c83a11769d34610d1991945350acd4f0aaef9ef70b5bbd57fab74fac6be8cbc028b9bab63aa5de62d9f1f95d949e9d093e +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -28313,6 +28373,7 @@ Entropy.14 = e3d8fcb8c049e442d2bd07104c46f0602a1f60f87bdc02dbecdcfcf4006b5b0a ReseedEntropy.14 = e25327867ff27456eff9f4ae4375c7a85788b400dcae03ae8c892472c8a05221 Output.14 = 754063c679269931fdab8f90deaa967969f20b1805d93fe5b1928512cd2fe98984974b0bb1d7494d81f53e073f1a3a9378ea27307a154dc8a1fb1d3e17998f85 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -28408,6 +28469,7 @@ AdditionalInputA.14 = ff296cd83f439529d436254c490013f26fac4ab407e158a06b3c9d4e9e AdditionalInputB.14 = 63dee758f80f00738dee68e5f8a361cbbb371bcfa1b67ffb073c45e3c84b85fb Output.14 = 295446b08f879c3e46f0c57dac85767d94805fcdf7beb1eee75d40f643254691adef0e8300cf27deb90a72805cce91a4433d263ecacee0583b222b81c0bbe401 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -28473,6 +28535,7 @@ PersonalisationString.14 = 345b74cf00947dc1eedbbacd5e4030d5639f5e3c0b9fb986fdc0c ReseedEntropy.14 = 3150b6ab1fb005ceb8323c6982fc3af3092077241dcf4993fe91696bd5b8b747 Output.14 = bff83f45e0a4223489b08409497471427e7b82f834082137497bc552127446a8a3f52a730914650cd753098162f7d253bbd625983430d1f16fcdb0f78a1348a8 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 0 @@ -28583,6 +28646,7 @@ AdditionalInputA.14 = b643013474a37b208a6f6c44cc56b1caea69e1289d8897d53f40423d9a AdditionalInputB.14 = b1e07a0f9740c49335ab5244e3b7aa567c7234e01253fa1c31372ac43b1d6519 Output.14 = 6e5fb213d4bef40b3f274f956960a1e0d28e5399bfcf2709fe98de2b54ff26766835b6ed538b887cc617529d057f6005db0227dae7627728504cb8cf3530eb2e +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -28633,6 +28697,7 @@ Entropy.14 = ac8e24b8704e2011076ff9175fa1c12d9beeed66c9a975037ef6f1f519efa2230ca ReseedEntropy.14 = cbe05b235ab45735f0fa0ed945ec38ec3801f2caed0bd8f96dfb34cc75ef1a6a4122f5a8305f915e Output.14 = 91c49803af71477a06a6a493b75aa36817aa15b58afe7598750b2fe4d663f05ecf0b8c1b5737cd611e2d56ce95a029bc4fbc307f5478f0b796b259e01a48920b +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -28728,6 +28793,7 @@ AdditionalInputA.14 = a491fa45d161efa71ccdb405d6ef3153700b28966582e1052cea992218 AdditionalInputB.14 = 4a0cd52d005056df60803fb353728f3b3fd27964e5c96965ac472ff8bb4dedc4dd7d1ca04b124f0a Output.14 = 0f78e45be38a6a46c2914449beb9df52394067b720f390225f930c3313916f00293c7f7f173cd89d2c30c72bc07482f066708bda7a29af420490821c98c995f4 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -28793,6 +28859,7 @@ PersonalisationString.14 = a35f706fe78dab179bdb83495408764805175744bc020388a8a60 ReseedEntropy.14 = 4d632ef30482e6d5949cf52407d42caea7cd745e70d76d3449852a7ddb3f92e19840cd0217e1112f Output.14 = 3340cd5e74c52918b391156702851b25327072f075e16b8c9378972b081b2ca8cfa7665b7052cc44f480f0c188342357cc6c8cb616a0dadefc4e1ed40ba42b0a +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -28903,6 +28970,7 @@ AdditionalInputA.14 = 5f7205d87d0a9868234eeb8c4ae42cd47c03983b77dfaa84637b4080df AdditionalInputB.14 = fb6d486fd7586036003ffce8865e479498fe530f9ae29e01f98d4a2f7b665b6a9329450b0fb6ffb1 Output.14 = 0d3d8c9ff86fb56bf362787f474f838066fa7483a958c23f752be6e21cb42fee11d8dc53396508f9fd5122d04e41d0e0c949d50c46d51d0ac824b6f46b5df088 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -28953,6 +29021,7 @@ Entropy.14 = 0e681f881afa243f5de75a046205f733a32a1bb39e2abd057c07d8d5e81589d537e ReseedEntropy.14 = cb16a4907b39f647eec2b388704d6a2b89836cdd8d1c0c7ff27cddbbb0d01e306dbd01ec58334700 Output.14 = e48aab2c01335ba4f6d377c3c993932d4fe2ef60254eff315491b81acd1c22b3a33c59b8b78c479b7cd4fdd31f7d15864a48ac706e32174de36f9239aba4b6ad +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29048,6 +29117,7 @@ AdditionalInputA.14 = 37ab678301ab45deca791b4c5b1a792c5422f2e3be57bcf77d92468e25 AdditionalInputB.14 = cb7a6611c7fd8ffb884ab41766bf4a57878f187dbb09d7b0e77db4ed2ccfbcf3c640a9348dec4e1f Output.14 = b194fd786cfab66885cfe7b03daf642dc60efd7399f6c48d3df50337b40c40349b94ca509053451c34d6b838ce1905b5cddbcf5df1be2a9783404bd0b72b523d +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29113,6 +29183,7 @@ PersonalisationString.14 = 003b5e534bb565f4e1eacb22f2a2a65093dd0c782a27805f0c4c4 ReseedEntropy.14 = f2c16713da96ef435d96c63fbbc57d49c44d99c679c1af53a12cadea98d31981a7d06991efeec73f Output.14 = 67c409157d60f8703da237c4c8b4f124298bc95f68cd5510304c2167145fb7c4beeadbc6d7ff9b261b420e93cf9fb135d9946d5f4c4829557e7dcd713143115b +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29223,6 +29294,7 @@ AdditionalInputA.14 = 6f6d6ab0d0c02ecfbaa3ba6d8f38a8acb08699d08f3035ce7fd03343b7 AdditionalInputB.14 = fba0d6f6ca8f1a587782c5319766209059a23cb3e7476b2d060ad06f2db9e09728cdbe0f8a86c14c Output.14 = 9e88544b8486d3445c0bf47d0f55bb8d3f2abf5d5b2816df7abcf3f419dc37ca332bc00fb8c40152750b4c46054e8a281190f6e3007b844c63f6cbd1dd9acb01 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29273,6 +29345,7 @@ Entropy.14 = 8f5235da708cb15781db85ddc141eacc654d93f8c211ae718df22ed7bae7ba5f2d5 ReseedEntropy.14 = e6cf01b0cf9931ded0ae50bd0e1092cf79221397f2850d31390db33ae05072ad0e67cde6f3c438ba Output.14 = 7a00675e1a9b524dadc1b356b22c46c6747147ed736639739bbf761ed9b917670238ec001387b7cf3c91a58a81ec09c1487313058b6c26ce61d5785269a1d8e3 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29368,6 +29441,7 @@ AdditionalInputA.14 = 18a09894ed824809e66ee447f9413505035c8e85db5b9c6e597bf6a2e3 AdditionalInputB.14 = 75ec329e54639306dc853b73498dbc002abceadb355e12ae69fea16cc3ae892272544990d2938be9 Output.14 = 4c08126a7fe978f25982672ee2044a9dfe31919a2003853a74d9132b46a2278547af5980d037401275ff86528bff41fa80180e823bb88cda6029e06d2b009e81 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29433,6 +29507,7 @@ PersonalisationString.14 = d811d476960f2d5032cc3fb7002be155c6314e03ae7788dc886d0 ReseedEntropy.14 = 8fad4aec11507a394be8bf8cf24c4f2442c45948b5ddf28ebe33f9643ae5d21337ec8dedc9b23e1a Output.14 = 6d353a66b4cd16ffc5469b1c16951ba00b075db4f1282df1cba7267b9e191e21f604dda9eb48921f927f1d7b4548d5bcc580829c422ef0d5b2127d5eff4b020c +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29543,6 +29618,7 @@ AdditionalInputA.14 = eb4fa0ae2bd5ff9ab19545d30350fab09719db12f428ccc3fea36da4a0 AdditionalInputB.14 = f1d0853fc6fecca6730079b5e64840bdcbc2ccf4a9e20aa08e8ee2e48c785838b154c66845e2423b Output.14 = a29949eb92716b0682cd27f62ca00cfbad717fc976c55dddd854ded44a53ea2cd0dc0a97db8b6011d583f8fcb522b7f8c3d2fdd68ebdc083e23d5f5737dfb572 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29593,6 +29669,7 @@ Entropy.14 = 963fe575c96b319a3418cc7548484ab827df1f7ba56b0da8131fd19f7712add1d29 ReseedEntropy.14 = e1470ee367e55bd8dd82dea6f7fbd905b98d596306807f8aae529807b36aa0655bd260e1e2bab75c Output.14 = a1e6286529fab40e3db9b57741bf6e5b4904590d05569a7d571baf77842065be742e2c26c14e8599e46a520fa39b81ebe32dd857556d9f55e4bd37c1952afc0d +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29688,6 +29765,7 @@ AdditionalInputA.14 = bf76973791b52d9387e2a36f3ab3620bb983dcd2399fef3cc6bf4cf86c AdditionalInputB.14 = 2089acf7aca43a77d8459d4f384919575ed88c7c4759b9dd7033a132a85c2ec6c71025c166083bc7 Output.14 = 81309a10ac3f02d3fee049a5ddb9f02f64dff3d6b75259d561921a8349b30054059b2af81c6f7d50189a0bb6d360da06bcbdc944997d6f8b051f23998c8c36ae +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29753,6 +29831,7 @@ PersonalisationString.14 = a477a42a221cd2cbcf790ca70fb6a5f18a91c297617561acd1bc5 ReseedEntropy.14 = 108f6f37621ace418e2155f70dda4c2b5d6aafa9269f6aa98a5455e3a1d188e64ec022c454c68620 Output.14 = 05e4896494b02861a51357463f705e812a14f57eb8630cf1fb025c42ec9dd54de3f5fa1b38d1f3d890aad74d5ad1683d0b5981da4d3a939d05fd5435b1d50f38 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 0 @@ -29863,6 +29942,7 @@ AdditionalInputA.14 = 6aec5f8c3dc54924104e04635ab80b1f782869bc5c1557f7d89daa1e1b AdditionalInputB.14 = 668d732a98f7ae8cdc9235d63e705955c09600a490021a19a34c1befba8cb613ee7d8e4c5774aba4 Output.14 = 1dfb0a6bf411580aa55044f26c598d2620965fc94a769001f10b1909228616146bc9d02f749d094786805e3db859da9e6a572833af5cefdb147873ec6023b028 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -29913,6 +29993,7 @@ Entropy.14 = 1accff5a19861164c5d2cf542cf41a789f143c7956518ae158d4449ff0c257a0096 ReseedEntropy.14 = f2fa58209759d84bf38a1656bae655669767a902ade22a830df56b32ef9e1c992335eb4cb27eeb142bfd21b5d31451de Output.14 = f214b4055d182cb258d9e9b61251bebc9bf090db662c4e36023cc156964fbbe1cedf691cd0c3d7db4262fb65a5d34b942f909b0f31fc18009766413523dcaf40 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30008,6 +30089,7 @@ AdditionalInputA.14 = e33d181f3159fb0874eff5ef8ddd2b51a60b13ccf046f7e637ed27bed8 AdditionalInputB.14 = 3ecf6233820e6cceddac7b024c490c5ee14c73d5b598c92cda30940471b6ed450019120689aaf157fd87b71b13afea25 Output.14 = 9d793dd96b870dfa0267623bd1c2d8bd3e2c63e9f211340f630fea01358011394154145a10659c4d98274a525c48a90da0126a99b85ed5b4b903195f0dddc762 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30073,6 +30155,7 @@ PersonalisationString.14 = 8c40c5317f29b64da7f4025cda90ae3e99ba1ed350482048f8411 ReseedEntropy.14 = cb7933c3c803644d4ab7c35b941319bebf6784f98c04754c69359e10c9693b57ae12e38b08ca8a9f0f15142c4476f0bc Output.14 = e95d375c7b3354190721d598e8fde7aef16fb2a9dc963ed76eef6a12abe2001622725a8e1545c73c9a85995e6b07806e2ac39b179b595bcfd96b2189b5d10497 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30183,6 +30266,7 @@ AdditionalInputA.14 = 588eb722d4066ce1e9148d2e7a6d43d1d8b4886bd97f36f24599dcdedb AdditionalInputB.14 = 1b4e904a6b861201028506075d7d7fecb81158ea3749421d4d4710ba0fcb157b5019dbca199c8302d34745cb0c2330b1 Output.14 = d155941b54ab48dc1866641c034b117d6dd8a7d068d29201105d845315dbc747afd8fb1f9ba5c976c75ff8c7052aff7b342c1489bc0c9f8a7d898b88ed0d5746 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30233,6 +30317,7 @@ Entropy.14 = 68e91e73623fa6a3ce22f424e9db971459dfbe06601ccff96f1726fa18e61d5cdc1 ReseedEntropy.14 = 249b56dcdc4c5c8eaf796c8685a740fd4ea2455c135e0d7b8e50532fd87c95b781c8f3775c213c2714eecef140125b78 Output.14 = a15d3d61408ddea3b9753c854c693ca1a91cf49d172160bf15f512f345bb1bda9aa7bc4fcce177fdfebb3fea4cc6404c6024527ea662669a5eb78753822bfdd3 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30328,6 +30413,7 @@ AdditionalInputA.14 = ed3f47e59a12b36a42616b338c7a77a18e333d38abb9da4e36914b69f3 AdditionalInputB.14 = 6e39b249f1b8111ff12fa24f9f2320df2dc8752e1541f556b5cedfff409b6a858490c27e052a63504c7131b438f44356 Output.14 = 650bee69393d5d7793c8a5a40cae79bd470d15fdacab7b51b251f51dc5d3e383d28d808c7f9e018c71eccc80371a9e0267ba4053ec0e4c071d110942c43149c0 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30393,6 +30479,7 @@ PersonalisationString.14 = 531b64be5d25937f30bed886f2021855db1b63777febe6695eb4f ReseedEntropy.14 = 350112071b8315afa26fa3d9be6b6dec59ba7fed2387556cdec43ab8def92050d2f0fd34ef0c837c022c337f227b2169 Output.14 = 47ad3d7ef4e7bc4696d039b6e424669200b5f6c687f813c270483793518adf6698aa40a781208878017bf77afeb2f98794d21578623888eb98135ef0e5121c57 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30503,6 +30590,7 @@ AdditionalInputA.14 = 02a4bfd4a825e4d811770127c6f5a568deff4d7989300a0bd23220a586 AdditionalInputB.14 = f9775f8fb1b767c4639e2c3fe9f0820e03e28780641ecbf832451baea5e1ef83cf9e078cc325b1fc7a8a14bf07cc4ff5 Output.14 = ba473979f23358b95ff49610a7b91936b7d1da44bf8891cc19ac6ceb9f0241a8c3771a2efb403275bf599aad30b9e4604e90729241763801387ab239ae543625 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30553,6 +30641,7 @@ Entropy.14 = e23a7f95c3cf3fddddec66cb16e1fbc38495ebe98b3e14d8f351e58bc457cd38b79 ReseedEntropy.14 = 36410abe456d7a51948098897ec205f75f22ee09cfcc94ca88fbaff8d159fc779a8e420d11fc1ac09518237bfdb74462 Output.14 = 3c14a63a9c74dd02051c0147637401649a68452c28af90e9628f1ac87df1d27671397ba34f493997ef634284b74b3b28b2e7d4171eb025e470f39dfd12636a5f +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30648,6 +30737,7 @@ AdditionalInputA.14 = aff406d3d514ec118c9a8f470db34922b8bb262f78c1ee6ecbc647eaa2 AdditionalInputB.14 = 50d8e7887df0785c331a381b6f11057ed720abaece80b7f8358386fabf5da24a912b8f1563301fbcd7ad240c03a5e444 Output.14 = be0045c0bee70daf5a57e5b449fde2e9320a0e0d429950ec3b8ec14ca2acdd7ca2a365bebf11f45f356c34f7e52a8c39ac2e141815134bab3b79ce3dc1d2a44f +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30713,6 +30803,7 @@ PersonalisationString.14 = cfbbe01cda290c89b2841f37952cfc1d9a4222fb425e9453de307 ReseedEntropy.14 = dc9c22b1006462af08615eca5998ea81a81411be226a241c38d480e7ae0ab5bb34721f0ab9226633d655675ffd953420 Output.14 = e544668dbca5b35bb59ab04945649cead8d822a1d8ce125e3ae5db8b23e3bcc05bf6921ce95b85766b92c13c59ae83d908471e03e020fdeb59e5cea817a48802 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30823,6 +30914,7 @@ AdditionalInputA.14 = bd203cdd94307bab1a53734a3a451f0b038614892186b26877b2c1c849 AdditionalInputB.14 = 631cf0317b713d07ce74f7b05ff4e7a158c769993d357325f8e9d16b25076bc9b0febbbd66bf23fbc9c27286dc1663e7 Output.14 = 401176185d33ef08d0b65a5b853d57583250dd2efaf44ca0f987b45f89eafeb52d2f4346bf9b9d0b7dd4f7126e7d89dd32f53b737cef79ab5dd0794fb8a4c89d +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30873,6 +30965,7 @@ Entropy.14 = 91fa80b727040295b850119e9fb7e4cce4551ae234f29616af15572557d1555de04 ReseedEntropy.14 = 9937f776ddae1dd4a6ed76cc1795d450e14d1e462c30a9e1a85334b3ca148451b94e00055b3ed227f0a2fc247db4db6d Output.14 = e659a7de7a1b1b15a56170a1d6334dec91b6fffc47fb7ae1f2b3af03cbc25f7bec0cb6afadb76af9d36216825ee0e13aa3915bc515325c27270858654175a81d +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -30968,6 +31061,7 @@ AdditionalInputA.14 = 54dd28543c859fd4dc1e4f0a44ec9aa2b758d51379c0a9c75805356793 AdditionalInputB.14 = 3803a58e41fb766847b9f568ecd7f1993091c4689fcf70f754d345ec7a3f45d1fecbfcc52cd60b47b5a486acb155e213 Output.14 = 3cfb2eda22c4f01893b4760b785d330cb771938ed6f2f929030fe625780fb91fc2f9952409b99f011cb5e7e0b4a7d461be80e94e91111ace0604a7a41719f3b3 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -31033,6 +31127,7 @@ PersonalisationString.14 = e7a492e06f2079eb6428f4d39fb18aa0ece5d1edc5f2e1403737b ReseedEntropy.14 = 17837fdc7d5600fa487fa07331c4db6e3d65d522537aae0715a5936f5cb81953965fdda82e5f2b0a1f20dc8beb76beca Output.14 = 2cf0d9cfb60234b23086dc1649e6fa99c4104de9853d19508105535c960468777a936543f6b31ed0d3c52d135671a23d3ea08fb7f29c9dcb3f151163587c39db +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 0 @@ -52485,6 +52580,7 @@ AdditionalInputB.14 = 373b7d3c6e3c07907a45e6292da02991c252b4f368ac894e44fe2741d6 EntropyPredictionResistanceB.14 = 72901d3c6324cb6eea7e62879721c4ab437fcac453cc43f179388851b6d160f3 Output.14 = effddd2d7c39df20550e03ad21ccba6f6775a92726af567a80bcc91523f3646ec156cbaabd4fdb13c63105f2b771f94fbdec6a2670f8fb263cdec3ac1b775774 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -52550,6 +52646,7 @@ EntropyPredictionResistanceA.14 = 43d53e48de3c247857132224a448147672dec7cffe1016 EntropyPredictionResistanceB.14 = de28c574f0d771f2211acb54b43a60ef79973081f06da6819219612c67bd94b7 Output.14 = 3e6e82f2edb3fcd74559b46d319b09cfc3441c06bac7a1260647ed7f9327485d553873d8b58c08410574161e0ff9d5bb2ed4cfea533bdbcd47ec627ac405d3f6 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -52645,6 +52742,7 @@ AdditionalInputB.14 = f298b8789db7c5b8e0354764d0b30013453c3c5c77bfec04264203d767 EntropyPredictionResistanceB.14 = 9a4dfac99270a67b45256a4da4ac0df15693a4a19fb68d08c0a2061a9e190749 Output.14 = a7746e689fbe9eeed34b0ba524851742a5fefe1ff5ab84c6b9a118da64a8ad8fc9ff601ccbe6a5b7e90c5da8cdc8d9fba741d22a0aa1d8ce4fb9cd6148eb06da +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -52725,6 +52823,7 @@ EntropyPredictionResistanceA.14 = 9dfd31e3adc822b675c0a9c8702df12de4c3354ccdb538 EntropyPredictionResistanceB.14 = 2a1b1519d22d40ef4ec23c6d97dc148cfe171fb5f8b1c305ec6d8e83a1ef9064 Output.14 = ac054570b081cf53b39b0a2faa21ee9b554c05ff9055843ac0eb9031d1de324701ad4cf2875623e0bf4184de4aea20070be1cb586880ac87fbb7e414b4b128d0 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -52835,6 +52934,7 @@ AdditionalInputB.14 = 6fd46ca18d10326f5734d0160163bc42d3daa55e3c74a2e0fc7380fd84 EntropyPredictionResistanceB.14 = 16f3bd62634368535da170a7f117bbf8b896ba1bfac5ab682247b1b55452e844 Output.14 = f84c05b144b114fbd2f80a21862a44f3641fbe980957e3fab736976db37b8bca823d7f848f32f4aca60268c020a2e85a5ee0f31fb746f0dff066b83d32563df9 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -52900,6 +53000,7 @@ EntropyPredictionResistanceA.14 = 8090391380ed44d3423fdf8d47891a2027110da4c2334e EntropyPredictionResistanceB.14 = 8288a190ae9118c57b033808bb3f895d4dfbf2dc7ce9b9016e339548fee10a6f Output.14 = 73d122b8854f2610a833a78af28baf4a2dae48dd1ed685e4f98947092e3aaa56a65fdc9acd8a875c16b2a91c757ff7cd6ee777292fbcb0220795c9519cf44052 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -52995,6 +53096,7 @@ AdditionalInputB.14 = 440e9b55a68dd27df4ef8d0dfeb8c2156c2250cc1ab574432c2b62baca EntropyPredictionResistanceB.14 = 3cd2f704ace560337fcbcc07d2b027c37380b35b26b26e40b9d62dd654e44193 Output.14 = e55b536cca2b2148af20e887ad6b1c6ab5c285fe5271e188c5fe5f7f037bab8d6d2502ab71d768d4f05b1bef7f27440ce8f64311ff7147dbb55719bf7371bbd4 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53075,6 +53177,7 @@ EntropyPredictionResistanceA.14 = d0caa71a0c2e2f218bdded7a08864addea822aaab598b5 EntropyPredictionResistanceB.14 = 31fcf2f4f7580ea3b79e738830d42a218935ac5c6583febabc14bb5463fe4609 Output.14 = ae6cbc3e108ba64b18244ac14eefb670caa16784e175ffc1f41126cdbe791e0e3de26d58123aae6843613b478b9ed94173fa27c7400bb071e0a9829b9a8fca19 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53185,6 +53288,7 @@ AdditionalInputB.14 = 55156a604966212f7cf20379b79cdfee41a9fe462c9f7e17e5a082c5dc EntropyPredictionResistanceB.14 = c64dc7f4e7fc14ada0905e271e0de491a7b8e4931d26823e572132329e00652a Output.14 = 7d96dfe0f6fe3eac2de3a3a8729d36afb1767aeae2ac3c79db0c523226cacac3cac6d5a87d4f152e8e7274069cc9f12bb7edb293f04e9bbd5a8f0ab142fc373b +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53250,6 +53354,7 @@ EntropyPredictionResistanceA.14 = 25aeb73bc04139a647b60a0e506db2109581f58b704f00 EntropyPredictionResistanceB.14 = a2e5839c59fc255576a2fd462c719895314a033823f11f419446d02702bf004f Output.14 = fb833a40a658217ad75391aa8311b3e872bbc2e1cb150da87cc6e3494423c5a992593b68f609d30387a0384f64079236a1038969d011bea6f8adb052c5b57eec +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53345,6 +53450,7 @@ AdditionalInputB.14 = 4e6c1d082917ac9eda7f032c61867736b5be7b3045555f6ef10c584875 EntropyPredictionResistanceB.14 = bcad225d779bd3653a616a8d667030c556117b2adb88e4a6a4e0d0561ae94f42 Output.14 = 14cf6fa5cfb8f9c74add5b2dca5e30395a1045ed1e1cf4e91ccbdf8ab80d1c0f1d93481651535e4089638b04fdf95f52aec1fff6565b21d8a2a32ea814952411 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53425,6 +53531,7 @@ EntropyPredictionResistanceA.14 = 24e9ce22a727e4540d7d85e056bf6448063d5f13dae559 EntropyPredictionResistanceB.14 = 9a5f15c36078cfa0c768868816d5bd0b1d33c492fa9554498b6625639a293dcc Output.14 = 54c02aa8e6ccc1f109a5f215f488fe9ca7c7ceb3d1b0d9e9256ac4f5d4195cc8c36f8d8ddff55ea10f86d0eb5bdb5b116339b9c0229eb7e96814012a2ed5eb0a +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53535,6 +53642,7 @@ AdditionalInputB.14 = 34e517ff4f40e3c0c699710134cdeed029baea8e142db0bac9c5aba6a0 EntropyPredictionResistanceB.14 = 09d8b16346fbf20ca073688ab3e917602686e07dff338142841410068e640296 Output.14 = c1d0095376ac846921d2bba5f4d50d231851311792c66d125d5701d6cc466e181c893dfc9999c21063f69f0cdb9850c3a34755926c67e3af75e801e7c21f3da9 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53600,6 +53708,7 @@ EntropyPredictionResistanceA.14 = c52074e8343f57c0f56c9aa4bc3a6bcc9dff30b21905ae EntropyPredictionResistanceB.14 = f09a47309a1ddfeb54eea6dfa7b15ab0e6f183e2478a3889de89091c2bac0c25 Output.14 = efd931fe77e202d2aba86f6407126a859c881abc86c8f8342deeabf527ed6dc679e5dfcdd212ddc3f2e779d043f058893d7b23c6b69334ba0132db6ce82a167c +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53695,6 +53804,7 @@ AdditionalInputB.14 = 0bf212302b4d20c6d2b799c9fd692b14b5672897fc45b416addaf55501 EntropyPredictionResistanceB.14 = d0b9c12bd6b178f89a238afb0fce43d45dfd2467b3a1cf9b1aa31960179f125c Output.14 = 7e5720126ce4ef83b785d9649915cf76ed6ef318422950b6540cef9a0ca90c40203b3a365b8a5c40d63475f7b37f5366b7f2ed6e18885e361ba89d46350028e4 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53775,6 +53885,7 @@ EntropyPredictionResistanceA.14 = 3695bd2e5b30b1d3957dd0a116bddba53a24dbe647dea6 EntropyPredictionResistanceB.14 = 4079d6610bbc715e62777ab699e3ac6b6c4d097aad4debf668a54d15744d9ec1 Output.14 = d0aaa51fb084825f8bf0476c703f1133829a93dee1f8061222f3502ff1bdfd550edfdc275f3aec8a8fc5f9e5f71246362fdbcc65a00e7cc52ff353cfa3b3759a +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-128-CTR PredictionResistance = 1 @@ -53885,6 +53996,7 @@ AdditionalInputB.14 = b44a499fdf9330170ebede64cf8fb19f4a8317596d80d8f9c9d1009322 EntropyPredictionResistanceB.14 = a4341ae5155601af7ccfd9bc573968f99ff82ae2605a462af7e6ed6fd5f2cab6 Output.14 = de6541dae09137dfe17fa3bc785c8f45d3d36cb621d76c53f9031b2853ee0657a1edba0f6f06dade6a5a62faec54cf69bbf15db2244909114b0486f75da3cf16 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -53950,6 +54062,7 @@ EntropyPredictionResistanceA.14 = ddcd35394681d6f0170aa6bd8932b602745f41117eecb8 EntropyPredictionResistanceB.14 = 09a5d5925616379b5221b347659afa11da4326b630b57f3b78db9812e667ed3fbad25fcce6307486 Output.14 = e04e5432f671015350f0cc912f5e83e969e00584c6178cc82394cf85ce3dee6ca87b6cb02e27a21e03f83c24c761f521830645fefd4474c634e1124a4d93da30 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54045,6 +54158,7 @@ AdditionalInputB.14 = cc7df42c7f93a63b8a8389c66a336519cf27cc6e61a06a67c33077c954 EntropyPredictionResistanceB.14 = 1c59550710b2efa9f009e44c0aa724ad3451da29323f60d68d025693510fc01670c282b38bff3249 Output.14 = de2abced63a11a9c7c034fae31d8fd57239a76a8d8382d9a507e5230c1b0c5bf063a99f00cd4428db196597427900f56ac2ff8d556d3af3d119a590b594c2e90 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54125,6 +54239,7 @@ EntropyPredictionResistanceA.14 = 756f29305af9f4d3ceca4399594d07636df0b2ecfaa064 EntropyPredictionResistanceB.14 = 1880252ad93c994dff31fb2a10fab8c265cf6f6a36f010fc35e4d858bbb783e3a682afc3fb98fe6d Output.14 = 2f7872a704eb276afad3efb131e67c4b9508fffdbb704e8c85c07e6132745941a8889ffc37baa637a1b7b7b0b84fbfdb8fbc00e7f1eff50baf2d062d8434bba2 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54235,6 +54350,7 @@ AdditionalInputB.14 = 3d91e9e7ca5683312545bdb4613dba83182b0c906f3a1d65a2610709e8 EntropyPredictionResistanceB.14 = c9255e2fabf84b9edd45737f5de13e5661acc03623a3f9268efcaf7f5562cf839bcceda229e06f11 Output.14 = 28ac3acb17dfdba1d5abb3e2515dc16b42bd207d2743c51b3a2e5edceb0021d964fadd50d499e2df1623c2832a9e552331e915395d65e95f3d523d40d1d8a15c +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54300,6 +54416,7 @@ EntropyPredictionResistanceA.14 = ea4ffce516fba5a28325206d639d1b3a0f7c61798947a5 EntropyPredictionResistanceB.14 = d7e649cdf563e960640b50927a92abcaa306d4e1315eadb0316bb65d7f9166577bab34bf012a6f9c Output.14 = e92c34e544c5342445228ae6740616889856eda4ce82fb7f1c15d1951953f5509ae754624ad9f159dd5e1908da3c97d2a66945b8a8746634dc70b7f31718c4ab +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54395,6 +54512,7 @@ AdditionalInputB.14 = 16d262848510e407c7680cfcd3fcc27b8647fcc0155426b3e7b54bc473 EntropyPredictionResistanceB.14 = f6d98f69302da7ad42b8e580a9d755e929fe39fb0436140388fc7160d94f6167c0e150566fe5310f Output.14 = 9c7766b3ebb27f65539f3dd6001ae45c85bba6d6c09e600f0b9cf5e02f30b0f8584e696c2fee0239d5e4d5b623700ca98c94e7ca82fbb8b4643549f29d2df244 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54475,6 +54593,7 @@ EntropyPredictionResistanceA.14 = 828357ad5c99f114394f578f56cd7e9a5da671636bce00 EntropyPredictionResistanceB.14 = 6f256e9f5f7a84ba4fd6eb19b6ae20b27c26660e51982bc4cf8e28a2dc43cdb723cc8a727c2ea91d Output.14 = c176910a6a7c96982841c0b603b423b2fa67c267b5388d858a4d8dcd69d6b67cb96816892162147e38cc602afa459fc5623da0862b74f1e8f569bf3b1024d881 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54585,6 +54704,7 @@ AdditionalInputB.14 = 205f0f79d140c6ffef742bf3cda512a3fb84af66d058e5a34752cfd0e4 EntropyPredictionResistanceB.14 = 1989becc20da39682e67b961dc4a2f10a73b037b21cf055f1f12e8f59f047200dab4907e5e8b96aa Output.14 = fa20e0054f9edef75b34aa4e76b16dd6d9d54de5e350c879e16541cb80a4e64c3f392a0108c792ec8fcec84721cd71ccae15de31f3eff57e09f024506857c3e9 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54650,6 +54770,7 @@ EntropyPredictionResistanceA.14 = fcab2000ecec66a23af1381d36e1df97a4341c329f375b EntropyPredictionResistanceB.14 = d75022692bbe5beeca5d81942443cf0dd78b770b7542cb8fd1be65e4908816ea43fa903a7a66fe0b Output.14 = d5f91235a90cafc96e39e2a1e636d9a2386c5214d8616941bb9f4c2fd375da49d33fabec2faca971d6520bab482e33f6f2752b2d054f9c3bb1f50d072978ea2f +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54745,6 +54866,7 @@ AdditionalInputB.14 = 1a72cab51be3633be268e4533fe4ad482e5178cb3b15c6d8090ae9e888 EntropyPredictionResistanceB.14 = 6587fd55057566c3fcdbd85aa2b693d885234144a6ac9000b8640c8530da8e2e72abfca6980d7119 Output.14 = a0496a05e5238f171f18870973c9e7b9b3fff44df1fc1ccfa398ef73aeb41829a39339fd032591abcce4cd9402297f7c2e38fd2486eaa8c20134fc0122af978f +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54825,6 +54947,7 @@ EntropyPredictionResistanceA.14 = b459eeb404a1480b64e7d572bced365bf822878085363d EntropyPredictionResistanceB.14 = a057871a394e93e58ba191c239e21858a3127a6b748a4505eda487dc6a5293304aad36d52da132b6 Output.14 = 96b24ef7b19370cb3ec40a4763de926977ecbe6af2fba201e983e7bbd71b23fa95bd315933ce2fb5a10f4a121cc56b125233f09ff920cc380df7ab5513403457 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -54935,6 +55058,7 @@ AdditionalInputB.14 = 02a318a1579714ddac239f968564fa2768d5099c237237ac15aba9bddc EntropyPredictionResistanceB.14 = 0d18ee1fdb9dc23c66aea587fa59cc9c65da7690a7a780bc64727fa3fb22602301911ed3f99fd712 Output.14 = 992397ec168448c4521560085f3956d2fc583bda1924b29fddd081dfcc056a0dcaaf3edd1a84158b6b7e5737d37535fbbd6258319b7458c5524cd0061a8850e8 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -55000,6 +55124,7 @@ EntropyPredictionResistanceA.14 = ad927a71c6390c5613a7c14780abe6d266b2d126aa49f2 EntropyPredictionResistanceB.14 = 152ec7c0d26eab6de29d3d2ef321281297bd2591be887318712ccdbbd3ecfc1c9250f99a226fc9b8 Output.14 = 0ad1101454cfe091f1456383eeb1e7a968328da150f1166b89e7c202daf5e42324314c43fd1da6de3feb9ffcf82cf217bbcdf5c96864c227246306f0c975c4c8 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -55095,6 +55220,7 @@ AdditionalInputB.14 = 3f5221732e417fe4234626d8b4fe5dce8d0974a7551c4e7b9eb827f32c EntropyPredictionResistanceB.14 = 1d81b5e14e9f995cf19771d54877e97b2d4f551c36033874fcf3a4814312d7064acc2556ea5e0fdc Output.14 = c6d9cb21922398c6a63e4d17f0f69f1d4c1b4998d73828d43ea1f69acad5b1d94800a6976c09a8b5befa2b0c82877874eaed15027f9f7dad3bffa005e49758a0 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -55175,6 +55301,7 @@ EntropyPredictionResistanceA.14 = 21db28b5cb9724d93c58f787b155f0131c39b5606e6a96 EntropyPredictionResistanceB.14 = 4aa587edcb940c3a9328a0ef2f195effc1cf027b549ff1ec5d5cac0e996196eacd16108498b27366 Output.14 = 69dc6c36459e005275e344886624ca61a42cba3387dcee79392ae96a311313dc7e33283605fb46aa1d881bccaec6336a61545dac52166cbf8174b8dca3ebfbc6 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-192-CTR PredictionResistance = 1 @@ -55285,6 +55412,7 @@ AdditionalInputB.14 = 3dc3ef9447ffddf64c3ca0569afcf8e5d491a9571b9a1fa251e0684d3a EntropyPredictionResistanceB.14 = 140636342e9ebb2bae8a87b5d8193a59b75b12318e7094975bed5ce2d23a58b4a021496e820a1b35 Output.14 = b72e486984d1273fa7865a2a43a830b625e394cccf169610ad2714b5b64ef6473f53e62aaffc85bfa2b155bf81830abfc528a80c17f2e325bb7ac9197e5a1099 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55350,6 +55478,7 @@ EntropyPredictionResistanceA.14 = 6f16ff94cb8ade7a928b9a59af32ea79944e6890a003b0 EntropyPredictionResistanceB.14 = c73fe23a8ba2bb780178342598252e9ce3de907c4fc1cd632b353cf959ff610f23a8a2b0424ad137aec7da42f8c9f2da Output.14 = 8f7261edf6d10824218ad0b10881e3c1251637bbb71d0f35280caec7de254e07147f33288b5c60794060b59e6f5cc2938e4c29de1e4d5d4d3bde3f27c3fab92d +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55445,6 +55574,7 @@ AdditionalInputB.14 = da29846d4d48e3eeac71ab07fae9b9dbb6c5d83cffb75c67be10bb15e6 EntropyPredictionResistanceB.14 = 0d9037cf745b3cf41628eb1538bb71b59116da1049ecd36d12d344c5a17e471c8c4e72cfdc7ca0538c81085952241d68 Output.14 = 7a7ed6e632630ffcf32f0373deb2c67c6dcb77f04f1991f89d5d25a3a8c390ac8ac373b66c5da990c3fe28cd93f3a4f8e5594cae25498ed73f5f001b83179b0c +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55525,6 +55655,7 @@ EntropyPredictionResistanceA.14 = 2b3877ed4d1b3174d36e784ad7b6b7991dd52979ca5b1c EntropyPredictionResistanceB.14 = 91d421c3eb04de94099a7467254bad70e236d5c27616f766e85b4de3965001db854e61a80bfec2eacb4ff93ecafb8b83 Output.14 = ed703d9273bb9462ac400ee8d587ea3c4d6c27aa014defcb6ca6fe885272bcb4b6ba0822f42941071bf635b41d997c631b680d91b23ee48351041dc274900821 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55635,6 +55766,7 @@ AdditionalInputB.14 = 4f23641093342d946d3a956c456dba18bd42de21cb2494f6310da7d20a EntropyPredictionResistanceB.14 = 843e7cac38b659a611dc4af4bd228ebc0cd9073ee98350d04da61f77db66c0c70872153d9fa2af4bc583ac2cf79d506e Output.14 = 6754a72f7fe23ea607ef0ae61a61eb3afc562c5227670572b7ff2dcecf3dcb4194829d29fcf9b100412aa0ee87611ab534896f80f47cff40b7f76e0ea46b3d41 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55700,6 +55832,7 @@ EntropyPredictionResistanceA.14 = b8ef0d478028f0c55dd13861281489e6c124870f0f28c8 EntropyPredictionResistanceB.14 = c12649a0f249c7f5ddb550eb527a0f720e5eaf04e6e3b96dc24881eba10ce466f67e3fe51a0342cb1a2192a555798169 Output.14 = d8c63ecb23f16ee925282b7744e8cc2c2c1deb56581cf27152118b5790cdbe682a34d91523bf0c7be4ff263aba2ffdda35e4d36a5122461b89b43069932b30a9 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55795,6 +55928,7 @@ AdditionalInputB.14 = e97f7fc9e287ae947d3e937d60ece684f0c8dd9e133cbd7265b2b3e073 EntropyPredictionResistanceB.14 = 94904fbdfaf6b1d8931c15a37277814dcacc6343d48b80a1c624f8aa3733e05a52bf1f1266e2b90da5d562d7ffcbc274 Output.14 = ef2fcb4a9113e062d6cd37f51a9944645c3cce0b06e2d11a2c778bdb559a2f627c8a0e7f419660f461456064c3508df1db945af6085abaf7719e868a912df8dd +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55875,6 +56009,7 @@ EntropyPredictionResistanceA.14 = c436b73aae532ffb950c6ed83753aa6df0571f11fd8e0a EntropyPredictionResistanceB.14 = d3ed7671eb3c2e0c115ec9d6d684964d39533d767413b63e0bf7c956b47205f8d5001a9650e7a1c7381f110c9ecfe92c Output.14 = f99b7d88ccfe1c84c9949c3548630ea2a9ec033543c693c5bf72a82f404c5eec5b2a09afb6c95f10b48fe4608092e7213285af83ba1304acfef846060a1cf860 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -55985,6 +56120,7 @@ AdditionalInputB.14 = 58a98d14625f59f7adf6a703b2e1ee21fb83f22f3694f7f06548c85804 EntropyPredictionResistanceB.14 = aec90f26f7c7853f3917de516f1ee0f85a0f3d0eb4967f6d2694552a93a25ca7fbdb4554de8acc0e60af0c5b0829cb9a Output.14 = 18d3f2396fa92b0b9e6bc7a5c0f9f8e10857c0063b4fdd8ee76d12e1205eb5e4fbe1b07ffc0ec5045eaaad608a558d1107f931c0290392166bed2d09849880a5 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -56050,6 +56186,7 @@ EntropyPredictionResistanceA.14 = 1e5191f18e3c049b3aa304604a42b13e87b61ab808a1f2 EntropyPredictionResistanceB.14 = a04435fab8cffaaef34f6738f2682adef4790e8e2655d5943bd5370009ede99a6da3c9ca4dc7105a1352f9bd295be419 Output.14 = 31b0234431f4ff22f0c1f5c220a5890c7efabc06974357a1ab8a79d1caa66b46b62f0b5a5b0d8010923dd86ced2f039effa2031619aafbb3d7dc9362ef04bdf3 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -56145,6 +56282,7 @@ AdditionalInputB.14 = b1e3c770adbc772d94edef6188d0f07ea1c25fb41dd20eefb552dead33 EntropyPredictionResistanceB.14 = ffd6fd3031397d33e382f40b6338e7e3640b9b35800d890581fad4784366a1533f38398f255dc316bde222850794e46a Output.14 = 826dc7b1c39fb4955f614fab27697ed5fa1ed8686c701ef5e03776a814bbcdf9afe49343cb53944241c30b201be6d181edd20d55fe0374a43d68205d8ef758ff +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -56225,6 +56363,7 @@ EntropyPredictionResistanceA.14 = 83acc7bc2f89de95c84a4450d509e7de3512ad839f832b EntropyPredictionResistanceB.14 = 95a26a2f946c03f51012bc6cda0797af89a8500394cc7f11866a861608eb97fcd2e37df3f681dc3c1b3f48bdeae119cd Output.14 = a7b6c0c8bebd7eca9357a2be02063a603c103d68a793e792497ecf66592835f1f9607dae7b98be1049514ec5ea4cdd0b41d5cbf986a3a04314515b341f0924ab +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -56335,6 +56474,7 @@ AdditionalInputB.14 = c0e16d4fc85cfb1c3a4f69806041c5a270d4af742292dcebeccba75e1b EntropyPredictionResistanceB.14 = a52c99a12f63c6ae4bc101ff221d7fd1b4dd79df76e38992ba3fdf380bdbad5e6aa15d0ab638e90874d81bdb2e983aba Output.14 = e728957b292565f906de0cee5bf91fbe2e189857ca5d5efefb5953a8e9f46630756ea01abf8e6fc499bc8e2e5c29c62669bc07ccfbdc7951215f8ba7f1bc815e +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -56400,6 +56540,7 @@ EntropyPredictionResistanceA.14 = cd66ebf08c99f9c04c1effc078717b4f24422f111591a0 EntropyPredictionResistanceB.14 = 60c6f9f07f75f1a80188b32d07c2895872c4e8b92a19ac6c2a29bc807f99fb4af75b6aed8e6f75c9a6b1559b48f128e9 Output.14 = 2d20709ea0ff7a624ea1e37d80c65c25eaed85af45ef1a092ea7b97c49c912a0f0fc62d29ff4e4182c6bb12676cab3711c2b8db265cd9f81569a300b99fac43e +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -56495,6 +56636,7 @@ AdditionalInputB.14 = dbe91ffe3bfb719bebbb0e3bb60aa907ca6e0411c05a7ded766674cd4d EntropyPredictionResistanceB.14 = ca5099749aa7f195e0fde5262c56ad35c1d52069001fbb6580d478f50d1d69f6941d7ea4fa66e4741cad701a67f92933 Output.14 = a135641f33e2aa5975a3be70b05e0b8c48372ef7c6768eed8e6c2b4e91d9153eead217ea47bf96b1412af4e08c3114d2c85f2e29fbe93c26014677bd14266ecf +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 @@ -56575,6 +56717,7 @@ EntropyPredictionResistanceA.14 = c3444261962386b57d6c5f125dc3043678afe1962d55d9 EntropyPredictionResistanceB.14 = 1fd895068aec8df2684784007949e0370578676c6537a09dd90567b95f6138809e70bcc9fc9efc03dfd83f0367784bde Output.14 = 894f3bc0fcbdb76b01df80f05d0ca636bd51438f5ee28250f27e8e47968c9c86a847970090d51b0a60984ebb5079017a5c5bac394e9644befc566edd4768d919 +FIPSversion = <3.5.8 RAND = CTR-DRBG Cipher = AES-256-CTR PredictionResistance = 1 From e386501f08c7e8ff87eb54608654959a11c94b7e Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 28 Jul 2026 16:23:01 +0200 Subject: [PATCH 113/189] Document the behavior of BN_generate_prime() on failure The ret argument is freed on failure which might be surprising to callers. Reported by: Minkyung Park (UNIST) Reviewed-by: Eugene Syromiatnikov Reviewed-by: Paul Yang MergeDate: Mon Aug 10 15:09:34 2026 (Merged from https://github.com/openssl/openssl/pull/32099) (cherry picked from commit 6d250710fb8cfd5c9a41af373c0c1ca85ff836c2) --- doc/man3/BN_generate_prime.pod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/man3/BN_generate_prime.pod b/doc/man3/BN_generate_prime.pod index 6b8d1de19cd83..4c83fd4a5e4b0 100644 --- a/doc/man3/BN_generate_prime.pod +++ b/doc/man3/BN_generate_prime.pod @@ -201,6 +201,8 @@ BN_is_prime_fasttest() and BN_check_prime return 0 if the number is composite, -1 on error. BN_generate_prime() returns the prime number on success, B otherwise. +Please note that the B BIGNUM is freed on failure and must not be +used or freed by the caller in such case. BN_GENCB_new returns a pointer to a BN_GENCB structure on success, or B otherwise. From d5e78dfc824eb8d99de1d861992eaad83de53fda Mon Sep 17 00:00:00 2001 From: Filipe Date: Sat, 1 Aug 2026 02:35:37 -0300 Subject: [PATCH 114/189] Document SM4 table-lookup side-channel risk Note in EVP_CIPHER-SM4(7) that SM4 implementations may use secret-dependent table lookups and are not guaranteed to be constant-time. Mention the portable C path as a concrete example and point to CPU capability man pages for code-path selection. Fixes: https://github.com/openssl/openssl/issues/31911 Assisted-by: Cursor:composer Reviewed-by: Eugene Syromiatnikov Reviewed-by: Paul Yang MergeDate: Tue Aug 11 07:03:00 2026 (Merged from https://github.com/openssl/openssl/pull/32136) --- doc/man7/EVP_CIPHER-SM4.pod | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/man7/EVP_CIPHER-SM4.pod b/doc/man7/EVP_CIPHER-SM4.pod index a446fafb6d4b1..b68ffc9b6aae9 100644 --- a/doc/man7/EVP_CIPHER-SM4.pod +++ b/doc/man7/EVP_CIPHER-SM4.pod @@ -39,6 +39,13 @@ L. =head1 NOTES +SM4 implementations in OpenSSL may use secret-dependent table lookups and +are not guaranteed to be constant-time. In particular, the portable C +implementation uses S-box and T-table lookups and may be vulnerable to +cache-timing side-channel attacks. Which code path is used depends on CPU +capabilities; see L, L and +L. + The SM4-XTS implementation allows streaming to be performed, but each L or L call requires each input to be a multiple of the blocksize. Only the final EVP_EncryptUpdate() or @@ -48,11 +55,12 @@ stealing (CTS) is used to fill the block. =head1 SEE ALSO -L, L +L, L, L, +L, L =head1 COPYRIGHT -Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2026 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 From b41c1bc191299c74949b631c54b376c2485b7855 Mon Sep 17 00:00:00 2001 From: Haiyang Huang Date: Thu, 18 Jun 2026 09:19:42 +0800 Subject: [PATCH 115/189] quic: reject ACK of an unsent packet number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ossl_ackm_on_rx_ack_frame() stored ack_ranges[0].end into largest_acked_pkt[pkt_space] without checking it against the highest packet number actually sent in that space. Because largest_acked_pkt only ever increases and drives loss detection, an ACK acknowledging a packet number that was never sent (up to 2**62 - 1) pins the value and causes every in-flight and subsequently-sent packet to be declared lost, permanently corrupting loss detection for the connection. RFC 9000 s. 13.1 recommends treating an acknowledgment for a packet the endpoint did not send as a connection error of type PROTOCOL_VIOLATION, where it can be detected. Reject any ACK whose largest acknowledged packet number exceeds the highest packet number sent in that space; the bound, highest_sent, is already tracked. The depacketiser raises PROTOCOL_VIOLATION when the ACK manager rejects the frame. Update the QUIC tests for the new behaviour: cases 7 and 8 now assert rejection, case 14 covers the 2**62 - 1 boundary, two pre-existing fixtures that acknowledged one packet past the highest sent are corrected, and the "fictional PN" script now expects a PROTOCOL_VIOLATION close. Fixes: fa4e92a70a5f "QUIC ACK Manager, Statistics Manager and Congestion Control API" Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Saša Nedvědický Reviewed-by: Tomas Mraz MergeDate: Tue Jun 23 16:36:27 2026 Reviewed-by: Frederik Wedel-Heinen Reviewed-by: Nikola Pajkovsky (Merged from https://github.com/openssl/openssl/pull/32208) --- ssl/quic/quic_ackm.c | 13 +++++++ ssl/quic/quic_rx_depack.c | 15 ++++++-- test/quic_ackm_test.c | 66 +++++++++++++++++++++++++++++++----- test/quic_multistream_test.c | 9 +++-- 4 files changed, 90 insertions(+), 13 deletions(-) diff --git a/ssl/quic/quic_ackm.c b/ssl/quic/quic_ackm.c index 24b72e42d902b..20697cd7c4e83 100644 --- a/ssl/quic/quic_ackm.c +++ b/ssl/quic/quic_ackm.c @@ -1169,8 +1169,21 @@ int ossl_ackm_on_rx_ack_frame(OSSL_ACKM *ackm, const OSSL_QUIC_FRAME_ACK *ack, int pkt_space, OSSL_TIME rx_time) { OSSL_ACKM_TX_PKT *na_pkts, *lost_pkts; + struct tx_pkt_history_st *h = get_tx_history(ackm, pkt_space); int must_set_timer = 0; + /* + * RFC 9000 s. 13.1 recommends treating an acknowledgment for a packet we + * did not send as a PROTOCOL_VIOLATION, where detectable. The largest + * acknowledged PN is ack_ranges[0].end; if it exceeds the highest PN we have + * sent in this space, reject the ACK. Otherwise the peer-controlled value is + * stored into largest_acked_pkt below, which only ever increases and drives + * loss detection, so a single such ACK would permanently force every + * in-flight and subsequently-sent packet to be declared lost. + */ + if (ack->ack_ranges[0].end > h->highest_sent) + return 0; + if (ackm->largest_acked_pkt[pkt_space] == QUIC_PN_INVALID) ackm->largest_acked_pkt[pkt_space] = ack->ack_ranges[0].end; else diff --git a/ssl/quic/quic_rx_depack.c b/ssl/quic/quic_rx_depack.c index 7ab59f01a1cde..59d16b2f362c7 100644 --- a/ssl/quic/quic_rx_depack.c +++ b/ssl/quic/quic_rx_depack.c @@ -125,8 +125,19 @@ static int depack_do_frame_ack(PACKET *pkt, QUIC_CHANNEL *ch, } if (!ossl_ackm_on_rx_ack_frame(ch->ackm, &ack, - packet_space, received)) - goto malformed; + packet_space, received)) { + /* + * The ACK manager rejects the frame if it acknowledges a packet number + * we have not sent. RFC 9000 s. 13.1 recommends treating this as a + * PROTOCOL_VIOLATION connection error (distinct from a frame decoding + * error, which is handled at the malformed label below). + */ + ossl_quic_channel_raise_protocol_error(ch, + OSSL_QUIC_ERR_PROTOCOL_VIOLATION, + frame_type, + "ACK for unsent packet number"); + return 0; + } ++ch->diag_num_rx_ack; return 1; diff --git a/test/quic_ackm_test.c b/test/quic_ackm_test.c index 9b8e3aafb7fa5..88cd033837cdb 100644 --- a/test/quic_ackm_test.c +++ b/test/quic_ackm_test.c @@ -11,6 +11,7 @@ #include #include "internal/quic_ackm.h" #include "internal/quic_cc.h" +#include "internal/quic_vlint.h" static OSSL_TIME fake_time = { 0 }; @@ -147,13 +148,26 @@ struct tx_ack_test_case { const OSSL_QUIC_ACK_RANGE *ack_ranges; size_t num_ack_ranges; const char *expect_ack; /* 1=ack, 2=lost, 4=discarded */ + int expect_reject; /* if nonzero the ACK must be rejected (returns 0) */ }; #define DEFINE_TX_ACK_CASE(n, pntable) \ static const struct tx_ack_test_case tx_ack_case_##n = { \ (pntable), OSSL_NELEM(pntable), \ tx_ack_range_##n, OSSL_NELEM(tx_ack_range_##n), \ - tx_ack_expect_##n \ + tx_ack_expect_##n, 0 \ + } + +/* + * As DEFINE_TX_ACK_CASE, but the ACK acknowledges a packet number that was + * never sent and so must be rejected by ossl_ackm_on_rx_ack_frame() + * (RFC 9000 s. 13.1). + */ +#define DEFINE_TX_ACK_CASE_REJECT(n, pntable) \ + static const struct tx_ack_test_case tx_ack_case_##n = { \ + (pntable), OSSL_NELEM(pntable), \ + tx_ack_range_##n, OSSL_NELEM(tx_ack_range_##n), \ + tx_ack_expect_##n, 1 \ } /* One range, partial coverage of space */ @@ -207,32 +221,32 @@ static const char tx_ack_expect_5[] = { }; DEFINE_TX_ACK_CASE(5, linear_20); -/* One range, covering entire space */ +/* One range covering the whole space (0..19, highest sent PN is 19): all acked */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_6[] = { - { 0, 20 }, + { 0, 19 }, }; static const char tx_ack_expect_6[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; DEFINE_TX_ACK_CASE(6, linear_20); -/* One range, covering more space than exists */ +/* One range above the highest sent PN (30 > 19): ACK rejected */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_7[] = { { 0, 30 }, }; static const char tx_ack_expect_7[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -DEFINE_TX_ACK_CASE(7, linear_20); +DEFINE_TX_ACK_CASE_REJECT(7, linear_20); -/* One range, covering nothing (too high) */ +/* One range entirely above the sent PNs (21..30): ACK rejected */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_8[] = { { 21, 30 }, }; static const char tx_ack_expect_8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -DEFINE_TX_ACK_CASE(8, linear_20); +DEFINE_TX_ACK_CASE_REJECT(8, linear_20); /* One range, covering nothing (too low) */ static const OSSL_QUIC_ACK_RANGE tx_ack_range_9[] = { @@ -289,6 +303,20 @@ static const char tx_ack_expect_13[] = { }; DEFINE_TX_ACK_CASE(13, high_linear_20); +/* + * Largest range claims the maximum PN (2**62 - 1, never sent) plus a second + * range over real packets so loss detection would otherwise run. ACK rejected; + * otherwise largest_acked_pkt pins at the maximum and every in-flight packet is + * declared lost. + */ +static const OSSL_QUIC_ACK_RANGE tx_ack_range_14[] = { + { OSSL_QUIC_VLINT_MAX, OSSL_QUIC_VLINT_MAX }, { 15, 19 } +}; +static const char tx_ack_expect_14[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +DEFINE_TX_ACK_CASE_REJECT(14, linear_20); + static const struct tx_ack_test_case *const tx_ack_cases[] = { &tx_ack_case_1, &tx_ack_case_2, @@ -303,6 +331,7 @@ static const struct tx_ack_test_case *const tx_ack_cases[] = { &tx_ack_case_11, &tx_ack_case_12, &tx_ack_case_13, + &tx_ack_case_14, }; enum { @@ -402,6 +431,25 @@ static int test_tx_ack_case_actual(int tidx, int space, int mode) /* Try acknowledging. */ ack.ack_ranges = (OSSL_QUIC_ACK_RANGE *)c->ack_ranges; ack.num_ack_ranges = c->num_ack_ranges; + + if (c->expect_reject) { + /* ACK of an unsent PN: rejected without touching loss detection. */ + if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack, space, + fake_time), + 0)) + goto err; + + for (i = 0; i < c->pn_table_len; ++i) { + if (!TEST_int_eq(h.pkts[i].acked, 0) + || !TEST_int_eq(h.pkts[i].lost, 0) + || !TEST_int_eq(h.pkts[i].discarded, 0)) + goto err; + } + + testresult = 1; + goto err; + } + if (!TEST_int_eq(ossl_ackm_on_rx_ack_frame(h.ackm, &ack, space, fake_time), 1)) goto err; @@ -577,7 +625,7 @@ static int test_tx_ack_time_script(int tidx) ack.num_ack_ranges = 1; ack_range.start = s->pn; - ack_range.end = s->pn + s->num_pn; + ack_range.end = s->pn + s->num_pn - 1; fake_time = ossl_time_add(fake_time, ossl_ticks2time(s->time_advance)); diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index 169577a64595f..1987bd826136e 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -4034,9 +4034,14 @@ static const struct script_op script_49[] = { OP_SET_INJECT_WORD(4, 0) OP_S_WRITE(a, "Strawberry", 10) - OP_C_READ_EXPECT(DEFAULT, "Strawberry", 10) + /* + * The injected ACK acknowledges a packet number we have not sent, which the + * peer is expected to treat as a PROTOCOL_VIOLATION, so the connection is + * closed rather than the stream data being delivered. + */ + OP_C_EXPECT_CONN_CLOSE_INFO(OSSL_QUIC_ERR_PROTOCOL_VIOLATION, 0, 0) - OP_END + OP_END }; /* 50. Fault injection - ACK - duplicate PN */ From f3b94dc87b18ab1371e2b1abf87be6a05ef2f34c Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 5 Aug 2026 15:04:02 +0200 Subject: [PATCH 116/189] ssl: add missing SSLfatal in PSK premaster secret generation An allocation failure for the PSK premaster secret buffer in ssl_generate_master_secret() returned failure without calling SSLfatal(), while its callers on both the client key exchange construction and processing paths assume the fatal state was already set. Also cover the unreachable no-PSK fallback branch. Assisted-by: Claude:claude-fable-5 Reviewed-by: Frederik Wedel-Heinen Reviewed-by: Matt Caswell MergeDate: Tue Aug 11 07:28:48 2026 (Merged from https://github.com/openssl/openssl/pull/32195) --- ssl/s3_lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 213ec84b171d5..079a308f6ff1b 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -5223,8 +5223,10 @@ int ssl_generate_master_secret(SSL_CONNECTION *s, unsigned char *pms, pskpmslen = 4 + pmslen + psklen; pskpms = OPENSSL_malloc(pskpmslen); - if (pskpms == NULL) + if (pskpms == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB); goto err; + } t = pskpms; s2n(pmslen, t); if (alg_k & SSL_kPSK) @@ -5248,6 +5250,7 @@ int ssl_generate_master_secret(SSL_CONNECTION *s, unsigned char *pms, OPENSSL_clear_free(pskpms, pskpmslen); #else /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); goto err; #endif } else { From d44190def5df1d4d6721956bc22e9ef46173781f Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 5 Aug 2026 14:59:42 +0200 Subject: [PATCH 117/189] statem: add missing SSLfatal in compressed certificate construction A WPACKET failure in tls_construct_server_compressed_certificate() returned CON_FUNC_ERROR without calling SSLfatal(), unlike the identical failure handling in tls_construct_server_certificate(). This trips the check_fatal assertion in write_state_machine() on debug builds and skips the alert and error state otherwise. Assisted-by: Claude:claude-fable-5 Reviewed-by: Matt Caswell Reviewed-by: Frederik Wedel-Heinen MergeDate: Tue Aug 11 07:34:19 2026 (Merged from https://github.com/openssl/openssl/pull/32197) --- ssl/statem/statem_srvr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 3c7d2ac433713..03fcc6eeac796 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -3921,8 +3921,10 @@ CON_FUNC_RETURN tls_construct_server_compressed_certificate(SSL_CONNECTION *sc, || !WPACKET_put_bytes_u24(pkt, cc->orig_len) || !WPACKET_start_sub_packet_u24(pkt) || !WPACKET_memcpy(pkt, cc->data, cc->len) - || !WPACKET_close(pkt)) + || !WPACKET_close(pkt)) { + SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return 0; + } sc->s3.tmp.cert->cert_comp_used++; return 1; From 3e74574a12a1f4672a49ad0e3b9bbde284e1148e Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 30 Jul 2026 09:24:59 +0900 Subject: [PATCH 118/189] Merge event masks for duplicate fds in the RIO poll builder ossl_rio_poll_builder_add_fd() documents duplicate registrations as equivalent to one registration with the logical OR of the requested directions. The poll(2) backend instead cleared an existing entry, making duplicate registrations last-writer-wins. The select(2) backend only adds bits to its fd_sets and already merges them. Clear the mask only when populating a new or reusable slot so an existing fd retains its previously requested events. Fixes https://github.com/openssl/openssl/issues/32116 Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Paul Yang Reviewed-by: Jakub Zelenka MergeDate: Tue Aug 11 07:12:57 2026 (Merged from https://github.com/openssl/openssl/pull/32117) (cherry picked from commit 363b604bffc131e2ccda48b89d2d3ebf5eb285ad) --- ssl/rio/poll_builder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ssl/rio/poll_builder.c b/ssl/rio/poll_builder.c index 28d93ee1947a9..8088b17ad7ada 100644 --- a/ssl/rio/poll_builder.c +++ b/ssl/rio/poll_builder.c @@ -120,8 +120,10 @@ int ossl_rio_poll_builder_add_fd(RIO_POLL_BUILDER *rpb, int fd, assert((rpb->pfd_heap != NULL && rpb->pfd_heap == pfds) || (rpb->pfd_heap == NULL && rpb->pfds == pfds)); assert(i <= rpb->pfd_num && rpb->pfd_num <= rpb->pfd_alloc); + /* Check the index first because an appended entry is uninitialised. */ + if (i == rpb->pfd_num || pfds[i].fd == -1) + pfds[i].events = 0; pfds[i].fd = fd; - pfds[i].events = 0; if (want_read) pfds[i].events |= POLLIN; From b74ed29f897735d121eafe38ba59be2198a3bc26 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 30 Jul 2026 09:25:18 +0900 Subject: [PATCH 119/189] test: cover duplicate fd event merging in RIO poll builder Add a poll-backend unit test which registers the same fd first for reading and then for writing. Verify that the builder retains one pollfd with both POLLIN and POLLOUT set. Without the preceding fix, the test observes POLLOUT only. Wire the test into the QUIC-gated test build and skip it on non-poll backends. Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Paul Yang Reviewed-by: Jakub Zelenka MergeDate: Tue Aug 11 07:12:58 2026 (Merged from https://github.com/openssl/openssl/pull/32117) (cherry picked from commit 258f06b1ef57ce147ff2b1da5977d9e9adc55be7) --- test/build.info | 7 +++- test/recipes/70-test_rio_poll_builder.t | 19 +++++++++++ test/rio_poll_builder_test.c | 45 +++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 test/recipes/70-test_rio_poll_builder.t create mode 100644 test/rio_poll_builder_test.c diff --git a/test/build.info b/test/build.info index 99e06d3945309..d9a87832d5018 100644 --- a/test/build.info +++ b/test/build.info @@ -82,7 +82,8 @@ IF[{- !$disabled{tests} -}] IF[{- !$disabled{quic} -}] PROGRAMS{noinst}=priority_queue_test quicfaultstest quicapitest \ - quic_newcid_test quic_srt_gen_test + quic_newcid_test quic_srt_gen_test \ + rio_poll_builder_test ENDIF IF[{- !$disabled{qlog} -}] @@ -345,6 +346,10 @@ IF[{- !$disabled{tests} -}] DEPEND[packettest]=../libcrypto libtestutil.a IF[{- !$disabled{'quic'} -}] + SOURCE[rio_poll_builder_test]=rio_poll_builder_test.c + INCLUDE[rio_poll_builder_test]=.. ../include ../apps/include + DEPEND[rio_poll_builder_test]=../libcrypto.a ../libssl.a libtestutil.a + SOURCE[quic_wire_test]=quic_wire_test.c INCLUDE[quic_wire_test]=../include ../apps/include DEPEND[quic_wire_test]=../libcrypto.a ../libssl.a libtestutil.a diff --git a/test/recipes/70-test_rio_poll_builder.t b/test/recipes/70-test_rio_poll_builder.t new file mode 100644 index 0000000000000..e76c2f280a781 --- /dev/null +++ b/test/recipes/70-test_rio_poll_builder.t @@ -0,0 +1,19 @@ +#! /usr/bin/env perl +# Copyright 2026 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_rio_poll_builder"); + +plan skip_all => "RIO poll builder tests require QUIC" + if disabled("quic"); + +plan tests => 1; + +ok(run(test(["rio_poll_builder_test"]))); diff --git a/test/rio_poll_builder_test.c b/test/rio_poll_builder_test.c new file mode 100644 index 0000000000000..f4acb7b9c20ba --- /dev/null +++ b/test/rio_poll_builder_test.c @@ -0,0 +1,45 @@ +/* + * Copyright 2026 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 "../ssl/rio/poll_builder.h" +#include "testutil.h" + +static int test_duplicate_fd(void) +{ +#if RIO_POLL_METHOD == RIO_POLL_METHOD_POLL + RIO_POLL_BUILDER rpb; + struct pollfd *pfds; + int ret = 0; + + if (!TEST_true(ossl_rio_poll_builder_init(&rpb))) + return 0; + + if (!TEST_true(ossl_rio_poll_builder_add_fd(&rpb, 0, 1, 0)) + || !TEST_true(ossl_rio_poll_builder_add_fd(&rpb, 0, 0, 1))) + goto out; + + pfds = rpb.pfd_heap != NULL ? rpb.pfd_heap : rpb.pfds; + if (!TEST_size_t_eq(rpb.pfd_num, 1) + || !TEST_int_eq(pfds[0].events, POLLIN | POLLOUT)) + goto out; + + ret = 1; +out: + ossl_rio_poll_builder_cleanup(&rpb); + return ret; +#else + return TEST_skip("poll() backend is not in use"); +#endif +} + +int setup_tests(void) +{ + ADD_TEST(test_duplicate_fd); + return 1; +} From 329938c1c4e9d1559dcd8123ac093f76b64f8d0c Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Mon, 3 Aug 2026 17:27:09 +1000 Subject: [PATCH 120/189] Additional ML-KEM cleansing Also, mark X448MLKEM1024 as FIPS non-approved (backport of #26220) Reviewed-by: Tim Hudson Reviewed-by: Milan Broz MergeDate: Tue Aug 11 15:06:57 2026 (Merged from https://github.com/openssl/openssl/pull/32167) --- crypto/ml_kem/ml_kem.c | 76 +++++++++++++++---- providers/fips/fipsprov.c | 4 +- providers/implementations/kem/ml_kem_kem.c | 1 + providers/implementations/kem/mlx_kem.c | 10 ++- .../implementations/keymgmt/ml_kem_kmgmt.c | 31 +++++--- providers/implementations/keymgmt/mlx_kmgmt.c | 26 +++++-- 6 files changed, 115 insertions(+), 33 deletions(-) diff --git a/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c index 41a3a43d759fe..2729c971e44b4 100644 --- a/crypto/ml_kem/ml_kem.c +++ b/crypto/ml_kem/ml_kem.c @@ -1310,6 +1310,12 @@ static __owur int matrix_expand(EVP_MD_CTX *mdctx, ML_KEM_KEY *key) int rank = key->vinfo->rank; int i, j; + /* + * The seeds derived below and the sampling buffers in sample_scalar() + * are not cleansed: per FIPS 203 section 3.3 the matrix A is easily + * computed from the public encapsulation key and does not require any + * special protections. + */ memcpy(input, key->rho, ML_KEM_RANDOM_BYTES); for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { @@ -1340,8 +1346,10 @@ static __owur int cbd_2(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1], uint16_t value, mask; uint8_t b; - if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) + if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) { + OPENSSL_cleanse((void *)randbuf, sizeof(randbuf)); return 0; + } do { b = *r++; @@ -1363,6 +1371,8 @@ static __owur int cbd_2(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1], mask = constish_time_non_zero(value >> 15); *curr++ = value + (kPrime & mask); } while (curr < end); + + OPENSSL_cleanse((void *)randbuf, sizeof(randbuf)); return 1; } @@ -1380,8 +1390,10 @@ static __owur int cbd_3(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1], uint8_t b1, b2, b3; uint16_t value, mask; - if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) + if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) { + OPENSSL_cleanse((void *)randbuf, sizeof(randbuf)); return 0; + } do { b1 = *r++; @@ -1415,6 +1427,8 @@ static __owur int cbd_3(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1], mask = constish_time_non_zero(value >> 15); *curr++ = value + (kPrime & mask); } while (curr < end); + + OPENSSL_cleanse((void *)randbuf, sizeof(randbuf)); return 1; } @@ -1427,14 +1441,19 @@ static __owur int gencbd_vector(scalar *out, CBD_FUNC cbd, uint8_t *counter, EVP_MD_CTX *mdctx, const ML_KEM_KEY *key) { uint8_t input[ML_KEM_RANDOM_BYTES + 1]; + int ret = 0; memcpy(input, seed, ML_KEM_RANDOM_BYTES); do { input[ML_KEM_RANDOM_BYTES] = (*counter)++; if (!cbd(out++, input, mdctx, key)) - return 0; + goto end; } while (--rank > 0); - return 1; + ret = 1; + +end: + OPENSSL_cleanse((void *)input, sizeof(input)); + return ret; } /* @@ -1445,15 +1464,20 @@ static __owur int gencbd_vector_ntt(scalar *out, CBD_FUNC cbd, uint8_t *counter, EVP_MD_CTX *mdctx, const ML_KEM_KEY *key) { uint8_t input[ML_KEM_RANDOM_BYTES + 1]; + int ret = 0; memcpy(input, seed, ML_KEM_RANDOM_BYTES); do { input[ML_KEM_RANDOM_BYTES] = (*counter)++; if (!cbd(out, input, mdctx, key)) - return 0; + goto end; scalar_ntt(out++); } while (--rank > 0); - return 1; + ret = 1; + +end: + OPENSSL_cleanse((void *)input, sizeof(input)); + return ret; } /* The |ETA1| value for ML-KEM-512 is 3, the rest and all ETA2 values are 2. */ @@ -1492,10 +1516,11 @@ static __owur int encrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES], uint8_t counter = 0; int du = vinfo->du; int dv = vinfo->dv; + int ret = 0; /* FIPS 203 "y" vector */ if (!gencbd_vector_ntt(y, cbd_1, &counter, r, rank, mdctx, key)) - return 0; + goto end; /* FIPS 203 "v" scalar */ inner_product(&v, key->t, y, rank); scalar_inverse_ntt(&v); @@ -1504,7 +1529,7 @@ static __owur int encrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES], /* All done with |y|, now free to reuse tmp[0] for FIPS 203 |e1| */ if (!gencbd_vector(e1, cbd_2, &counter, r, rank, mdctx, key)) - return 0; + goto end; vector_add(u, e1, rank); vector_compress(u, du, rank); vector_encode(out, u, du, rank); @@ -1513,14 +1538,19 @@ static __owur int encrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES], memcpy(input, r, ML_KEM_RANDOM_BYTES); input[ML_KEM_RANDOM_BYTES] = counter; if (!cbd_2(e2, input, mdctx, key)) - return 0; + goto end; scalar_add(&v, e2); /* Combine message with |v| */ scalar_decode_decompress_add(&v, message); scalar_compress(&v, dv); scalar_encode(out + vinfo->u_vector_bytes, &v, dv); - return 1; + ret = 1; + +end: + OPENSSL_cleanse((void *)input, sizeof(input)); + OPENSSL_cleanse((void *)&v, sizeof(v)); + return ret; } /* @@ -1544,6 +1574,9 @@ decrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES], scalar_sub(&v, &mask); scalar_compress(&v, 1); scalar_encode_1(out, &v); + + OPENSSL_cleanse((void *)&v, sizeof(v)); + OPENSSL_cleanse((void *)&mask, sizeof(mask)); } /*- @@ -1737,8 +1770,8 @@ static __owur int genkey(const uint8_t seed[ML_KEM_SEED_BYTES], ret = 1; end: - OPENSSL_cleanse((void *)augmented_seed, ML_KEM_RANDOM_BYTES); - OPENSSL_cleanse((void *)sigma, ML_KEM_RANDOM_BYTES); + OPENSSL_cleanse((void *)augmented_seed, sizeof(augmented_seed)); + OPENSSL_cleanse((void *)hashed, sizeof(hashed)); if (ret == 0) { ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR, "internal error while generating %s private key", @@ -1776,6 +1809,7 @@ static int encap(uint8_t *ctext, uint8_t secret[ML_KEM_SHARED_SECRET_BYTES], ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR, "internal error while performing %s encapsulation", key->vinfo->algorithm_name); + OPENSSL_cleanse((void *)Kr, sizeof(Kr)); return ret; } @@ -1822,6 +1856,7 @@ static int decap(uint8_t secret[ML_KEM_SHARED_SECRET_BYTES], ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR, "internal error while performing %s decapsulation", vinfo->algorithm_name); + OPENSSL_cleanse(failure_key, sizeof(failure_key)); return 0; } decrypt_cpa(decrypted, ctext, tmp, key); @@ -1830,6 +1865,8 @@ static int decap(uint8_t secret[ML_KEM_SHARED_SECRET_BYTES], || !encrypt_cpa(tmp_ctext, decrypted, r, tmp, mdctx, key)) { memcpy(secret, failure_key, ML_KEM_SHARED_SECRET_BYTES); OPENSSL_cleanse(decrypted, ML_KEM_SHARED_SECRET_BYTES); + OPENSSL_cleanse(Kr, sizeof(Kr)); + OPENSSL_cleanse(failure_key, sizeof(failure_key)); return 1; } mask = constant_time_eq_int_8(0, @@ -1838,6 +1875,7 @@ static int decap(uint8_t secret[ML_KEM_SHARED_SECRET_BYTES], secret[i] = constant_time_select_8(mask, Kr[i], failure_key[i]); OPENSSL_cleanse(decrypted, ML_KEM_SHARED_SECRET_BYTES); OPENSSL_cleanse(Kr, sizeof(Kr)); + OPENSSL_cleanse(failure_key, sizeof(failure_key)); return 1; } @@ -2199,6 +2237,9 @@ int ossl_ml_kem_genkey(uint8_t *pubenc, size_t publen, ML_KEM_KEY *key) EVP_MD_CTX_free(mdctx); if (!ret) { + /* Erase any partial public key output */ + if (pubenc != NULL) + OPENSSL_cleanse(pubenc, vinfo->pubkey_bytes); ossl_ml_kem_key_reset(key); return 0; } @@ -2257,6 +2298,10 @@ int ossl_ml_kem_encap_seed(uint8_t *ctext, size_t clen, } #undef case_encap_seed + /* Erase any partial ciphertext output on failure */ + if (!ret) + OPENSSL_cleanse(ctext, clen); + /* Declassify secret inputs and derived outputs before returning control */ CONSTTIME_DECLASSIFY(entropy, elen); CONSTTIME_DECLASSIFY(ctext, clen); @@ -2271,6 +2316,7 @@ int ossl_ml_kem_encap_rand(uint8_t *ctext, size_t clen, const ML_KEM_KEY *key) { uint8_t r[ML_KEM_RANDOM_BYTES]; + int ret; if (key == NULL) return 0; @@ -2280,8 +2326,11 @@ int ossl_ml_kem_encap_rand(uint8_t *ctext, size_t clen, < 1) return 0; - return ossl_ml_kem_encap_seed(ctext, clen, shared_secret, slen, + ret = ossl_ml_kem_encap_seed(ctext, clen, shared_secret, slen, r, sizeof(r), key); + + OPENSSL_cleanse((void *)r, sizeof(r)); + return ret; } int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen, @@ -2331,6 +2380,7 @@ int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen, \ ret = decap(shared_secret, ctext, cbuf, tmp, mdctx, key); \ OPENSSL_cleanse((void *)tmp, sizeof(tmp)); \ + OPENSSL_cleanse((void *)cbuf, sizeof(cbuf)); \ break; \ } switch (vinfo->evp_type) { diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 0a7deaeb78dc2..8917166bce374 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -540,7 +540,7 @@ static const OSSL_ALGORITHM fips_asym_kem[] = { { PROV_NAMES_ML_KEM_1024, FIPS_DEFAULT_PROPERTIES, ossl_ml_kem_asym_kem_functions }, #if !defined(OPENSSL_NO_ECX) { "X25519MLKEM768", FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, - { "X448MLKEM1024", FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, + { "X448MLKEM1024", FIPS_UNAPPROVED_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, #endif #if !defined(OPENSSL_NO_EC) { "SecP256r1MLKEM768", FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, @@ -607,7 +607,7 @@ static const OSSL_ALGORITHM fips_keymgmt[] = { #if !defined(OPENSSL_NO_ECX) { PROV_NAMES_X25519MLKEM768, FIPS_DEFAULT_PROPERTIES, ossl_mlx_x25519_kem_kmgmt_functions, PROV_DESCS_X25519MLKEM768 }, - { PROV_NAMES_X448MLKEM1024, FIPS_DEFAULT_PROPERTIES, ossl_mlx_x448_kem_kmgmt_functions, + { PROV_NAMES_X448MLKEM1024, FIPS_UNAPPROVED_PROPERTIES, ossl_mlx_x448_kem_kmgmt_functions, PROV_DESCS_X448MLKEM1024 }, #endif #if !defined(OPENSSL_NO_EC) diff --git a/providers/implementations/kem/ml_kem_kem.c b/providers/implementations/kem/ml_kem_kem.c index 722eadf228975..b584c2862088d 100644 --- a/providers/implementations/kem/ml_kem_kem.c +++ b/providers/implementations/kem/ml_kem_kem.c @@ -125,6 +125,7 @@ static int ml_kem_set_ctx_params(void *vctx, const OSSL_PARAM params[]) /* Possibly, but much less likely wrong type */ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH); + OPENSSL_cleanse((void *)ctx->entropy_buf, sizeof(ctx->entropy_buf)); ctx->entropy = NULL; return 0; } diff --git a/providers/implementations/kem/mlx_kem.c b/providers/implementations/kem/mlx_kem.c index 376b3342ddfa8..fb0a50f753709 100644 --- a/providers/implementations/kem/mlx_kem.c +++ b/providers/implementations/kem/mlx_kem.c @@ -118,7 +118,7 @@ static int mlx_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen, if (!mlx_kem_have_pubkey(key)) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); - goto end; + return 0; } encap_clen = key->minfo->ctext_bytes + key->xinfo->pubkey_bytes; encap_slen = ML_KEM_SHARED_SECRET_BYTES + key->xinfo->shsec_bytes; @@ -236,6 +236,10 @@ static int mlx_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen, ret = 1; end: + /* Erase any partial shared secret on failure */ + if (ret == 0) + OPENSSL_cleanse(shsec, + ML_KEM_SHARED_SECRET_BYTES + key->xinfo->shsec_bytes); EVP_PKEY_free(xkey); EVP_PKEY_CTX_free(ctx); return ret; @@ -324,6 +328,10 @@ static int mlx_kem_decapsulate(void *vctx, uint8_t *shsec, size_t *slen, ret = 1; end: + /* Erase any partial shared secret on failure */ + if (ret == 0) + OPENSSL_cleanse(shsec, + ML_KEM_SHARED_SECRET_BYTES + key->xinfo->shsec_bytes); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(xkey); return ret; diff --git a/providers/implementations/keymgmt/ml_kem_kmgmt.c b/providers/implementations/keymgmt/ml_kem_kmgmt.c index 1f5dd1e64ce4d..1422a3775c74a 100644 --- a/providers/implementations/keymgmt/ml_kem_kmgmt.c +++ b/providers/implementations/keymgmt/ml_kem_kmgmt.c @@ -109,10 +109,6 @@ static int ml_kem_pairwise_test(const ML_KEM_KEY *key, int key_flags) memset(out, 0, sizeof(out)); - /* - * The pairwise test is skipped unless either RANDOM or FIXED entropy PCTs - * are enabled. - */ if (key_flags & ML_KEM_KEY_RANDOM_PCT) { operation_result = ossl_ml_kem_encap_rand(ctext, v->ctext_bytes, secret, sizeof(secret), key); @@ -147,7 +143,10 @@ static int ml_kem_pairwise_test(const ML_KEM_KEY *key, int key_flags) v->algorithm_name); } #endif - OPENSSL_free(ctext); + OPENSSL_cleanse((void *)entropy, sizeof(entropy)); + OPENSSL_cleanse((void *)secret, sizeof(secret)); + OPENSSL_cleanse((void *)out, sizeof(out)); + OPENSSL_clear_free(ctext, v->ctext_bytes); return ret; } @@ -237,7 +236,7 @@ static int ml_kem_export(void *vkey, int selection, OSSL_CALLBACK *param_cb, { ML_KEM_KEY *key = vkey; OSSL_PARAM_BLD *tmpl = NULL; - OSSL_PARAM *params = NULL; + OSSL_PARAM *params = NULL, *p; const ML_KEM_VINFO *v; uint8_t *pubenc = NULL, *prvenc = NULL, *seedenc = NULL; size_t prvlen = 0, seedlen = 0; @@ -316,13 +315,19 @@ static int ml_kem_export(void *vkey, int selection, OSSL_CALLBACK *param_cb, goto err; ret = param_cb(params, cbarg); + /* + * OSSL_PARAM_free() only wipes the secure-heap data block, + * so wipe the key material copies held in the params first. + */ + for (p = params; p->key != NULL; p++) + OPENSSL_cleanse(p->data, p->data_size); OSSL_PARAM_free(params); err: OSSL_PARAM_BLD_free(tmpl); OPENSSL_secure_clear_free(seedenc, seedlen); OPENSSL_secure_clear_free(prvenc, prvlen); - OPENSSL_free(pubenc); + OPENSSL_clear_free(pubenc, v->pubkey_bytes); return ret; } @@ -539,12 +544,15 @@ static void *ml_kem_load(const void *reference, size_t reference_sz) if (!ml_kem_pairwise_test(key, key->prov_flags)) goto err; } - OPENSSL_free(encoded_dk); + OPENSSL_clear_free(encoded_dk, key->vinfo->prvkey_bytes); + OPENSSL_cleanse((void *)seed, sizeof(seed)); return key; } err: - OPENSSL_free(encoded_dk); + if (key != NULL && key->vinfo != NULL) + OPENSSL_clear_free(encoded_dk, key->vinfo->prvkey_bytes); + OPENSSL_cleanse((void *)seed, sizeof(seed)); ossl_ml_kem_key_free(key); return NULL; } @@ -705,6 +713,7 @@ static int ml_kem_gen_set_params(void *vgctx, const OSSL_PARAM params[]) /* Possibly, but less likely wrong data type */ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH); + OPENSSL_cleanse((void *)gctx->seedbuf, sizeof(gctx->seedbuf)); gctx->seed = NULL; return 0; } @@ -765,8 +774,10 @@ static void *ml_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg) if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) return key; - if (seed != NULL && !ossl_ml_kem_set_seed(seed, ML_KEM_SEED_BYTES, key)) + if (seed != NULL && !ossl_ml_kem_set_seed(seed, ML_KEM_SEED_BYTES, key)) { + ossl_ml_kem_key_free(key); return NULL; + } genok = ossl_ml_kem_genkey(nopub, 0, key); /* Erase the single-use seed */ diff --git a/providers/implementations/keymgmt/mlx_kmgmt.c b/providers/implementations/keymgmt/mlx_kmgmt.c index 5d1902ce637ca..75267f88e7610 100644 --- a/providers/implementations/keymgmt/mlx_kmgmt.c +++ b/providers/implementations/keymgmt/mlx_kmgmt.c @@ -245,7 +245,7 @@ static int mlx_kem_export(void *vkey, int selection, OSSL_CALLBACK *param_cb, { MLX_KEY *key = vkey; OSSL_PARAM_BLD *tmpl = NULL; - OSSL_PARAM *params = NULL; + OSSL_PARAM *params = NULL, *p; size_t publen; size_t prvlen; int ret = 0; @@ -307,12 +307,18 @@ static int mlx_kem_export(void *vkey, int selection, OSSL_CALLBACK *param_cb, goto err; ret = param_cb(params, cbarg); + /* + * OSSL_PARAM_free() only wipes the secure-heap data block, + * so wipe the key material copies held in the params first. + */ + for (p = params; p->key != NULL; p++) + OPENSSL_cleanse(p->data, p->data_size); OSSL_PARAM_free(params); err: OSSL_PARAM_BLD_free(tmpl); OPENSSL_secure_clear_free(sub_arg.prvenc, prvlen); - OPENSSL_free(sub_arg.pubenc); + OPENSSL_clear_free(sub_arg.pubenc, publen); return ret; } @@ -562,12 +568,18 @@ static int mlx_kem_get_params(void *vkey, OSSL_PARAM params[]) selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; /* Extract sub-component key material */ - if (!export_sub(&sub_arg, selection, key)) - return 0; - - if ((pub != NULL && sub_arg.pubcount != 2) - || (prv != NULL && sub_arg.prvcount != 2)) + if (!export_sub(&sub_arg, selection, key) + || (pub != NULL && sub_arg.pubcount != 2) + || (prv != NULL && sub_arg.prvcount != 2)) { + /* Erase any partial key material on failure */ + if (sub_arg.pubenc != NULL) + OPENSSL_cleanse(sub_arg.pubenc, + key->minfo->pubkey_bytes + key->xinfo->pubkey_bytes); + if (sub_arg.prvenc != NULL) + OPENSSL_cleanse(sub_arg.prvenc, + key->minfo->prvkey_bytes + key->xinfo->prvkey_bytes); return 0; + } return 1; } From 54c77a1a85e0958db4ca4da26e39cab97d55160a Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Mon, 3 Aug 2026 19:28:48 +1000 Subject: [PATCH 121/189] Additional ML-DSA cleansing Reviewed-by: Tim Hudson Reviewed-by: Milan Broz MergeDate: Tue Aug 11 15:06:58 2026 (Merged from https://github.com/openssl/openssl/pull/32167) --- crypto/ml_dsa/ml_dsa_encoders.c | 3 ++ crypto/ml_dsa/ml_dsa_key.c | 14 ++++-- crypto/ml_dsa/ml_dsa_matrix.c | 6 ++- crypto/ml_dsa/ml_dsa_sample.c | 45 ++++++++++++++----- crypto/ml_dsa/ml_dsa_sign.c | 17 ++++++- crypto/ml_dsa/ml_dsa_vector.h | 2 + .../implementations/keymgmt/ml_dsa_kmgmt.c | 3 +- 7 files changed, 70 insertions(+), 20 deletions(-) diff --git a/crypto/ml_dsa/ml_dsa_encoders.c b/crypto/ml_dsa/ml_dsa_encoders.c index 00e2b1772cf94..be687f2326604 100644 --- a/crypto/ml_dsa/ml_dsa_encoders.c +++ b/crypto/ml_dsa/ml_dsa_encoders.c @@ -932,6 +932,9 @@ int ossl_ml_dsa_sig_encode(const ML_DSA_SIG *sig, const ML_DSA_PARAMS *params, ret = 1; err: WPACKET_finish(&pkt); + /* Erase any partial signature output on failure */ + if (ret == 0) + OPENSSL_cleanse(out, params->sig_len); return ret; } diff --git a/crypto/ml_dsa/ml_dsa_key.c b/crypto/ml_dsa/ml_dsa_key.c index e999b6c08d092..66e2ff2b61a02 100644 --- a/crypto/ml_dsa/ml_dsa_key.c +++ b/crypto/ml_dsa/ml_dsa_key.c @@ -346,10 +346,15 @@ static int public_from_private(const ML_DSA_KEY *key, EVP_MD_CTX *md_ctx, /* Compress t */ vector_power2_round(&t, t1, t0); - /* Zeroize secret */ - vector_zero(&s1_ntt); ret = 1; err: + /* + * The low bits of |t| are private and |s1_ntt| is secret, wipe both. + * The trailing |a_ntt| matrix is not wiped: per FIPS 204 section 3.6.3 + * the matrix A is easily computed from the public key and does not + * require any special protections. + */ + OPENSSL_cleanse(polys, (k + l) * sizeof(*polys)); OPENSSL_free(polys); return ret; } @@ -370,6 +375,7 @@ int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key) && shake_xof(md_ctx, key->shake256_md, key->pub_encoding, key->params->pk_len, key->tr, sizeof(key->tr)); + vector_zero(&t0); vector_free(&t0); EVP_MD_CTX_free(md_ctx); return ret; @@ -401,7 +407,7 @@ int ossl_ml_dsa_key_pairwise_check(const ML_DSA_KEY *key) ret = vector_equal(&t1, &key->t1) && vector_equal(&t0, &key->t0); err: EVP_MD_CTX_free(md_ctx); - OPENSSL_free(polys); + OPENSSL_clear_free(polys, 2 * k * sizeof(*polys)); return ret; } @@ -489,7 +495,7 @@ int ossl_ml_dsa_generate_key(ML_DSA_KEY *out) "explicit %s private key does not match seed", out->params->alg); } - OPENSSL_free(sk); + OPENSSL_clear_free(sk, out->params->sk_len); } return ret; } diff --git a/crypto/ml_dsa/ml_dsa_matrix.c b/crypto/ml_dsa/ml_dsa_matrix.c index c7ff59845217f..5a9811df12e02 100644 --- a/crypto/ml_dsa/ml_dsa_matrix.c +++ b/crypto/ml_dsa/ml_dsa_matrix.c @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include #include "ml_dsa_local.h" #include "ml_dsa_vector.h" #include "ml_dsa_matrix.h" @@ -25,15 +26,16 @@ void ossl_ml_dsa_matrix_mult_vector(const MATRIX *a, const VECTOR *s, { size_t i, j; POLY *poly = a->m_poly; + POLY product; vector_zero(t); for (i = 0; i < a->k; i++) { for (j = 0; j < a->l; j++) { - POLY product; - ossl_ml_dsa_poly_ntt_mult(poly++, &s->poly[j], &product); poly_add(&product, &t->poly[i], &t->poly[i]); } } + + OPENSSL_cleanse(&product, sizeof(product)); } diff --git a/crypto/ml_dsa/ml_dsa_sample.c b/crypto/ml_dsa/ml_dsa_sample.c index 6fae4c4a0de5c..66f48b584e72f 100644 --- a/crypto/ml_dsa/ml_dsa_sample.c +++ b/crypto/ml_dsa/ml_dsa_sample.c @@ -8,6 +8,7 @@ */ #include +#include #include "ml_dsa_local.h" #include "ml_dsa_vector.h" #include "ml_dsa_matrix.h" @@ -159,13 +160,14 @@ static int rej_bounded_poly(EVP_MD_CTX *h_ctx, const EVP_MD *md, COEFF_FROM_NIBBLE_FUNC *coef_from_nibble, const uint8_t *seed, size_t seed_len, POLY *out) { + int ret = 0; int j = 0; uint32_t z0, z1; uint8_t blocks[SHAKE256_BLOCKSIZE], *b, *end = blocks + sizeof(blocks); /* Instead of just squeezing 1 byte at a time, we grab a whole block */ if (!shake_xof(h_ctx, md, seed, seed_len, blocks, sizeof(blocks))) - return 0; + goto err; while (1) { for (b = blocks; b < end; b++) { @@ -173,15 +175,22 @@ static int rej_bounded_poly(EVP_MD_CTX *h_ctx, const EVP_MD *md, z1 = *b >> 4; /* high nibble of byte */ if (coef_from_nibble(z0, &out->coeff[j]) - && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) - return 1; + && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) { + ret = 1; + goto err; + } if (coef_from_nibble(z1, &out->coeff[j]) - && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) - return 1; + && ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) { + ret = 1; + goto err; + } } if (!EVP_DigestSqueeze(h_ctx, blocks, sizeof(blocks))) - return 0; + goto err; } +err: + OPENSSL_cleanse(blocks, sizeof(blocks)); + return ret; } /** @@ -205,6 +214,13 @@ int ossl_ml_dsa_matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md, uint8_t derived_seed[ML_DSA_RHO_BYTES + 2]; POLY *poly = out->m_poly; + /* + * The seeds derived below and the sampling buffers in rej_ntt_poly() are + * not cleansed: per FIPS 204 section 3.6.3 the matrix A is easily + * computed from the public key and does not require any special + * protections. + */ + /* The seed used for each matrix element is rho + column_index + row_index */ memcpy(derived_seed, rho, ML_DSA_RHO_BYTES); @@ -274,6 +290,7 @@ int ossl_ml_dsa_vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta, } ret = 1; err: + OPENSSL_cleanse(derived_seed, sizeof(derived_seed)); return ret; } @@ -284,9 +301,11 @@ int ossl_ml_dsa_poly_expand_mask(POLY *out, const uint8_t *seed, size_t seed_len { uint8_t buf[32 * 20]; size_t buf_len = 32 * (gamma1 == ML_DSA_GAMMA1_TWO_POWER_19 ? 20 : 18); - - return shake_xof(h_ctx, md, seed, seed_len, buf, buf_len) + int ret = shake_xof(h_ctx, md, seed, seed_len, buf, buf_len) && ossl_ml_dsa_poly_decode_expand_mask(out, buf, buf_len, gamma1); + + OPENSSL_cleanse(buf, sizeof(buf)); + return ret; } /* @@ -311,13 +330,14 @@ int ossl_ml_dsa_poly_sample_in_ball(POLY *out_c, const uint8_t *seed, int seed_l uint64_t signs; int offset = 8; size_t end; + int ret = 0; /* * Rather than squeeze 8 bytes followed by lots of 1 byte squeezes * the SHAKE blocksize is squeezed each time and buffered into 'block'. */ if (!shake_xof(h_ctx, md, seed, seed_len, block, sizeof(block))) - return 0; + goto err; /* * grab the first 64 bits - since tau < 64 @@ -336,7 +356,7 @@ int ossl_ml_dsa_poly_sample_in_ball(POLY *out_c, const uint8_t *seed, int seed_l if (offset == sizeof(block)) { /* squeeze another block if the bytes from block have been used */ if (!EVP_DigestSqueeze(h_ctx, block, sizeof(block))) - return 0; + goto err; offset = 0; } @@ -354,5 +374,8 @@ int ossl_ml_dsa_poly_sample_in_ball(POLY *out_c, const uint8_t *seed, int seed_l out_c->coeff[index] = mod_sub(1, 2 * (signs & 1)); signs >>= 1; /* grab the next random bit */ } - return 1; + ret = 1; +err: + OPENSSL_cleanse(block, sizeof(block)); + return ret; } diff --git a/crypto/ml_dsa/ml_dsa_sign.c b/crypto/ml_dsa/ml_dsa_sign.c index 71eccf8759635..b3f3e20d357c0 100644 --- a/crypto/ml_dsa/ml_dsa_sign.c +++ b/crypto/ml_dsa/ml_dsa_sign.c @@ -197,6 +197,7 @@ static int ml_dsa_sign_internal(const ML_DSA_KEY *priv, int msg_is_mu, EVP_MD_CTX_free(md_ctx); OPENSSL_clear_free(alloc, alloc_len); OPENSSL_cleanse(rho_prime, sizeof(rho_prime)); + OPENSSL_cleanse(c_tilde, sizeof(c_tilde)); return ret; } @@ -387,7 +388,13 @@ int ossl_ml_dsa_sign(const ML_DSA_KEY *priv, int msg_is_mu, alloced_m = m; } ret = ml_dsa_sign_internal(priv, msg_is_mu, m, m_len, rand, rand_len, sig); - OPENSSL_free(alloced_m); + /* The encoded message may contain confidential message content */ + if (m != msg) { + if (m != m_tmp) + OPENSSL_clear_free(alloced_m, m_len); + else + OPENSSL_cleanse(m_tmp, sizeof(m_tmp)); + } } if (sig_len != NULL) *sig_len = priv->params->sig_len; @@ -424,6 +431,12 @@ int ossl_ml_dsa_verify(const ML_DSA_KEY *pub, int msg_is_mu, } ret = ml_dsa_verify_internal(pub, msg_is_mu, m, m_len, sig, sig_len); - OPENSSL_free(alloced_m); + /* The encoded message may contain confidential message content */ + if (m != msg) { + if (m != m_tmp) + OPENSSL_clear_free(alloced_m, m_len); + else + OPENSSL_cleanse(m_tmp, sizeof(m_tmp)); + } return ret; } diff --git a/crypto/ml_dsa/ml_dsa_vector.h b/crypto/ml_dsa/ml_dsa_vector.h index d24bf031a292a..de97dc1b3084c 100644 --- a/crypto/ml_dsa/ml_dsa_vector.h +++ b/crypto/ml_dsa/ml_dsa_vector.h @@ -8,6 +8,7 @@ */ #include +#include #include "ml_dsa_poly.h" struct vector_st { @@ -153,6 +154,7 @@ vector_expand_mask(VECTOR *out, const uint8_t *rho_prime, size_t rho_prime_len, poly_expand_mask(out->poly + i, derived_seed, sizeof(derived_seed), gamma1, h_ctx, md); } + OPENSSL_cleanse(derived_seed, sizeof(derived_seed)); } /* Scale back previously rounded value */ diff --git a/providers/implementations/keymgmt/ml_dsa_kmgmt.c b/providers/implementations/keymgmt/ml_dsa_kmgmt.c index 8b08c3c9d0d8e..3b7b608651a3f 100644 --- a/providers/implementations/keymgmt/ml_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/ml_dsa_kmgmt.c @@ -96,6 +96,7 @@ static int ml_dsa_pairwise_test(const ML_DSA_KEY *key) err: OSSL_SELF_TEST_onend(st, ret); OSSL_SELF_TEST_free(st); + OPENSSL_cleanse(sig, sizeof(sig)); return ret; } #endif @@ -537,7 +538,7 @@ static void ml_dsa_gen_cleanup(void *genctx) if (gctx == NULL) return; - OPENSSL_cleanse(gctx->entropy, gctx->entropy_len); + OPENSSL_cleanse(gctx->entropy, sizeof(gctx->entropy)); OPENSSL_free(gctx->propq); OPENSSL_free(gctx); } From dbb7cb4a983e5329b6a8a74898815533bcedb5f8 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Mon, 3 Aug 2026 21:45:36 +1000 Subject: [PATCH 122/189] slh-dsa: cleanse temporary copies of sensitive data Erase the temporaries that hold secrets or data derived from them: WOTS+ chain secrets, Merkle tree nodes, the message digest and candidate FORS keys in sign and verify, the MGF1 seed and PRF-msg output buffers, the encoded message (which may contain confidential content), and the caller's signature buffer when signing fails part way through. Also cleanse a private key of unexpected length that ossl_slh_dsa_key_fromdata() copied into the key before rejecting it. The SHA2 hash functions kept the digest and the concatenated child nodes in local stack buffers, abandoned on every call. Erasing them per call measurably slows the innermost functions, so move them into a scratch buffer in SLH_DSA_HASH_CTX that is erased when the context is freed. The SHAKE hash functions write straight to the caller's buffer and need no scratch. The key material copies built by slh_dsa_export() were freed with OSSL_PARAM_free(), which only wipes the secure-heap data block. This branch has no OSSL_PARAM_clear_free(), so wipe the copies explicitly before freeing. The FORS roots buffer in ossl_slh_fors_pk_from_sig() was sized as if it held k * a nodes, but only one root per tree is ever written. Shrink it to k * n bytes maximum and erase only the used length. Reviewed-by: Tim Hudson Reviewed-by: Milan Broz MergeDate: Tue Aug 11 15:07:00 2026 (Merged from https://github.com/openssl/openssl/pull/32167) --- crypto/slh_dsa/slh_dsa.c | 37 +++++++++++--- crypto/slh_dsa/slh_dsa_hash_ctx.c | 3 +- crypto/slh_dsa/slh_dsa_key.c | 6 +++ crypto/slh_dsa/slh_dsa_local.h | 12 +++++ crypto/slh_dsa/slh_fors.c | 50 +++++++++++-------- crypto/slh_dsa/slh_hash.c | 36 +++++++++---- crypto/slh_dsa/slh_hypertree.c | 21 +++++--- crypto/slh_dsa/slh_wots.c | 4 ++ crypto/slh_dsa/slh_xmss.c | 27 +++++----- .../implementations/keymgmt/slh_dsa_kmgmt.c | 14 ++++-- .../implementations/signature/slh_dsa_sig.c | 2 +- 11 files changed, 147 insertions(+), 65 deletions(-) diff --git a/crypto/slh_dsa/slh_dsa.c b/crypto/slh_dsa/slh_dsa.c index 41fc494048b4b..4cf75089920a0 100644 --- a/crypto/slh_dsa/slh_dsa.c +++ b/crypto/slh_dsa/slh_dsa.c @@ -8,6 +8,7 @@ */ #include #include +#include #include #include #include "slh_dsa_local.h" @@ -122,8 +123,13 @@ static int slh_sign_internal(SLH_DSA_HASH_CTX *hctx, err: if (!WPACKET_finish(wpkt)) ret = 0; + OPENSSL_cleanse(m_digest, sizeof(m_digest)); + OPENSSL_cleanse(pk_fors, sizeof(pk_fors)); if (ret) *sig_len = sig_len_expected; + else + /* Erase any partial signature output */ + OPENSSL_cleanse(sig, sig_len_expected); return ret; } @@ -148,6 +154,7 @@ static int slh_verify_internal(SLH_DSA_HASH_CTX *hctx, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { + int ret = 0; const SLH_DSA_KEY *pub = hctx->key; SLH_HASH_FUNC_DECLARE(pub, hashf); SLH_ADRS_FUNC_DECLARE(pub, adrsf); @@ -185,7 +192,7 @@ static int slh_verify_internal(SLH_DSA_HASH_CTX *hctx, if (!hashf->H_MSG(hctx, r, pk_seed, pk_root, msg, msg_len, m_digest, sizeof(m_digest))) - return 0; + goto err; /* * Get md (the first md_len bytes of m_digest to use in @@ -195,16 +202,20 @@ static int slh_verify_internal(SLH_DSA_HASH_CTX *hctx, if (!PACKET_buf_init(m_digest_rpkt, m_digest, sizeof(m_digest)) || !PACKET_get_bytes(m_digest_rpkt, &md, md_len) || !get_tree_ids(m_digest_rpkt, params, &tree_id, &leaf_id)) - return 0; + goto err; adrsf->set_tree_address(adrs, tree_id); adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_FORS_TREE); adrsf->set_keypair_address(adrs, leaf_id); - return ossl_slh_fors_pk_from_sig(hctx, sig_rpkt, md, pk_seed, adrs, - pk_fors, sizeof(pk_fors)) + ret = ossl_slh_fors_pk_from_sig(hctx, sig_rpkt, md, pk_seed, adrs, + pk_fors, sizeof(pk_fors)) && ossl_slh_ht_verify(hctx, pk_fors, sig_rpkt, pk_seed, tree_id, leaf_id, pk_root) && PACKET_remaining(sig_rpkt) == 0; +err: + OPENSSL_cleanse(m_digest, sizeof(m_digest)); + OPENSSL_cleanse(pk_fors, sizeof(pk_fors)); + return ret; } /** @@ -292,8 +303,13 @@ int ossl_slh_dsa_sign(SLH_DSA_HASH_CTX *slh_ctx, return 0; } ret = slh_sign_internal(slh_ctx, m, m_len, sig, siglen, sigsize, add_rand); - if (m != msg && m != m_tmp) - OPENSSL_free(m); + /* The encoded message may contain confidential message content */ + if (m != msg) { + if (m != m_tmp) + OPENSSL_clear_free(m, m_len); + else + OPENSSL_cleanse(m_tmp, sizeof(m_tmp)); + } return ret; } @@ -317,8 +333,13 @@ int ossl_slh_dsa_verify(SLH_DSA_HASH_CTX *slh_ctx, return 0; ret = slh_verify_internal(slh_ctx, m, m_len, sig, sig_len); - if (m != msg && m != m_tmp) - OPENSSL_free(m); + /* The encoded message may contain confidential message content */ + if (m != msg) { + if (m != m_tmp) + OPENSSL_clear_free(m, m_len); + else + OPENSSL_cleanse(m_tmp, sizeof(m_tmp)); + } return ret; } diff --git a/crypto/slh_dsa/slh_dsa_hash_ctx.c b/crypto/slh_dsa/slh_dsa_hash_ctx.c index 9dca01acf5ffc..820b1d37b278b 100644 --- a/crypto/slh_dsa/slh_dsa_hash_ctx.c +++ b/crypto/slh_dsa/slh_dsa_hash_ctx.c @@ -109,5 +109,6 @@ void ossl_slh_dsa_hash_ctx_free(SLH_DSA_HASH_CTX *ctx) if (ctx->md_big_ctx != ctx->md_ctx) EVP_MD_CTX_free(ctx->md_big_ctx); EVP_MAC_CTX_free(ctx->hmac_ctx); - OPENSSL_free(ctx); + /* Erases the |scratch| hash intermediates */ + OPENSSL_clear_free(ctx, sizeof(*ctx)); } diff --git a/crypto/slh_dsa/slh_dsa_key.c b/crypto/slh_dsa/slh_dsa_key.c index 6d778a39f46dc..9e980bf1bfb0b 100644 --- a/crypto/slh_dsa/slh_dsa_key.c +++ b/crypto/slh_dsa/slh_dsa_key.c @@ -313,6 +313,12 @@ int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[], key->pub = p; return 1; err: + /* + * A private key of unexpected length may have been copied into |priv| + * before |has_priv| was set, in which case the reset below would not + * erase it, so cleanse unconditionally. + */ + OPENSSL_cleanse(key->priv, sizeof(key->priv)); ossl_slh_dsa_key_reset(key); return 0; } diff --git a/crypto/slh_dsa/slh_dsa_local.h b/crypto/slh_dsa/slh_dsa_local.h index 57dfc1eb13011..3327d5dd3c72e 100644 --- a/crypto/slh_dsa/slh_dsa_local.h +++ b/crypto/slh_dsa/slh_dsa_local.h @@ -45,12 +45,24 @@ * NOTE: Any changes to this structure will need updating in * ossl_slh_dsa_hash_ctx_dup(). */ +/* A SHA-512 digest plus two |n| byte node values */ +#define SLH_DSA_HASH_SCRATCH_LEN (64 + 2 * SLH_MAX_N) + struct slh_dsa_hash_ctx_st { const SLH_DSA_KEY *key; /* This key is not owned by this object */ EVP_MD_CTX *md_ctx; /* Either SHAKE OR SHA-256 */ EVP_MD_CTX *md_big_ctx; /* Either SHA-512 or points to |md_ctx| for SHA-256*/ EVP_MAC_CTX *hmac_ctx; /* required by SHA algorithms for PRFmsg() */ int hmac_digest_used; /* Used for lazy init of hmac_ctx digest */ + /* + * Working storage for the SHA2 hash function intermediates, used in + * place of local stack copies, so that potentially sensitive + * intermediate data lives in one place and is erased when this object + * is freed (FIPS 205 section 3.1). The SHAKE hash functions write + * their output directly to the caller's buffer and need no scratch. + * Not used concurrently. + */ + uint8_t scratch[SLH_DSA_HASH_SCRATCH_LEN]; }; __owur int ossl_slh_wots_pk_gen(SLH_DSA_HASH_CTX *ctx, const uint8_t *sk_seed, diff --git a/crypto/slh_dsa/slh_fors.c b/crypto/slh_dsa/slh_fors.c index 78587589db428..a4359801ba14e 100644 --- a/crypto/slh_dsa/slh_fors.c +++ b/crypto/slh_dsa/slh_fors.c @@ -17,8 +17,8 @@ /* a = 6, 8, 9, 12 or 14 - There are (2^a) merkle trees */ #define SLH_MAX_A 9 -#define SLH_MAX_K_TIMES_A (SLH_MAX_A * SLH_MAX_K) -#define SLH_MAX_ROOTS (SLH_MAX_K_TIMES_A * SLH_MAX_N) +/* The FORS public key is computed from the roots of k Merkle trees */ +#define SLH_MAX_ROOTS (SLH_MAX_K * SLH_MAX_N) static void slh_base_2b(const uint8_t *in, uint32_t b, uint32_t *out, size_t out_len); @@ -87,25 +87,25 @@ static int slh_fors_node(SLH_DSA_HASH_CTX *ctx, const uint8_t *sk_seed, if (height == 0) { /* Gets here for leaf nodes */ - if (!slh_fors_sk_gen(ctx, sk_seed, pk_seed, adrs, node_id, sk, sizeof(sk))) - return 0; - adrsf->set_tree_height(adrs, 0); - adrsf->set_tree_index(adrs, node_id); - ret = key->hash_func->F(ctx, pk_seed, adrs, sk, n, node, node_len); + if (slh_fors_sk_gen(ctx, sk_seed, pk_seed, adrs, node_id, sk, sizeof(sk))) { + adrsf->set_tree_height(adrs, 0); + adrsf->set_tree_index(adrs, node_id); + ret = key->hash_func->F(ctx, pk_seed, adrs, sk, n, node, node_len); + } OPENSSL_cleanse(sk, n); - return ret; } else { - if (!slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id, height - 1, - lnode, sizeof(rnode)) - || !slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id + 1, - height - 1, rnode, sizeof(rnode))) - return 0; - adrsf->set_tree_height(adrs, height); - adrsf->set_tree_index(adrs, node_id); - if (!key->hash_func->H(ctx, pk_seed, adrs, lnode, rnode, node, node_len)) - return 0; + if (slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id, height - 1, + lnode, sizeof(lnode)) + && slh_fors_node(ctx, sk_seed, pk_seed, adrs, 2 * node_id + 1, + height - 1, rnode, sizeof(rnode))) { + adrsf->set_tree_height(adrs, height); + adrsf->set_tree_index(adrs, node_id); + ret = key->hash_func->H(ctx, pk_seed, adrs, lnode, rnode, node, node_len); + } + OPENSSL_cleanse(lnode, sizeof(lnode)); + OPENSSL_cleanse(rnode, sizeof(rnode)); } - return 1; + return ret; } /** @@ -132,6 +132,7 @@ int ossl_slh_fors_sign(SLH_DSA_HASH_CTX *ctx, const uint8_t *md, const uint8_t *sk_seed, const uint8_t *pk_seed, uint8_t *adrs, WPACKET *sig_wpkt) { + int ret = 0; const SLH_DSA_KEY *key = ctx->key; uint32_t tree_id, layer, s, tree_offset; uint32_t ids[SLH_MAX_K]; @@ -165,7 +166,7 @@ int ossl_slh_fors_sign(SLH_DSA_HASH_CTX *ctx, const uint8_t *md, if (!slh_fors_sk_gen(ctx, sk_seed, pk_seed, adrs, node_id + tree_id_times_two_power_a, out, sizeof(out)) || !WPACKET_memcpy(sig_wpkt, out, n)) - return 0; + goto err; /* * Traverse from the bottom of the tree (layer = 0) @@ -178,15 +179,18 @@ int ossl_slh_fors_sign(SLH_DSA_HASH_CTX *ctx, const uint8_t *md, s = node_id ^ 1; /* XOR gets the index of the other child in a binary tree */ if (!slh_fors_node(ctx, sk_seed, pk_seed, adrs, s + tree_offset, layer, out, sizeof(out))) - return 0; + goto err; node_id >>= 1; /* Get the parent node id */ tree_offset >>= 1; /* Each layer up has half as many nodes */ if (!WPACKET_memcpy(sig_wpkt, out, n)) - return 0; + goto err; } tree_id_times_two_power_a += two_power_a; } - return 1; + ret = 1; +err: + OPENSSL_cleanse(out, sizeof(out)); + return ret; } /** @@ -288,6 +292,8 @@ int ossl_slh_fors_pk_from_sig(SLH_DSA_HASH_CTX *ctx, PACKET *fors_sig_rpkt, err: if (!WPACKET_finish(wroot_pkt)) ret = 0; + /* At most one |n| byte root per tree was written */ + OPENSSL_cleanse(roots, k * n); return ret; } diff --git a/crypto/slh_dsa/slh_hash.c b/crypto/slh_dsa/slh_hash.c index bd112f1cb0dba..d05e431e3693b 100644 --- a/crypto/slh_dsa/slh_hash.c +++ b/crypto/slh_dsa/slh_hash.c @@ -92,12 +92,15 @@ slh_prf_msg_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *sk_prf, const uint8_t *opt_rand, const uint8_t *msg, size_t msg_len, WPACKET *pkt) { + int ret; unsigned char out[SLH_MAX_N]; const SLH_DSA_PARAMS *params = ctx->key->params; size_t n = params->n; - return xof_digest_3(ctx->md_ctx, sk_prf, n, opt_rand, n, msg, msg_len, out, n) + ret = xof_digest_3(ctx->md_ctx, sk_prf, n, opt_rand, n, msg, msg_len, out, n) && WPACKET_memcpy(pkt, out, n); + OPENSSL_cleanse(out, sizeof(out)); + return ret; } static int @@ -151,6 +154,7 @@ slh_hmsg_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed, const uint8_t *pk_root, const uint8_t *msg, size_t msg_len, uint8_t *out, size_t out_len) { + int ret; const SLH_DSA_PARAMS *params = hctx->key->params; size_t m = params->m; size_t n = params->n; @@ -163,9 +167,11 @@ slh_hmsg_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed, memcpy(seed, r, n); memcpy(seed + n, pk_seed, n); - return digest_4(hctx->md_big_ctx, r, n, pk_seed, n, pk_root, n, msg, msg_len, - seed + 2 * n) + ret = digest_4(hctx->md_big_ctx, r, n, pk_seed, n, pk_root, n, msg, msg_len, + seed + 2 * n) && (PKCS1_MGF1(out, m, seed, seed_len, hctx->key->md_big) == 0); + OPENSSL_cleanse(seed, sizeof(seed)); + return ret; } static int @@ -205,16 +211,23 @@ slh_prf_msg_sha2(SLH_DSA_HASH_CTX *hctx, && EVP_MAC_update(mctx, msg, msg_len) == 1 && EVP_MAC_final(mctx, mac, NULL, sizeof(mac)) == 1 && WPACKET_memcpy(pkt, mac, n); /* Truncate output to n bytes */ + OPENSSL_cleanse(mac, sizeof(mac)); return ret; } +/* + * The |digest| scratch storage in the hash context is used in place of a + * local stack buffer, and is erased when the hash context is freed + * (FIPS 205 section 3.1). On the PRF path it holds a derived chain secret. + */ static ossl_inline int -do_hash(EVP_MD_CTX *ctx, size_t n, const uint8_t *pk_seed, const uint8_t *adrs, +do_hash(SLH_DSA_HASH_CTX *hctx, EVP_MD_CTX *ctx, size_t n, + const uint8_t *pk_seed, const uint8_t *adrs, const uint8_t *m, size_t m_len, size_t b, uint8_t *out, size_t out_len) { int ret; uint8_t zeros[128] = { 0 }; - uint8_t digest[MAX_DIGEST_SIZE]; + uint8_t *digest = hctx->scratch; ret = digest_4(ctx, pk_seed, n, zeros, b - n, adrs, SLH_ADRSC_SIZE, m, m_len, digest); @@ -230,7 +243,7 @@ slh_prf_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, { size_t n = hctx->key->params->n; - return do_hash(hctx->md_ctx, n, pk_seed, adrs, sk_seed, n, + return do_hash(hctx, hctx->md_ctx, n, pk_seed, adrs, sk_seed, n, OSSL_SLH_DSA_SHA2_NUM_ZEROS_H_AND_T_BOUND1, out, out_len); } @@ -238,21 +251,22 @@ static int slh_f_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs, const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len) { - return do_hash(hctx->md_ctx, hctx->key->params->n, pk_seed, adrs, m1, m1_len, - OSSL_SLH_DSA_SHA2_NUM_ZEROS_H_AND_T_BOUND1, out, out_len); + return do_hash(hctx, hctx->md_ctx, hctx->key->params->n, pk_seed, adrs, + m1, m1_len, OSSL_SLH_DSA_SHA2_NUM_ZEROS_H_AND_T_BOUND1, out, out_len); } static int slh_h_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs, const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len) { - uint8_t m[SLH_MAX_N * 2]; + /* The concatenated children go in the scratch after the digest */ + uint8_t *m = hctx->scratch + MAX_DIGEST_SIZE; const SLH_DSA_PARAMS *prms = hctx->key->params; size_t n = prms->n; memcpy(m, m1, n); memcpy(m + n, m2, n); - return do_hash(hctx->md_big_ctx, n, pk_seed, adrs, m, 2 * n, + return do_hash(hctx, hctx->md_big_ctx, n, pk_seed, adrs, m, 2 * n, prms->sha2_h_and_t_bound, out, out_len); } @@ -262,7 +276,7 @@ slh_t_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs, { const SLH_DSA_PARAMS *prms = hctx->key->params; - return do_hash(hctx->md_big_ctx, prms->n, pk_seed, adrs, ml, ml_len, + return do_hash(hctx, hctx->md_big_ctx, prms->n, pk_seed, adrs, ml, ml_len, prms->sha2_h_and_t_bound, out, out_len); } diff --git a/crypto/slh_dsa/slh_hypertree.c b/crypto/slh_dsa/slh_hypertree.c index bc352bf5bc3a2..781bddbc93a9f 100644 --- a/crypto/slh_dsa/slh_hypertree.c +++ b/crypto/slh_dsa/slh_hypertree.c @@ -8,6 +8,7 @@ */ #include +#include #include "slh_dsa_local.h" #include "slh_dsa_key.h" @@ -33,6 +34,7 @@ int ossl_slh_ht_sign(SLH_DSA_HASH_CTX *ctx, const uint8_t *pk_seed, uint64_t tree_id, uint32_t leaf_id, WPACKET *sig_wpkt) { + int ret = 0; const SLH_DSA_KEY *key = ctx->key; SLH_ADRS_FUNC_DECLARE(key, adrsf); SLH_ADRS_DECLARE(adrs); @@ -70,7 +72,7 @@ int ossl_slh_ht_sign(SLH_DSA_HASH_CTX *ctx, psig = WPACKET_get_curr(sig_wpkt); if (!ossl_slh_xmss_sign(ctx, root, sk_seed, leaf_id, pk_seed, adrs, sig_wpkt)) - return 0; + goto err; /* * On the last loop it skips getting the public key since it is not needed * to calculate another signature. If this was called it should equal @@ -79,15 +81,18 @@ int ossl_slh_ht_sign(SLH_DSA_HASH_CTX *ctx, if (layer < d - 1) { if (!PACKET_buf_init(xmss_sig_rpkt, psig, WPACKET_get_curr(sig_wpkt) - psig)) - return 0; + goto err; if (!ossl_slh_xmss_pk_from_sig(ctx, leaf_id, xmss_sig_rpkt, root, pk_seed, adrs, root, sizeof(root))) - return 0; + goto err; leaf_id = tree_id & mask; tree_id >>= hm; } } - return 1; + ret = 1; +err: + OPENSSL_cleanse(root, sizeof(root)); + return ret; } /** @@ -108,6 +113,7 @@ int ossl_slh_ht_verify(SLH_DSA_HASH_CTX *ctx, const uint8_t *msg, PACKET *sig_pk const uint8_t *pk_seed, uint64_t tree_id, uint32_t leaf_id, const uint8_t *pk_root) { + int ret = 0; const SLH_DSA_KEY *key = ctx->key; SLH_ADRS_FUNC_DECLARE(key, adrsf); SLH_ADRS_DECLARE(adrs); @@ -127,9 +133,12 @@ int ossl_slh_ht_verify(SLH_DSA_HASH_CTX *ctx, const uint8_t *msg, PACKET *sig_pk adrsf->set_tree_address(adrs, tree_id); if (!ossl_slh_xmss_pk_from_sig(ctx, leaf_id, sig_pkt, node, pk_seed, adrs, node, sizeof(node))) - return 0; + goto err; leaf_id = tree_id & mask; tree_id >>= tree_height; } - return (memcmp(node, pk_root, n) == 0); + ret = (memcmp(node, pk_root, n) == 0); +err: + OPENSSL_cleanse(node, sizeof(node)); + return ret; } diff --git a/crypto/slh_dsa/slh_wots.c b/crypto/slh_dsa/slh_wots.c index ea278fcd84121..c478f282d3639 100644 --- a/crypto/slh_dsa/slh_wots.c +++ b/crypto/slh_dsa/slh_wots.c @@ -244,6 +244,8 @@ int ossl_slh_wots_sign(SLH_DSA_HASH_CTX *ctx, const uint8_t *msg, } ret = 1; err: + OPENSSL_cleanse(sk, sizeof(sk)); + OPENSSL_cleanse(msg_and_csum_nibbles, sizeof(msg_and_csum_nibbles)); return ret; } @@ -311,5 +313,7 @@ int ossl_slh_wots_pk_from_sig(SLH_DSA_HASH_CTX *ctx, err: if (!WPACKET_finish(tmp_pkt)) ret = 0; + OPENSSL_cleanse(tmp, sizeof(tmp)); + OPENSSL_cleanse(msg_and_csum_nibbles, sizeof(msg_and_csum_nibbles)); return ret; } diff --git a/crypto/slh_dsa/slh_xmss.c b/crypto/slh_dsa/slh_xmss.c index dae036c6a2189..9d0b18608e6c9 100644 --- a/crypto/slh_dsa/slh_xmss.c +++ b/crypto/slh_dsa/slh_xmss.c @@ -8,6 +8,7 @@ */ #include +#include #include "slh_dsa_local.h" #include "slh_dsa_key.h" @@ -39,29 +40,31 @@ int ossl_slh_xmss_node(SLH_DSA_HASH_CTX *ctx, const uint8_t *sk_seed, { const SLH_DSA_KEY *key = ctx->key; SLH_ADRS_FUNC_DECLARE(key, adrsf); + int ret = 0; if (h == 0) { /* For leaf nodes generate the public key */ adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_WOTS_HASH); adrsf->set_keypair_address(adrs, node_id); - if (!ossl_slh_wots_pk_gen(ctx, sk_seed, pk_seed, adrs, + if (ossl_slh_wots_pk_gen(ctx, sk_seed, pk_seed, adrs, pk_out, pk_out_len)) - return 0; + ret = 1; } else { uint8_t lnode[SLH_MAX_N], rnode[SLH_MAX_N]; - if (!ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id, h - 1, pk_seed, adrs, + if (ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id, h - 1, pk_seed, adrs, lnode, sizeof(lnode)) - || !ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id + 1, h - 1, - pk_seed, adrs, rnode, sizeof(rnode))) - return 0; - adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_TREE); - adrsf->set_tree_height(adrs, h); - adrsf->set_tree_index(adrs, node_id); - if (!key->hash_func->H(ctx, pk_seed, adrs, lnode, rnode, pk_out, pk_out_len)) - return 0; + && ossl_slh_xmss_node(ctx, sk_seed, 2 * node_id + 1, h - 1, + pk_seed, adrs, rnode, sizeof(rnode))) { + adrsf->set_type_and_clear(adrs, SLH_ADRS_TYPE_TREE); + adrsf->set_tree_height(adrs, h); + adrsf->set_tree_index(adrs, node_id); + ret = key->hash_func->H(ctx, pk_seed, adrs, lnode, rnode, pk_out, pk_out_len); + } + OPENSSL_cleanse(lnode, sizeof(lnode)); + OPENSSL_cleanse(rnode, sizeof(rnode)); } - return 1; + return ret; } /** diff --git a/providers/implementations/keymgmt/slh_dsa_kmgmt.c b/providers/implementations/keymgmt/slh_dsa_kmgmt.c index 0edc067298054..05aa0da7ca5ed 100644 --- a/providers/implementations/keymgmt/slh_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/slh_dsa_kmgmt.c @@ -223,7 +223,7 @@ static int slh_dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, { SLH_DSA_KEY *key = keydata; OSSL_PARAM_BLD *tmpl; - OSSL_PARAM *params = NULL; + OSSL_PARAM *params = NULL, *p; int ret = 0; if (!ossl_prov_is_running() || key == NULL) @@ -244,6 +244,12 @@ static int slh_dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, goto err; ret = param_cb(params, cbarg); + /* + * OSSL_PARAM_free() only wipes the secure-heap data block, + * so wipe the key material copies held in the params first. + */ + for (p = params; p->key != NULL; p++) + OPENSSL_cleanse(p->data, p->data_size); OSSL_PARAM_free(params); err: OSSL_PARAM_BLD_free(tmpl); @@ -298,7 +304,7 @@ static int slh_dsa_fips140_pairwise_test(const SLH_DSA_KEY *key, uint8_t msg[16] = { 0 }; size_t msg_len = sizeof(msg); uint8_t *sig = NULL; - size_t sig_len; + size_t sig_len = 0; OSSL_LIB_CTX *lib_ctx; int alloc_ctx = 0; @@ -341,7 +347,7 @@ static int slh_dsa_fips140_pairwise_test(const SLH_DSA_KEY *key, err: if (alloc_ctx) ossl_slh_dsa_hash_ctx_free(ctx); - OPENSSL_free(sig); + OPENSSL_clear_free(sig, sig_len); OSSL_SELF_TEST_onend(st, ret); OSSL_SELF_TEST_free(st); return ret; @@ -426,7 +432,7 @@ static void slh_dsa_gen_cleanup(void *genctx) if (gctx == NULL) return; - OPENSSL_cleanse(gctx->entropy, gctx->entropy_len); + OPENSSL_cleanse(gctx->entropy, sizeof(gctx->entropy)); OPENSSL_free(gctx->propq); OPENSSL_free(gctx); } diff --git a/providers/implementations/signature/slh_dsa_sig.c b/providers/implementations/signature/slh_dsa_sig.c index c6d4e04c1b84d..6d43be32f4d2e 100644 --- a/providers/implementations/signature/slh_dsa_sig.c +++ b/providers/implementations/signature/slh_dsa_sig.c @@ -61,7 +61,7 @@ static void slh_dsa_freectx(void *vctx) ossl_slh_dsa_hash_ctx_free(ctx->hash_ctx); OPENSSL_free(ctx->propq); - OPENSSL_cleanse(ctx->add_random, ctx->add_random_len); + OPENSSL_cleanse(ctx->add_random, sizeof(ctx->add_random)); OPENSSL_free(ctx); } From 0f85cc6358d348576326bb0b534275425f011fcd Mon Sep 17 00:00:00 2001 From: Loganaden Velvindron Date: Tue, 28 Jul 2026 21:50:53 +0400 Subject: [PATCH 123/189] storemgmt: Validate msblob length before buffer allocation Reviewed-by: Paul Dale Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz Merge-date: Wed Aug 12 09:54:12 2026 Merged-from: https://github.com/openssl/openssl/pull/32102 (cherry picked from commit 0f5493e60b9e8ec500de5812fe28b9f564408608) --- providers/implementations/storemgmt/file_store_any2obj.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/providers/implementations/storemgmt/file_store_any2obj.c b/providers/implementations/storemgmt/file_store_any2obj.c index f5553b97da37d..8b8663d7574a2 100644 --- a/providers/implementations/storemgmt/file_store_any2obj.c +++ b/providers/implementations/storemgmt/file_store_any2obj.c @@ -191,6 +191,12 @@ static int msblob2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, ok = 0; mem_want = ossl_blob_length(bitlen, isdss, ispub); + + if (bitlen > BLOB_MAX_LENGTH) { + ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG); + goto err; + } + if (!BUF_MEM_grow(mem, mem_len + mem_want)) { ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); goto err; From 4adfa0d8ccab5424f3e01716a0981f10b3913cf9 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 10 Aug 2026 12:55:31 +0200 Subject: [PATCH 124/189] .github/workflows: remove openssl-3.1, openssl-3.2 and openssl-3.3 from CI jobs These branches are EOL, so there is no need to keep running CI jobs for them. Reviewed-by: Eugene Syromiatnikov Reviewed-by: Nikola Pajkovsky Merge-date: Wed Aug 12 10:15:26 2026 Merged-from: https://github.com/openssl/openssl/pull/32268 --- .github/workflows/coveralls.yml | 9 --------- .github/workflows/prov-compat-label.yml | 8 +------- .github/workflows/provider-compatibility.yml | 11 ++--------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml index f997726145795..b270841fa72ab 100644 --- a/.github/workflows/coveralls.yml +++ b/.github/workflows/coveralls.yml @@ -51,15 +51,6 @@ jobs: },{ "branch": "openssl-3.4", "extra_config": "no-afalgeng enable-fips enable-tfo" - }, { - "branch": "openssl-3.3", - "extra_config": "no-afalgeng enable-fips enable-tfo" - }, { - "branch": "openssl-3.2", - "extra_config": "no-afalgeng enable-fips enable-tfo" - }, { - "branch": "openssl-3.1", - "extra_config": "no-afalgeng enable-fips" }, { "branch": "openssl-3.0", "extra_config": "no-afalgeng enable-fips" diff --git a/.github/workflows/prov-compat-label.yml b/.github/workflows/prov-compat-label.yml index ec6adc5f8e6c7..a129338eac6e9 100644 --- a/.github/workflows/prov-compat-label.yml +++ b/.github/workflows/prov-compat-label.yml @@ -113,10 +113,6 @@ jobs: name: openssl-3.0, dir: branch-3.0, tgz: branch-3.0.tar.gz, - }, { - name: openssl-3.3, - dir: branch-3.3, - tgz: branch-3.3.tar.gz, }, { name: openssl-3.4, dir: branch-3.4, @@ -197,7 +193,7 @@ jobs: # Note that releases are not used as a test environment for # later providers. Problems in these situations ought to be # caught by cross branch testing before the release. - tree_a: [ branch-3.6, branch-3.5, branch-3.4, branch-3.3, branch-3.0, + tree_a: [ branch-3.6, branch-3.5, branch-3.4, branch-3.0, openssl-3.0.0, openssl-3.0.8, openssl-3.0.9, openssl-3.1.2 ] tree_b: [ PR ] include: @@ -209,8 +205,6 @@ jobs: tree_b: branch-3.5 - tree_a: PR tree_b: branch-3.4 - - tree_a: PR - tree_b: branch-3.3 - tree_a: PR tree_b: branch-3.0 steps: diff --git a/.github/workflows/provider-compatibility.yml b/.github/workflows/provider-compatibility.yml index a664b831f8669..c5546784c01af 100644 --- a/.github/workflows/provider-compatibility.yml +++ b/.github/workflows/provider-compatibility.yml @@ -117,11 +117,6 @@ jobs: dir: branch-3.0, tgz: branch-3.0.tar.gz, extra_config: "", - }, { - name: openssl-3.3, - dir: branch-3.3, - tgz: branch-3.3.tar.gz, - extra_config: "", }, { name: openssl-3.4, dir: branch-3.4, @@ -204,11 +199,9 @@ jobs: # Note that releases are not used as a test environment for # later providers. Problems in these situations ought to be # caught by cross branch testing before the release. - tree_a: [ branch-master, branch-3.6, branch-3.5, branch-3.4, branch-3.3, - branch-3.0, + tree_a: [ branch-master, branch-3.6, branch-3.5, branch-3.4, branch-3.0, openssl-3.0.0, openssl-3.0.8, openssl-3.0.9, openssl-3.1.2 ] - tree_b: [ branch-master, branch-3.6, branch-3.5, branch-3.4, branch-3.3, - branch-3.0 ] + tree_b: [ branch-master, branch-3.6, branch-3.5, branch-3.4, branch-3.0 ] steps: - name: early exit checks id: early_exit From 2dacccc943b47b8dc1ce8f7109c9852391b5a0d8 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Wed, 27 May 2026 01:02:49 +1000 Subject: [PATCH 125/189] Fix some missing close parens in signature docs Fixes: a9fc8702e072 "doc: document the OSSL_SIGNATURE_PARAM_FIPS_VERIFY_MESSAGE parameter" Reviewed-by: Eugene Syromiatnikov Reviewed-by: Bob Beck Reviewed-by: Nikola Pajkovsky MergeDate: Wed Aug 12 10:54:50 2026 (Merged from https://github.com/openssl/openssl/pull/32104) --- doc/man7/EVP_SIGNATURE-ECDSA.pod | 2 +- doc/man7/EVP_SIGNATURE-RSA.pod | 2 +- doc/man7/provider-signature.pod | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/man7/EVP_SIGNATURE-ECDSA.pod b/doc/man7/EVP_SIGNATURE-ECDSA.pod index aa1d1a8f0de93..cd9536ef2900f 100644 --- a/doc/man7/EVP_SIGNATURE-ECDSA.pod +++ b/doc/man7/EVP_SIGNATURE-ECDSA.pod @@ -89,7 +89,7 @@ EVP_PKEY_CTX_get_params(). =item "fips-indicator" (B) -=item "verify-message" (B +=item "verify-message" (B) The parameters are described in L. diff --git a/doc/man7/EVP_SIGNATURE-RSA.pod b/doc/man7/EVP_SIGNATURE-RSA.pod index 7ec9eda5c1a5c..6de51825b5d34 100644 --- a/doc/man7/EVP_SIGNATURE-RSA.pod +++ b/doc/man7/EVP_SIGNATURE-RSA.pod @@ -167,7 +167,7 @@ EVP_PKEY_CTX_get_params(). =item "fips-indicator" (B) -=item "verify-message" (B +=item "verify-message" (B) These common parameter are described in L. diff --git a/doc/man7/provider-signature.pod b/doc/man7/provider-signature.pod index 0e25dc3d32d39..a77062632d467 100644 --- a/doc/man7/provider-signature.pod +++ b/doc/man7/provider-signature.pod @@ -588,7 +588,7 @@ A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. This may be used after calling either the sign or verify final functions. It may return 0 if either the "digest-check", "key-check", or "sign-check" are set to 0. -=item "verify-message" (B +=item "verify-message" (B) A getter that returns 1 if a signature verification operation acted on a raw message, or 0 if it verified a predigested message. A value of 0 From 08e7756c3900bcfd77a720e7b74e27d6e4ed01a9 Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Thu, 23 Jul 2026 09:38:02 +0200 Subject: [PATCH 126/189] QUIC server: limit number of pending QUIC channels/connections Currently, there is no limit for pending QUIC connections. The port default packet handler creates channel for every valid initial packet which does belong to existing channel (a.k.a. connection). The newly created channel is inserted to list of pending channels where it waits to be accepted by local application by call to SSL_accept_connection(3ossl). This change introduces a limit for pending connection. The pending queue is limited to 256 pending connections. Applications may change the limit by calling SSL_set_feature_request_uint(3ossl) on SSL server listener object with configurable value SSL_VALUE_QUIC_MAX_PENDING_CONNS. Fixes: CVE-2026-14456 Reviewed-by: Eugene Syromiatnikov Reviewed-by: Andrew Dinh Reviewed-by: Neil Horman MergeDate: Wed Aug 12 15:00:25 2026 (Merged from https://github.com/openssl/openssl/pull/32052) (cherry picked from commit 9416706d408bb84deb7cee4647bff3045d2dc7ba) (cherry picked from commit 4084152e040329ca0194c4c1750b9b46d00a5b6b) --- doc/man3/SSL_get_value_uint.pod | 20 +++++++++++++++-- include/internal/quic_port.h | 4 ++++ include/openssl/ssl.h.in | 1 + ssl/quic/quic_impl.c | 38 +++++++++++++++++++++++++++++++++ ssl/quic/quic_port.c | 16 ++++++++++++++ ssl/quic/quic_port_local.h | 1 + util/other.syms | 1 + 7 files changed, 79 insertions(+), 2 deletions(-) diff --git a/doc/man3/SSL_get_value_uint.pod b/doc/man3/SSL_get_value_uint.pod index df0ee6176b3c9..0e2fb79414e04 100644 --- a/doc/man3/SSL_get_value_uint.pod +++ b/doc/man3/SSL_get_value_uint.pod @@ -12,6 +12,7 @@ SSL_VALUE_CLASS_FEATURE_REQUEST, SSL_VALUE_CLASS_FEATURE_PEER_REQUEST, SSL_VALUE_CLASS_FEATURE_NEGOTIATED, SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL, SSL_VALUE_QUIC_STREAM_BIDI_REMOTE_AVAIL, SSL_VALUE_QUIC_STREAM_UNI_LOCAL_AVAIL, SSL_VALUE_QUIC_STREAM_UNI_REMOTE_AVAIL, SSL_VALUE_QUIC_IDLE_TIMEOUT, +SSL_VALUE_QUIC_MAX_PENDING_CONNS, SSL_VALUE_EVENT_HANDLING_MODE, SSL_VALUE_EVENT_HANDLING_MODE_INHERIT, SSL_VALUE_EVENT_HANDLING_MODE_EXPLICIT, @@ -45,6 +46,7 @@ manage negotiable features and configuration values for an SSL object #define SSL_VALUE_QUIC_STREAM_UNI_LOCAL_AVAIL #define SSL_VALUE_QUIC_STREAM_UNI_REMOTE_AVAIL #define SSL_VALUE_QUIC_IDLE_TIMEOUT + #define SSL_VALUE_QUIC_MAX_PENDING_CONNS #define SSL_VALUE_EVENT_HANDLING_MODE #define SSL_VALUE_EVENT_HANDLING_MODE_INHERIT @@ -168,6 +170,16 @@ changed. This release of OpenSSL uses a default value of 30 seconds. This default value may change between releases of OpenSSL. +=item B (listener object) + +Generic value, sets the limit on channels (connection objects) which a QUIC server can +insert into the list of pending connections. A pending connection is a connection +which the local application needs to accept (L) in order to retrieve +an SSL connection object. The connection is removed from the pending queue by a call +to L. The default limit for pending connections is 256. An INITIAL +QUIC packet, which is received by a QUIC server with a full pending connections +queue, is silently discarded. Setting the value to zero disables the limit. + =item B (connection object) Generic read-only statistical value. The number of bidirectional, @@ -335,11 +347,15 @@ time. L, L, L, L, L, L, -L, L +L, L, +L =head1 HISTORY -These functions were added in OpenSSL 3.3. +The value SSL_VALUE_QUIC_MAX_PENDING_CONNS has been added in OpenSSL 4.1 +and ported to older releases 4.0.2, 3.6.4 and 3.5.8. + +The remaining functions and values described here were all added in OpenSSL 3.3. =head1 COPYRIGHT diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 5a2c9352378bf..e9c81d9a52ae2 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -187,6 +187,10 @@ uint64_t ossl_quic_port_get_net_bio_epoch(const QUIC_PORT *port); void ossl_quic_port_raise_net_error(QUIC_PORT *port, QUIC_CHANNEL *triggering_ch); +uint64_t ossl_quic_port_get_max_pending_channels(const QUIC_PORT *port); + +void ossl_quic_port_set_max_pending_channels(QUIC_PORT *port, uint64_t max_pending_channels); + #endif #endif diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in index 99087b874ab9a..90be33cb4f176 100644 --- a/include/openssl/ssl.h.in +++ b/include/openssl/ssl.h.in @@ -2441,6 +2441,7 @@ __owur int SSL_get_conn_close_info(SSL *ssl, #define SSL_VALUE_STREAM_WRITE_BUF_SIZE 7 #define SSL_VALUE_STREAM_WRITE_BUF_USED 8 #define SSL_VALUE_STREAM_WRITE_BUF_AVAIL 9 +#define SSL_VALUE_QUIC_MAX_PENDING_CONNS 16 #define SSL_VALUE_EVENT_HANDLING_MODE_INHERIT 0 #define SSL_VALUE_EVENT_HANDLING_MODE_IMPLICIT 1 diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 801e37d410c63..afbd7b949e596 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -410,6 +410,11 @@ static int expect_quic_cs(const SSL *s, QCTX *ctx) return expect_quic_as(s, ctx, QCTX_C | QCTX_S); } +static int expect_quic_cl(const SSL *s, QCTX *ctx) +{ + return expect_quic_as(s, ctx, QCTX_C | QCTX_L); +} + static int expect_quic_csl(const SSL *s, QCTX *ctx) { return expect_quic_as(s, ctx, QCTX_C | QCTX_S | QCTX_L); @@ -3643,6 +3648,33 @@ static int qc_getset_idle_timeout(QCTX *ctx, uint32_t class_, return ret; } +QUIC_TAKES_LOCK +static int qc_getset_max_pending_channels(QCTX *ctx, uint32_t class_, + uint64_t *p_value_out, uint64_t *p_value_in) +{ + int ret = 0; + uint64_t value_out = 0; + + qctx_lock(ctx); + + if (class_ == SSL_VALUE_CLASS_GENERIC && ctx->is_listener) { + value_out = ossl_quic_port_get_max_pending_channels(ctx->ql->port); + if (p_value_in != NULL) + ossl_quic_port_set_max_pending_channels(ctx->ql->port, *p_value_in); + ret = 1; + } else { + QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS, NULL); + ret = 0; + } + + qctx_unlock(ctx); + + if (ret && p_value_out != NULL) + *p_value_out = value_out; + + return ret; +} + QUIC_TAKES_LOCK static int qc_get_stream_avail(QCTX *ctx, uint32_t class_, int is_uni, int is_remote, @@ -3778,6 +3810,8 @@ static int expect_quic_for_value(SSL *s, QCTX *ctx, uint32_t id) case SSL_VALUE_STREAM_WRITE_BUF_USED: case SSL_VALUE_STREAM_WRITE_BUF_AVAIL: return expect_quic_cs(s, ctx); + case SSL_VALUE_QUIC_MAX_PENDING_CONNS: + return expect_quic_cl(s, ctx); default: return expect_quic_conn_only(s, ctx); } @@ -3799,6 +3833,8 @@ int ossl_quic_get_value_uint(SSL *s, uint32_t class_, uint32_t id, switch (id) { case SSL_VALUE_QUIC_IDLE_TIMEOUT: return qc_getset_idle_timeout(&ctx, class_, value, NULL); + case SSL_VALUE_QUIC_MAX_PENDING_CONNS: + return qc_getset_max_pending_channels(&ctx, class_, value, NULL); case SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL: return qc_get_stream_avail(&ctx, class_, /*uni=*/0, /*remote=*/0, value); @@ -3845,6 +3881,8 @@ int ossl_quic_set_value_uint(SSL *s, uint32_t class_, uint32_t id, case SSL_VALUE_EVENT_HANDLING_MODE: return qc_getset_event_handling(&ctx, class_, NULL, &value); + case SSL_VALUE_QUIC_MAX_PENDING_CONNS: + return qc_getset_max_pending_channels(&ctx, class_, NULL, &value); default: return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 200022ac2c564..50b7cd7f5c3c0 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -93,6 +93,8 @@ typedef struct validation_token { */ #define ENCRYPTED_TOKEN_MAX_LEN (MARSHALLED_TOKEN_MAX_LEN + 16 + 12) +#define DEFAULT_MAX_PENDING_CONNS 256 + DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); DEFINE_LIST_OF_IMPL(incoming_ch, QUIC_CHANNEL); DEFINE_LIST_OF_IMPL(port, QUIC_PORT); @@ -110,6 +112,7 @@ QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) port->validate_addr = args->do_addr_validation; port->get_conn_user_ssl = args->get_conn_user_ssl; port->user_ssl_arg = args->user_ssl_arg; + port->max_pending_channels = DEFAULT_MAX_PENDING_CONNS; if (!port_init(port)) { OPENSSL_free(port); @@ -1581,6 +1584,9 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, if (hdr.type != QUIC_PKT_TYPE_INITIAL) goto undesirable; + if (port->max_pending_channels > 0 && ossl_list_incoming_ch_num(&port->incoming_channel_list) >= port->max_pending_channels) + goto undesirable; + odcid.id_len = 0; /* @@ -1760,3 +1766,13 @@ void ossl_quic_port_restore_err_state(const QUIC_PORT *port) ERR_clear_error(); OSSL_ERR_STATE_restore(port->err_state); } + +uint64_t ossl_quic_port_get_max_pending_channels(const QUIC_PORT *port) +{ + return port->max_pending_channels; +} + +void ossl_quic_port_set_max_pending_channels(QUIC_PORT *port, uint64_t max_pending_channels) +{ + port->max_pending_channels = max_pending_channels; +} diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 3bad3fc3a3aa5..cb04598db829a 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -118,6 +118,7 @@ struct quic_port_st { /* AES-256 GCM context for token encryption */ EVP_CIPHER_CTX *token_ctx; + uint64_t max_pending_channels; }; #endif diff --git a/util/other.syms b/util/other.syms index 299dd6e84d998..0bb7b92bd69bf 100644 --- a/util/other.syms +++ b/util/other.syms @@ -785,6 +785,7 @@ SSL_VALUE_CLASS_FEATURE_REQUEST define SSL_VALUE_CLASS_FEATURE_PEER_REQUEST define SSL_VALUE_CLASS_FEATURE_NEGOTIATED define SSL_VALUE_QUIC_IDLE_TIMEOUT define +SSL_VALUE_QUIC_MAX_PENDING_CONNS define SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL define SSL_VALUE_QUIC_STREAM_BIDI_REMOTE_AVAIL define SSL_VALUE_QUIC_STREAM_UNI_LOCAL_AVAIL define From 2417e4ffdd09417cab6db8fab0b7bbadf4d185a7 Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Thu, 23 Jul 2026 07:06:28 +0200 Subject: [PATCH 127/189] test/quictestlib.c: add functions to create QUIC objects on dgram bio Add the following helper functions: * create_quic_ctx_pair() - creates pair of SSL_CTX (server, client). * create_quic_conn_objects() - creates pair of SSL objects, client and listener. They both are 'connected' by BIO_dgram_pair. * create_quic_client() - creates SSL QUIC client object bound to BIO object provided by caller. Reviewed-by: Eugene Syromiatnikov Reviewed-by: Andrew Dinh Reviewed-by: Neil Horman MergeDate: Wed Aug 12 15:00:27 2026 (Merged from https://github.com/openssl/openssl/pull/32052) (cherry picked from commit f20e51341d3134bed58e6bb18475b80bfd5712ce) (cherry picked from commit 50c55eed777b1f9041256399f9cc6b3cc0c91f23) --- test/helpers/quictestlib.c | 315 +++++++++++++++++++++++++++++++++++++ test/helpers/quictestlib.h | 4 + 2 files changed, 319 insertions(+) diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index d10f4432784c3..3b487c937d4e6 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -18,6 +18,8 @@ #include "../threadstest.h" #endif #include "internal/quic_ssl.h" +#include "../../ssl/ssl_local.h" +#include "internal/ssl_unwrap.h" #include "internal/quic_wire_pkt.h" #include "internal/quic_record_tx.h" #include "internal/quic_error.h" @@ -1375,3 +1377,316 @@ int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src) return 1; } + +static const unsigned char alpn[] = { + 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' +}; + +static int select_alpn(SSL *ssl, const unsigned char **out, unsigned char *out_len, + const unsigned char *in, unsigned int in_len, void *arg) +{ + int e; + + e = SSL_select_next_proto((unsigned char **)out, out_len, alpn, sizeof(alpn), + in, in_len); + return (e == OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_ALERT_FATAL; +} + +int create_quic_ctx_pair(OSSL_LIB_CTX *libctx, SSL_CTX **c_sctx_p, SSL_CTX **s_sctx_p, + const char *certfile, const char *keyfile) +{ + int ok = 0; + SSL_CTX *c_sctx, *s_sctx; + + c_sctx = NULL; + s_sctx = NULL; + c_sctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); + if (!TEST_ptr(c_sctx)) { + TEST_info("%s SSL_CTX_new_ex(OSSL_QUIC_client_method()) failed", __func__); + goto done; + } + + s_sctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_server_method()); + if (!TEST_ptr(s_sctx)) { + TEST_info("%s SSL_CTX_new_ex(OSSL_QUIC_server_method()) failed", __func__); + goto done; + } + + ok = SSL_CTX_use_certificate_file(s_sctx, certfile, SSL_FILETYPE_PEM); + if (ok != 1) { + TEST_info("%s SSL_CTX_use_certificate_file(%s) failed", __func__, certfile); + ok = 0; + goto done; + } + + ok = SSL_CTX_use_PrivateKey_file(s_sctx, keyfile, SSL_FILETYPE_PEM); + if (ok != 1) { + TEST_info("%s SSL_CTX_use_PrivateKey_file(%s) failed", __func__, keyfile); + ok = 0; + goto done; + } + SSL_CTX_set_alpn_select_cb(s_sctx, select_alpn, NULL); + + *c_sctx_p = c_sctx; + c_sctx = NULL; + *s_sctx_p = s_sctx; + s_sctx = NULL; + +done: + SSL_CTX_free(c_sctx); + SSL_CTX_free(s_sctx); + + return ok; +} + +static int create_dgram_pair(BIO **c_bio_p, BIO **s_bio_p) +{ + BIO *c_bio, *s_bio; + BIO_ADDR *localaddr = NULL; + struct in_addr ina; + int bio_flags = 0; + int ok; + + ina.s_addr = htonl(0x7f000001); + bio_flags |= BIO_DGRAM_CAP_HANDLES_DST_ADDR + | BIO_DGRAM_CAP_HANDLES_SRC_ADDR + | BIO_DGRAM_CAP_PROVIDES_DST_ADDR + | BIO_DGRAM_CAP_PROVIDES_SRC_ADDR; + + c_bio = NULL; + s_bio = NULL; + ok = BIO_new_bio_dgram_pair(&c_bio, 1500, &s_bio, 1500); + if (ok == 0) { + TEST_info("%s BIO_new_bio_dgram_pair() error", __func__); + goto done; + } + + ok = BIO_dgram_set_caps(c_bio, bio_flags); + if (ok == 0) { + TEST_info("%s BIO_dgram_set_caps(c_bio, bio_flags) failed", __func__); + goto done; + } + + ok = BIO_dgram_set_caps(s_bio, bio_flags); + if (ok == 0) { + TEST_info("%s BIO_dgram_set_caps(s_bio, bio_flags) failed", __func__); + goto done; + } + + ok = BIO_dgram_set_mtu(c_bio, 1500); + if (ok == 0) { + TEST_info("%s BIO_dgram_set_mtu(c_bio) error", __func__); + goto done; + } + + ok = BIO_dgram_set_mtu(s_bio, 1500); + if (ok == 0) { + TEST_info("%s BIO_dgram_set_mtu(s_bio) error", __func__); + goto done; + } + + localaddr = BIO_ADDR_new(); + if (!TEST_ptr(localaddr)) { + TEST_info("%s BIO_ADDR_new() error", __func__); + goto done; + } + ok = BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina), htons(4080)); + if (ok == 0) { + TEST_info("%s BIO_ADDR_rawmake(4080) error", __func__); + goto done; + } + ok = BIO_dgram_set0_local_addr(c_bio, localaddr); + if (ok != 1) { + TEST_info("%s BIO_dgram_set0_local_addr(c_bio)", __func__); + ok = 0; + goto done; + } + + localaddr = BIO_ADDR_new(); + if (!TEST_ptr(localaddr)) { + TEST_info("%s BIO_ADDR_new() error", __func__); + goto done; + } + ok = BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina), htons(8040)); + if (ok == 0) { + TEST_info("%s BIO_ADDR_rawmake(8040) error", __func__); + goto done; + } + ok = BIO_dgram_set0_local_addr(s_bio, localaddr); + if (ok != 1) { + TEST_info("%s BIO_dgram_set0_local_addr(c_bio)", __func__); + ok = 0; + goto done; + } + localaddr = NULL; + + ok = BIO_dgram_set_local_addr_enable(c_bio, 1); + if (ok == 0) { + TEST_info("%s BIO_dgram_set_local_addr_enable(c_bio)", __func__); + goto done; + } + + ok = BIO_dgram_set_local_addr_enable(s_bio, 1); + if (ok == 0) { + TEST_info("%s BIO_dgram_set_local_addr_enable(s_bio)", __func__); + goto done; + } + + *c_bio_p = c_bio; + c_bio = NULL; + *s_bio_p = s_bio; + s_bio = NULL; + +done: + BIO_free(c_bio); + BIO_free(s_bio); + BIO_ADDR_free(localaddr); + + return ok; +} + +static int init_client(SSL *c_ssl) +{ + BIO_ADDR *peer_addr = NULL; + struct in_addr ina; + int ok = 0; + SSL_CONNECTION *sc; + + ina.s_addr = htonl(0x7f000001); + + ok = SSL_set_tlsext_host_name(c_ssl, "localhost"); + if (ok == 0) { + TEST_info("%s SSL_set_tlsext_host_name()", __func__); + goto done; + } + + sc = SSL_CONNECTION_FROM_SSL(c_ssl); + if (sc == NULL || !X509_VERIFY_PARAM_set1_host(sc->param, "localhost", 0)) { + ok = 0; + TEST_info("%s SSL_set1_dnsname()", __func__); + goto done; + } + + ok = SSL_set_alpn_protos(c_ssl, alpn, sizeof(alpn)); + if (ok != 0) { + TEST_info("%s SSL_set_alpn_protos() failed", __func__); + ok = 0; + goto done; + } + + ok = SSL_set_blocking_mode(c_ssl, 0); + if (ok == 0) { + TEST_info("%s SSL_set_block_mode() failed", __func__); + goto done; + } + + peer_addr = BIO_ADDR_new(); + if (!TEST_ptr(peer_addr)) { + TEST_info("%s BIO_ADDR_new() failed", __func__); + goto done; + } + ok = BIO_ADDR_rawmake(peer_addr, AF_INET, &ina, sizeof(ina), htons(8040)); + if (ok == 0) { + TEST_info("%s BIO_ADDR_rawmake() failed", __func__); + goto done; + } + ok = SSL_set1_initial_peer_addr(c_ssl, peer_addr); + if (ok == 0) { + TEST_info("%s SSL_set1_initial_peer_addr() failed", __func__); + goto done; + } + +done: + BIO_ADDR_free(peer_addr); + + return ok; +} + +int create_quic_conn_objects(SSL_CTX *c_sctx, SSL_CTX *s_sctx, SSL **c_ssl_p, SSL **s_ssl_p) +{ + BIO *c_bio = NULL, *s_bio = NULL; + SSL *c_ssl = NULL, *s_ssl = NULL; + int ok; + + ok = create_dgram_pair(&c_bio, &s_bio); + if (ok == 0) + goto done; + + c_ssl = SSL_new(c_sctx); + if (!TEST_ptr(c_ssl)) { + TEST_info("%s SSL_new(c_sctx) failed", __func__); + ok = 0; + goto done; + } + + ok = init_client(c_ssl); + if (ok == 0) + goto done; + + s_ssl = SSL_new_listener(s_sctx, 0); + if (!TEST_ptr(s_ssl)) { + TEST_info("%s SSL_new_listener() failed", __func__); + ok = 0; + goto done; + } + + SSL_set_bio(c_ssl, c_bio, c_bio); + SSL_set_bio(s_ssl, s_bio, s_bio); + c_bio = NULL; + s_bio = NULL; + + ok = SSL_set_blocking_mode(s_ssl, 0); + if (ok == 0) { + TEST_info("%s SSL_set_blocking_mode() failed", __func__); + ok = 0; + goto done; + } + + *c_ssl_p = c_ssl; + c_ssl = NULL; + *s_ssl_p = s_ssl; + s_ssl = NULL; + +done: + BIO_free(c_bio); + BIO_free(s_bio); + SSL_free(c_ssl); + SSL_free(s_ssl); + + return ok; +} + +SSL *create_quic_client(SSL_CTX *c_sctx, BIO *c_bio) +{ + SSL *c_ssl; + + if (!TEST_ptr(c_bio)) + return NULL; + + c_ssl = SSL_new(c_sctx); + if (!TEST_ptr(c_ssl)) { + TEST_info("%s SSL_new(c_sctx) failed", __func__); + return NULL; + } + + if (BIO_up_ref(c_bio) == 0) { + TEST_info("%s BIO_up_ref() failed)", __func__); + goto error; + } + SSL_set_bio(c_ssl, c_bio, c_bio); + + if (init_client(c_ssl) == 0) + goto error; + + if (SSL_set_blocking_mode(c_ssl, 0) == 0) { + TEST_info("%s SSL_set_blocking_mode() failed", __func__); + goto error; + } + + return c_ssl; + +error: + SSL_free(c_ssl); + + return NULL; +} diff --git a/test/helpers/quictestlib.h b/test/helpers/quictestlib.h index 63c77f90b78be..a60d40ffe3c14 100644 --- a/test/helpers/quictestlib.h +++ b/test/helpers/quictestlib.h @@ -289,3 +289,7 @@ const BIO_METHOD *bio_f_pkt_split_dgram_filter(void); /* Free the BIO filter method object */ void bio_f_pkt_split_dgram_filter_free(void); + +int create_quic_ctx_pair(OSSL_LIB_CTX *libctx, SSL_CTX **c_sctx_p, SSL_CTX **s_sctx_p, const char *certfile, const char *keyfile); +int create_quic_conn_objects(SSL_CTX *c_sctx, SSL_CTX *s_ctx, SSL **c_ssl_p, SSL **s_ssl_p); +SSL *create_quic_client(SSL_CTX *c_sctx, BIO *c_bio); From b05a190fe598cc1deb6d6e314ab8d1c4dd2d4436 Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Thu, 23 Jul 2026 09:51:41 +0200 Subject: [PATCH 128/189] test/quicapitest.c: add test for pending connections limit enforcement This is a regression test for CVE-2026-14456. Reviewed-by: Eugene Syromiatnikov Reviewed-by: Andrew Dinh Reviewed-by: Neil Horman MergeDate: Wed Aug 12 15:00:30 2026 (Merged from https://github.com/openssl/openssl/pull/32052) (cherry picked from commit 0461a5636deca9af034db70ff017ad1138836c8c) (cherry picked from commit d446963b2622ee371df76971e5e2ddc7289839c4) --- include/internal/quic_ssl.h | 1 + ssl/quic/quic_impl.c | 13 ++++ test/quicapitest.c | 127 ++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h index f714d10477166..fade4d6316312 100644 --- a/include/internal/quic_ssl.h +++ b/include/internal/quic_ssl.h @@ -179,6 +179,7 @@ int ossl_quic_conn_poll_events(SSL *ssl, uint64_t events, int do_tick, int ossl_quic_get_notifier_fd(SSL *ssl); void ossl_quic_enter_blocking_section(SSL *ssl, QUIC_REACTOR_WAIT_CTX *wctx); void ossl_quic_leave_blocking_section(SSL *ssl, QUIC_REACTOR_WAIT_CTX *wctx); +QUIC_PORT *ossl_quic_listener_get_port(SSL *s); #endif diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index afbd7b949e596..13bb007fa49b4 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -5449,6 +5449,19 @@ QUIC_CHANNEL *ossl_quic_conn_get_channel(SSL *s) return ctx.qc->ch; } +QUIC_PORT *ossl_quic_listener_get_port(SSL *s) +{ + QCTX ctx; + + /* + * expect listerner only + */ + if (!expect_quic_listener(s, &ctx)) + return NULL; + + return ctx.ql->port; +} + int ossl_quic_set_diag_title(SSL_CTX *ctx, const char *title) { #ifndef OPENSSL_NO_QLOG diff --git a/test/quicapitest.c b/test/quicapitest.c index d40413898a6ff..f24eff4755cf4 100644 --- a/test/quicapitest.c +++ b/test/quicapitest.c @@ -21,6 +21,8 @@ #include "../ssl/ssl_local.h" #include "../ssl/quic/quic_channel_local.h" #include "internal/quic_error.h" +#include "internal/quic_ssl.h" +#include "internal/quic_port.h" static OSSL_LIB_CTX *libctx = NULL; static OSSL_PROVIDER *defctxnull = NULL; @@ -3088,6 +3090,130 @@ static int test_quic_resize_txe(void) return ret; } + +#define PENDING_LIMIT 5 +#define HANDSHAKE_STEPS 10 +static int test_pending_limit(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl_listener = NULL, *serverssl = NULL; + SSL *extra_clients[PENDING_LIMIT * 2] = { NULL }; + BIO *bio; + unsigned int i, handshake_step; + int done; + int testresult = 0; + int ok; + QUIC_PORT *port; + size_t pending_connections = 0; + + if (!TEST_true(create_quic_ctx_pair(libctx, &cctx, &sctx, cert, privkey))) + return 0; + + if (!TEST_true(create_quic_conn_objects(cctx, sctx, &clientssl, &serverssl_listener))) + goto end; + + ok = SSL_set_generic_value_uint(serverssl_listener, + SSL_VALUE_QUIC_MAX_PENDING_CONNS, PENDING_LIMIT); + if (!TEST_true(ok)) { + TEST_info("%s call to SSL_set_generic_request_uint" + "(SSL_VALUE_QUIC_MAX_PENDING_CONNS failed", + __func__); + goto end; + } + + if (!TEST_true(SSL_listen(serverssl_listener))) { + TEST_info("%s SSL_listen() failed", __func__); + goto end; + } + + port = ossl_quic_listener_get_port(serverssl_listener); + if (!TEST_ptr(port)) + goto end; + + bio = SSL_get_rbio(clientssl); + if (!TEST_ptr(bio)) + goto end; + + if (!TEST_ptr_eq(bio, SSL_get_wbio(clientssl))) + goto end; + + for (i = 0; i < OSSL_NELEM(extra_clients); i++) { + extra_clients[i] = create_quic_client(cctx, bio); + if (!TEST_ptr(extra_clients[i])) + goto end; + } + + for (i = 0; i < PENDING_LIMIT; i++) { + handshake_step = 0; + done = 0; + while (!done && handshake_step++ < HANDSHAKE_STEPS) { + /* + * connections are never accepted by the server. The SSL_connect() + * for non-blocking client returns -1 to keep connect retrying + */ + if (!TEST_int_lt(SSL_connect(extra_clients[i]), 0)) + goto end; + SSL_handle_events(serverssl_listener); + pending_connections = ossl_quic_port_get_num_incoming_channels(port); + done = (pending_connections == (i + 1)); + } + } + + if (!TEST_size_t_eq(pending_connections, PENDING_LIMIT)) + goto end; + + /* + * initiate yet another connection. The connection must not be inserted + * to pending queue. The pending_connections must be 5. + */ + for (i = PENDING_LIMIT; i < OSSL_NELEM(extra_clients); i++) { + handshake_step = 0; + done = 0; + while (!done && handshake_step++ < HANDSHAKE_STEPS) { + /* + * connections are never accepted by the server. The SSL_connect() + * for non-blocking client returns -1 to keep connect retrying + */ + if (!TEST_int_le(SSL_connect(extra_clients[i]), 0)) + goto end; + SSL_handle_events(serverssl_listener); + pending_connections = ossl_quic_port_get_num_incoming_channels(port); + done = (pending_connections == (i + 1)); + } + } + pending_connections = ossl_quic_port_get_num_incoming_channels(port); + if (!TEST_size_t_eq(pending_connections, PENDING_LIMIT)) + goto end; + + /* + * accept one connection and check the length of the queue dropped to 4. + */ + done = 0; + handshake_step = 0; + while (!done && handshake_step++ < HANDSHAKE_STEPS) { + if (!TEST_int_lt(SSL_connect(extra_clients[0]), 0)) + goto end; + SSL_handle_events(serverssl_listener); + serverssl = SSL_accept_connection(serverssl_listener, 0); + done = (serverssl != NULL); + } + pending_connections = ossl_quic_port_get_num_incoming_channels(port); + if (!TEST_size_t_eq(pending_connections, PENDING_LIMIT - 1)) + goto end; + + testresult = 1; +end: + for (i = 0; i < OSSL_NELEM(extra_clients); i++) + SSL_free(extra_clients[i]); + SSL_free(clientssl); + SSL_free(serverssl); + SSL_free(serverssl_listener); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + /***********************************************************************************/ OPT_TEST_DECLARE_USAGE("provider config certsdir datadir\n") @@ -3192,6 +3318,7 @@ int setup_tests(void) ADD_TEST(test_ssl_set_verify); ADD_TEST(test_client_hello_retry); ADD_TEST(test_quic_resize_txe); + ADD_TEST(test_pending_limit); return 1; err: From 16d0fdf8f086b06ea21e08e53f75eb30ca381ab3 Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Thu, 13 Aug 2026 15:23:33 +1000 Subject: [PATCH 129/189] Deal with riscv64 qemu-user stderr noise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the RISCV vector extensions version is not explicitly specified, qemu issues warnings to stderr when running each program. This broke some CI jobs. Pin the version to the (current) "v1.0" default. Reviewed-by: Nikola Pajkovsky Reviewed-by: Saša Nedvědický Reviewed-by: Igor Ustinov MergeDate: Thu Aug 13 06:32:59 2026 (Merged from https://github.com/openssl/openssl/pull/32345) (cherry picked from commit 31e93626b5f24b84947a954929106b4cfd5a03e7) --- .github/workflows/cross-compiles.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/cross-compiles.yml b/.github/workflows/cross-compiles.yml index 6b061aefa5233..08b25335befb2 100644 --- a/.github/workflows/cross-compiles.yml +++ b/.github/workflows/cross-compiles.yml @@ -107,6 +107,10 @@ jobs: fips: no }, { arch: riscv64-linux-gnu, + # Pin the vector spec version, otherwise qemu-user emits a + # "vector version is not specified" warning on stderr at every + # process start, which upsets tests that parse or check stderr. + qemucpu: "rv64,v=true,vext_spec=v1.0", libs: libc6-dev-riscv64-cross, target: linux64-riscv64, fips: no From 701178f81421442a622da7df23029feb8d138374 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Wed, 12 Aug 2026 20:58:04 +0200 Subject: [PATCH 130/189] test: use portable function-name macro in QUIC test helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use OPENSSL_FUNC instead of __func__ so the helper compiles in strict ANSI/C90 builds. Fixes: 0461a5636dec ("test/quicapitest.c: add test for pending connections limit enforcement") Signed-off-by: Nikola Pajkovsky Reviewed-by: Viktor Dukhovni Reviewed-by: Saša Nedvědický Reviewed-by: Milan Broz Merge-date: Thu Aug 13 07:18:30 2026 Merged-from: https://github.com/openssl/openssl/pull/32337 (cherry picked from commit 0b9dacf5ef252775a9fab0e876a05415b23651ab) (cherry picked from commit 7df38b8e2a11ce14e2c2b8257c290ae7647fd5bd) --- test/helpers/quictestlib.c | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index 3b487c937d4e6..05bae3189a15e 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -1402,26 +1402,26 @@ int create_quic_ctx_pair(OSSL_LIB_CTX *libctx, SSL_CTX **c_sctx_p, SSL_CTX **s_s s_sctx = NULL; c_sctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); if (!TEST_ptr(c_sctx)) { - TEST_info("%s SSL_CTX_new_ex(OSSL_QUIC_client_method()) failed", __func__); + TEST_info("%s SSL_CTX_new_ex(OSSL_QUIC_client_method()) failed", OPENSSL_FUNC); goto done; } s_sctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_server_method()); if (!TEST_ptr(s_sctx)) { - TEST_info("%s SSL_CTX_new_ex(OSSL_QUIC_server_method()) failed", __func__); + TEST_info("%s SSL_CTX_new_ex(OSSL_QUIC_server_method()) failed", OPENSSL_FUNC); goto done; } ok = SSL_CTX_use_certificate_file(s_sctx, certfile, SSL_FILETYPE_PEM); if (ok != 1) { - TEST_info("%s SSL_CTX_use_certificate_file(%s) failed", __func__, certfile); + TEST_info("%s SSL_CTX_use_certificate_file(%s) failed", OPENSSL_FUNC, certfile); ok = 0; goto done; } ok = SSL_CTX_use_PrivateKey_file(s_sctx, keyfile, SSL_FILETYPE_PEM); if (ok != 1) { - TEST_info("%s SSL_CTX_use_PrivateKey_file(%s) failed", __func__, keyfile); + TEST_info("%s SSL_CTX_use_PrivateKey_file(%s) failed", OPENSSL_FUNC, keyfile); ok = 0; goto done; } @@ -1457,64 +1457,64 @@ static int create_dgram_pair(BIO **c_bio_p, BIO **s_bio_p) s_bio = NULL; ok = BIO_new_bio_dgram_pair(&c_bio, 1500, &s_bio, 1500); if (ok == 0) { - TEST_info("%s BIO_new_bio_dgram_pair() error", __func__); + TEST_info("%s BIO_new_bio_dgram_pair() error", OPENSSL_FUNC); goto done; } ok = BIO_dgram_set_caps(c_bio, bio_flags); if (ok == 0) { - TEST_info("%s BIO_dgram_set_caps(c_bio, bio_flags) failed", __func__); + TEST_info("%s BIO_dgram_set_caps(c_bio, bio_flags) failed", OPENSSL_FUNC); goto done; } ok = BIO_dgram_set_caps(s_bio, bio_flags); if (ok == 0) { - TEST_info("%s BIO_dgram_set_caps(s_bio, bio_flags) failed", __func__); + TEST_info("%s BIO_dgram_set_caps(s_bio, bio_flags) failed", OPENSSL_FUNC); goto done; } ok = BIO_dgram_set_mtu(c_bio, 1500); if (ok == 0) { - TEST_info("%s BIO_dgram_set_mtu(c_bio) error", __func__); + TEST_info("%s BIO_dgram_set_mtu(c_bio) error", OPENSSL_FUNC); goto done; } ok = BIO_dgram_set_mtu(s_bio, 1500); if (ok == 0) { - TEST_info("%s BIO_dgram_set_mtu(s_bio) error", __func__); + TEST_info("%s BIO_dgram_set_mtu(s_bio) error", OPENSSL_FUNC); goto done; } localaddr = BIO_ADDR_new(); if (!TEST_ptr(localaddr)) { - TEST_info("%s BIO_ADDR_new() error", __func__); + TEST_info("%s BIO_ADDR_new() error", OPENSSL_FUNC); goto done; } ok = BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina), htons(4080)); if (ok == 0) { - TEST_info("%s BIO_ADDR_rawmake(4080) error", __func__); + TEST_info("%s BIO_ADDR_rawmake(4080) error", OPENSSL_FUNC); goto done; } ok = BIO_dgram_set0_local_addr(c_bio, localaddr); if (ok != 1) { - TEST_info("%s BIO_dgram_set0_local_addr(c_bio)", __func__); + TEST_info("%s BIO_dgram_set0_local_addr(c_bio)", OPENSSL_FUNC); ok = 0; goto done; } localaddr = BIO_ADDR_new(); if (!TEST_ptr(localaddr)) { - TEST_info("%s BIO_ADDR_new() error", __func__); + TEST_info("%s BIO_ADDR_new() error", OPENSSL_FUNC); goto done; } ok = BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina), htons(8040)); if (ok == 0) { - TEST_info("%s BIO_ADDR_rawmake(8040) error", __func__); + TEST_info("%s BIO_ADDR_rawmake(8040) error", OPENSSL_FUNC); goto done; } ok = BIO_dgram_set0_local_addr(s_bio, localaddr); if (ok != 1) { - TEST_info("%s BIO_dgram_set0_local_addr(c_bio)", __func__); + TEST_info("%s BIO_dgram_set0_local_addr(c_bio)", OPENSSL_FUNC); ok = 0; goto done; } @@ -1522,13 +1522,13 @@ static int create_dgram_pair(BIO **c_bio_p, BIO **s_bio_p) ok = BIO_dgram_set_local_addr_enable(c_bio, 1); if (ok == 0) { - TEST_info("%s BIO_dgram_set_local_addr_enable(c_bio)", __func__); + TEST_info("%s BIO_dgram_set_local_addr_enable(c_bio)", OPENSSL_FUNC); goto done; } ok = BIO_dgram_set_local_addr_enable(s_bio, 1); if (ok == 0) { - TEST_info("%s BIO_dgram_set_local_addr_enable(s_bio)", __func__); + TEST_info("%s BIO_dgram_set_local_addr_enable(s_bio)", OPENSSL_FUNC); goto done; } @@ -1556,43 +1556,43 @@ static int init_client(SSL *c_ssl) ok = SSL_set_tlsext_host_name(c_ssl, "localhost"); if (ok == 0) { - TEST_info("%s SSL_set_tlsext_host_name()", __func__); + TEST_info("%s SSL_set_tlsext_host_name()", OPENSSL_FUNC); goto done; } sc = SSL_CONNECTION_FROM_SSL(c_ssl); if (sc == NULL || !X509_VERIFY_PARAM_set1_host(sc->param, "localhost", 0)) { ok = 0; - TEST_info("%s SSL_set1_dnsname()", __func__); + TEST_info("%s SSL_set1_dnsname()", OPENSSL_FUNC); goto done; } ok = SSL_set_alpn_protos(c_ssl, alpn, sizeof(alpn)); if (ok != 0) { - TEST_info("%s SSL_set_alpn_protos() failed", __func__); + TEST_info("%s SSL_set_alpn_protos() failed", OPENSSL_FUNC); ok = 0; goto done; } ok = SSL_set_blocking_mode(c_ssl, 0); if (ok == 0) { - TEST_info("%s SSL_set_block_mode() failed", __func__); + TEST_info("%s SSL_set_block_mode() failed", OPENSSL_FUNC); goto done; } peer_addr = BIO_ADDR_new(); if (!TEST_ptr(peer_addr)) { - TEST_info("%s BIO_ADDR_new() failed", __func__); + TEST_info("%s BIO_ADDR_new() failed", OPENSSL_FUNC); goto done; } ok = BIO_ADDR_rawmake(peer_addr, AF_INET, &ina, sizeof(ina), htons(8040)); if (ok == 0) { - TEST_info("%s BIO_ADDR_rawmake() failed", __func__); + TEST_info("%s BIO_ADDR_rawmake() failed", OPENSSL_FUNC); goto done; } ok = SSL_set1_initial_peer_addr(c_ssl, peer_addr); if (ok == 0) { - TEST_info("%s SSL_set1_initial_peer_addr() failed", __func__); + TEST_info("%s SSL_set1_initial_peer_addr() failed", OPENSSL_FUNC); goto done; } @@ -1614,7 +1614,7 @@ int create_quic_conn_objects(SSL_CTX *c_sctx, SSL_CTX *s_sctx, SSL **c_ssl_p, SS c_ssl = SSL_new(c_sctx); if (!TEST_ptr(c_ssl)) { - TEST_info("%s SSL_new(c_sctx) failed", __func__); + TEST_info("%s SSL_new(c_sctx) failed", OPENSSL_FUNC); ok = 0; goto done; } @@ -1625,7 +1625,7 @@ int create_quic_conn_objects(SSL_CTX *c_sctx, SSL_CTX *s_sctx, SSL **c_ssl_p, SS s_ssl = SSL_new_listener(s_sctx, 0); if (!TEST_ptr(s_ssl)) { - TEST_info("%s SSL_new_listener() failed", __func__); + TEST_info("%s SSL_new_listener() failed", OPENSSL_FUNC); ok = 0; goto done; } @@ -1637,7 +1637,7 @@ int create_quic_conn_objects(SSL_CTX *c_sctx, SSL_CTX *s_sctx, SSL **c_ssl_p, SS ok = SSL_set_blocking_mode(s_ssl, 0); if (ok == 0) { - TEST_info("%s SSL_set_blocking_mode() failed", __func__); + TEST_info("%s SSL_set_blocking_mode() failed", OPENSSL_FUNC); ok = 0; goto done; } @@ -1665,12 +1665,12 @@ SSL *create_quic_client(SSL_CTX *c_sctx, BIO *c_bio) c_ssl = SSL_new(c_sctx); if (!TEST_ptr(c_ssl)) { - TEST_info("%s SSL_new(c_sctx) failed", __func__); + TEST_info("%s SSL_new(c_sctx) failed", OPENSSL_FUNC); return NULL; } if (BIO_up_ref(c_bio) == 0) { - TEST_info("%s BIO_up_ref() failed)", __func__); + TEST_info("%s BIO_up_ref() failed)", OPENSSL_FUNC); goto error; } SSL_set_bio(c_ssl, c_bio, c_bio); @@ -1679,7 +1679,7 @@ SSL *create_quic_client(SSL_CTX *c_sctx, BIO *c_bio) goto error; if (SSL_set_blocking_mode(c_ssl, 0) == 0) { - TEST_info("%s SSL_set_blocking_mode() failed", __func__); + TEST_info("%s SSL_set_blocking_mode() failed", OPENSSL_FUNC); goto error; } From c37abfdd65030bb11b708e43504b47fc1c96ab31 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Thu, 13 Aug 2026 11:18:56 +0200 Subject: [PATCH 131/189] test: use portable function-name macro in QUIC test helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nikola Pajkovsky Reviewed-by: Saša Nedvědický Reviewed-by: Eugene Syromiatnikov Reviewed-by: Viktor Dukhovni MergeDate: Thu Aug 13 12:15:34 2026 (Merged from https://github.com/openssl/openssl/pull/32349) --- test/quicapitest.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/quicapitest.c b/test/quicapitest.c index f24eff4755cf4..fd950772c878a 100644 --- a/test/quicapitest.c +++ b/test/quicapitest.c @@ -3090,7 +3090,6 @@ static int test_quic_resize_txe(void) return ret; } - #define PENDING_LIMIT 5 #define HANDSHAKE_STEPS 10 static int test_pending_limit(void) @@ -3117,12 +3116,12 @@ static int test_pending_limit(void) if (!TEST_true(ok)) { TEST_info("%s call to SSL_set_generic_request_uint" "(SSL_VALUE_QUIC_MAX_PENDING_CONNS failed", - __func__); + OPENSSL_FUNC); goto end; } if (!TEST_true(SSL_listen(serverssl_listener))) { - TEST_info("%s SSL_listen() failed", __func__); + TEST_info("%s SSL_listen() failed", OPENSSL_FUNC); goto end; } From 57b84ed1cf9b6c6fe8230be85869351ce2e8e839 Mon Sep 17 00:00:00 2001 From: unjuno Date: Tue, 11 Aug 2026 21:46:40 +0900 Subject: [PATCH 132/189] cms: clear temporary key buffers on failure Use OPENSSL_clear_free() with the original allocation length on the KARI, KEKRI, and PWRI failure paths. This is defense-in-depth hardening at the CMS/provider boundary. Reviewed-by: Tomas Mraz Reviewed-by: Dmitry Belyavskiy Merge-date: Fri Aug 14 06:38:29 2026 Merged-from: https://github.com/openssl/openssl/pull/32303 (cherry picked from commit de80bb12501c32bd92cfd02b56da778925da992c) --- crypto/cms/cms_env.c | 6 ++++-- crypto/cms/cms_kari.c | 6 ++++-- crypto/cms/cms_pwri.c | 5 ++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index a8ecabb64ed76..0041adcd41c11 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -928,6 +928,7 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, CMS_EncryptedContentInfo *ec; CMS_KEKRecipientInfo *kekri; unsigned char *ukey = NULL; + size_t ukey_alloc_len = 0; int ukeylen; int r = 0, wrap_nid; EVP_CIPHER *cipher = NULL; @@ -965,7 +966,8 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, goto err; } - ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); + ukey_alloc_len = (size_t)kekri->encryptedKey->length - 8; + ukey = OPENSSL_malloc(ukey_alloc_len); if (ukey == NULL) goto err; @@ -994,7 +996,7 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, err: EVP_CIPHER_free(cipher); if (!r) - OPENSSL_free(ukey); + OPENSSL_clear_free(ukey, ukey_alloc_len); EVP_CIPHER_CTX_free(ctx); return r; diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c index eb5b5d7862857..519e19bc087d1 100644 --- a/crypto/cms/cms_kari.c +++ b/crypto/cms/cms_kari.c @@ -216,6 +216,7 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, size_t keklen; int rv = 0; unsigned char *out = NULL; + size_t out_alloc_len = 0; int outlen; keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx); @@ -233,7 +234,8 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, out = OPENSSL_malloc(outlen); if (out == NULL) goto err; - if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) + out_alloc_len = (size_t)outlen; + if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, (int)inlen)) goto err; *pout = out; *poutlen = (size_t)outlen; @@ -242,7 +244,7 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, err: OPENSSL_cleanse(kek, keklen); if (!rv) - OPENSSL_free(out); + OPENSSL_clear_free(out, out_alloc_len); EVP_CIPHER_CTX_reset(kari->ctx); /* FIXME: WHY IS kari->pctx freed here? /RL */ EVP_PKEY_CTX_free(kari->pctx); diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c index 54f0eda2a2d81..de59c74fdd6e9 100644 --- a/crypto/cms/cms_pwri.c +++ b/crypto/cms/cms_pwri.c @@ -315,6 +315,7 @@ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, EVP_CIPHER *kekcipher; unsigned char *key = NULL; size_t keylen; + size_t key_alloc_len = 0; const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms); ec = ossl_cms_get0_env_enc_content(cms); @@ -391,6 +392,7 @@ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, if (key == NULL) goto err; + key_alloc_len = keylen; if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx)) goto err; @@ -400,6 +402,7 @@ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, key = OPENSSL_malloc(pwri->encryptedKey->length); if (key == NULL) goto err; + key_alloc_len = (size_t)pwri->encryptedKey->length; if (!kek_unwrap_key(key, &keylen, pwri->encryptedKey->data, pwri->encryptedKey->length, kekctx)) { @@ -419,7 +422,7 @@ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, EVP_CIPHER_CTX_free(kekctx); if (!r) - OPENSSL_free(key); + OPENSSL_clear_free(key, key_alloc_len); X509_ALGOR_free(kekalg); return r; From 0c1e2d98eab6d6409f46b67cf43fa1a4555bb5c8 Mon Sep 17 00:00:00 2001 From: Greensi7 Date: Thu, 6 Aug 2026 01:52:45 +0200 Subject: [PATCH 133/189] Fix ASN1_TYPE memory leak in asn1_multi() In asn1_gen.c `asn1_multi()` function variable allocated as `ASN1_TYPE *typ = generate_v3()` is not freed if `if (!sk_ASN1_TYPE_push(sk, typ))` branch fails. Bug found by x509v3 fuzzer MFAIL test. Example input: ``` [default] 1.2.3.4 = ASN1:SEQUENCE:items [items] value = INTEGER:1 ``` Reviewed-by: Eugene Syromiatnikov Reviewed-by: Milan Broz Reviewed-by: Nikola Pajkovsky Merge-date: Fri Aug 14 10:15:34 2026 Merged-from: https://github.com/openssl/openssl/pull/32206 --- crypto/asn1/asn1_gen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c index 1c8d3d585940a..69fbd6f89e58e 100644 --- a/crypto/asn1/asn1_gen.c +++ b/crypto/asn1/asn1_gen.c @@ -426,8 +426,11 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, depth + 1, perr); if (!typ) goto bad; - if (!sk_ASN1_TYPE_push(sk, typ)) + + if (!sk_ASN1_TYPE_push(sk, typ)) { + ASN1_TYPE_free(typ); goto bad; + } } } From f49a4e20518c06227d857166cc7a37fe3a8eefef Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Wed, 12 Aug 2026 14:36:38 +1000 Subject: [PATCH 134/189] Revised RSASVE degenerate ciphertext check. The additional ciphertext check is now applied in rsasve_recover() where it belongs, and not in the underlying RSA primitives, where it remains conditional defined(FIPS_MODULE). Reviewed-by: Milan Broz Reviewed-by: Nikola Pajkovsky MergeDate: Mon Aug 17 14:01:18 2026 (Merged from https://github.com/openssl/openssl/pull/32314) --- crypto/rsa/rsa_ossl.c | 19 ++++++++++++- providers/implementations/kem/rsa_kem.c | 38 +++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c index ba195e71874e7..3dc26c56d0667 100644 --- a/crypto/rsa/rsa_ossl.c +++ b/crypto/rsa/rsa_ossl.c @@ -160,6 +160,14 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, * See SP800-56Br2, section 7.1.1.1 * RSAEP: 1 < f < (n – 1). * (where f is the plaintext). + * + * This bound is somewhat overkill here. RSASVE.GENERATE (7.2.1.2) + * regenerates z until 1 < z < n-1, so on that path the plaintext is in + * range unconditionally. On the OAEP path the leading 0x00 octet of the + * encoding forces m < n-1 unconditionally, while m = 0 or 1 is only + * cryptographically negligible, not impossible. The check is kept to + * mirror the RSADP bound in rsa_ossl_private_decrypt() and to keep RSAEP + * faithful to 7.1.1 of the SP; nothing in the SP relies on it here. */ if (padding == RSA_NO_PADDING) { BIGNUM *nminus1 = BN_CTX_get(ctx); @@ -567,10 +575,17 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, if (BN_bin2bn(from, (int)flen, f) == NULL) goto err; +#ifdef FIPS_MODULE /* * See SP800-56Br2, section 7.1.2.1 * RSADP: 1 < f < (n – 1) * (where f is the ciphertext). + * + * Kept under FIPS_MODULE because SP 800-56B KTS-OAEP (section 9.2) also + * decrypts through RSADP and needs this bound in a FIPS build, and there + * is no KTS-OAEP-specific path to attach it to. The non-FIPS RSASVE path + * applies the same 1 < c < n-1 in rsasve_recover() + * (providers/implementations/kem/rsa_kem.c); keep the two in step. */ if (padding == RSA_NO_PADDING) { BIGNUM *nminus1 = BN_CTX_get(ctx); @@ -587,7 +602,9 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } - } else { + } else +#endif + { if (BN_ucmp(f, rsa->n) >= 0) { ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; diff --git a/providers/implementations/kem/rsa_kem.c b/providers/implementations/kem/rsa_kem.c index c74dcffc77175..47f0c80c9443d 100644 --- a/providers/implementations/kem/rsa_kem.c +++ b/providers/implementations/kem/rsa_kem.c @@ -402,6 +402,44 @@ static int rsasve_recover(PROV_RSA_CTX *prsactx, return 0; } +#ifndef FIPS_MODULE + /* + * Reject clearly degenerate ciphertexts, c in {0, 1, n-1}. + * + * SP 800-56B Rev 2, 7.1.2.1 requires RSADP to enforce 1 < c < n-1. In a + * FIPS build that bound is applied by the RSADP primitive itself (see + * crypto/rsa/rsa_ossl.c, guarded by FIPS_MODULE), where it is also needed + * for KTS-OAEP; the primitive does not apply it in a non-FIPS build, so + * enforce it here for RSASVE. Raise the same errors as the primitive so + * the behaviour matches in both builds; keep the two sites in step. + */ + { + const BIGNUM *n = RSA_get0_n(prsactx->rsa); + BIGNUM *c = BN_new(); + BIGNUM *nminus1 = BN_new(); + int reason = 0; + + if (n == NULL || c == NULL || nminus1 == NULL + || BN_bin2bn(in, (int)inlen, c) == NULL + || BN_copy(nminus1, n) == NULL + || !BN_sub_word(nminus1, 1)) { + BN_free(c); + BN_free(nminus1); + return 0; + } + if (BN_ucmp(c, BN_value_one()) <= 0) + reason = RSA_R_DATA_TOO_SMALL; + else if (BN_ucmp(c, nminus1) >= 0) + reason = RSA_R_DATA_TOO_LARGE_FOR_MODULUS; + BN_free(c); + BN_free(nminus1); + if (reason != 0) { + ERR_raise(ERR_LIB_RSA, reason); + return 0; + } + } +#endif + /* Step (3): out = RSADP((n,d), in) */ ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa, RSA_NO_PADDING); if (ret > 0 && outlen != NULL) From bfd65553fc6f0e84daf582359417746b1ecca3a1 Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Tue, 30 Jun 2026 15:03:25 +0200 Subject: [PATCH 135/189] fuzz/provider.c: check evp##_up_ref return value in collect_##evp Coverity has reported an unchecked result of an evp##_up_ref call that is checked elsewhere. Rewrite the collect routine to try to do the up_ref first, and then call free if push doesn't succeed. Resolves: https://scan5.scan.coverity.com/#/project-view/65248/10222?selectedIssue=1695451 Resolves: https://scan5.scan.coverity.com/#/project-view/65248/10222?selectedIssue=1695454 Fixes: f3b988dc2951 "Add provider fuzzer" Reviewed-by: Viktor Dukhovni Reviewed-by: Tomas Mraz Merge-date: Tue Aug 18 05:24:16 2026 Merged-from: https://github.com/openssl/openssl/pull/32348 (cherry picked from commit e15e4852b3d4776b7aeb827ba734f2ac7a0b1ff7) --- fuzz/provider.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fuzz/provider.c b/fuzz/provider.c index 8234a7e8dca64..5cdea4bd9c01b 100644 --- a/fuzz/provider.c +++ b/fuzz/provider.c @@ -32,8 +32,11 @@ { \ STACK_OF(evp) *obj_stack = stack; \ \ - if (sk_##evp##_push(obj_stack, obj) > 0) \ - evp##_up_ref(obj); \ + if (!evp##_up_ref(obj)) \ + return; \ + \ + if (sk_##evp##_push(obj_stack, obj) <= 0) \ + evp##_free(obj); \ } \ static void init_##name(OSSL_LIB_CTX *libctx) \ { \ From 917a0e3691354784914ca40c3f02eb35ce287686 Mon Sep 17 00:00:00 2001 From: Anton Arapov Date: Fri, 7 Aug 2026 11:55:37 -0700 Subject: [PATCH 136/189] doc: FIPS provider is compatible with releases from 3.0 onwards State in fips_module(7) that a FIPS provider built from a validated version can be used with libcrypto and libssl from any supported release from OpenSSL 3.0 onwards, backward and forward, including future major release series, replacing the narrower wording that limited this to the same major release series. The downloads page reference in the same paragraph now points at https://openssl-library.org/source/, which www.openssl.org/source/ redirects to. Aligns the documentation with the OpenSSL Library FIPS Module Support Policy. Assisted-by: Claude Code:claude-fable-5 Reviewed-by: Nikola Pajkovsky Reviewed-by: Tomas Mraz Reviewed-by: Richard Levitte Merge-date: Tue Aug 18 07:21:22 2026 Merged-from: https://github.com/openssl/openssl/pull/32105 (cherry picked from commit 090868518bbff01f8e9590444aed3c06a254a3b2) --- doc/man7/fips_module.pod | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/man7/fips_module.pod b/doc/man7/fips_module.pod index f32c65081e12a..6e30f5c5ca6fc 100644 --- a/doc/man7/fips_module.pod +++ b/doc/man7/fips_module.pod @@ -589,13 +589,16 @@ L /for further information. Some released versions of OpenSSL do not include a validated FIPS provider. To determine which versions have undergone the validation process, please refer to the -L. If you +L. If you require FIPS-approved functionality, it is essential to build your FIPS provider using one of the validated versions listed there. Normally, it is possible to utilize a FIPS provider constructed from one of the validated versions alongside F and F compiled from any -release within the same major release series. This flexibility enables -you to address bug fixes and CVEs that fall outside the FIPS boundary. +supported release from OpenSSL 3.0 onwards; provider compatibility is +maintained backward and forward across these releases, including future +major release series, for as long as the module remains supported. This +flexibility enables you to address bug fixes and CVEs that fall outside +the FIPS boundary. As the FIPS provider still supports non-FIPS validated algorithms, The property query C is mandatory for applications that From fbf649a568d89313504cb9cbf8227999b6113887 Mon Sep 17 00:00:00 2001 From: Anton Arapov Date: Fri, 7 Aug 2026 11:55:38 -0700 Subject: [PATCH 137/189] README-FIPS: clarify provider and library cross-version compatibility State that a FIPS provider built from any validated version may be used together with an OpenSSL library built from any supported release from OpenSSL 3.0 onwards, backward and forward, including future major release series. The downloads page references in the updated paragraph now point at https://openssl-library.org/source/, which www.openssl.org/source/ redirects to. Aligns the documentation with the OpenSSL Library FIPS Module Support Policy. Assisted-by: Claude Code:claude-fable-5 Reviewed-by: Nikola Pajkovsky Reviewed-by: Tomas Mraz Reviewed-by: Richard Levitte Merge-date: Tue Aug 18 07:21:24 2026 Merged-from: https://github.com/openssl/openssl/pull/32105 (cherry picked from commit 93a175f15adfad7f469f98cd2455cd65551e4eb6) --- README-FIPS.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README-FIPS.md b/README-FIPS.md index b31f8c65304b2..feb6892a2c47c 100644 --- a/README-FIPS.md +++ b/README-FIPS.md @@ -32,11 +32,15 @@ Installing the FIPS provider ============================ In order to be FIPS compliant you must only use FIPS validated source code. -Refer to for information related to +Refer to for information related to which versions are FIPS validated. The instructions given below build OpenSSL -just using the FIPS validated source code. Any FIPS validated version may be -used with any other openssl library. Please see -To determine which FIPS validated library version may be appropriate for you. +just using the FIPS validated source code. A FIPS provider built from any +validated version may be used together with an OpenSSL library built from any +supported release from OpenSSL 3.0 onwards; provider compatibility is +maintained backward and forward across these releases, including future major +release series, for as long as the module remains supported. Please see + +to determine which FIPS validated library version may be appropriate for you. If you want to use a validated FIPS provider, but also want to use the latest OpenSSL release to build everything else, then refer to the next section. From 9a2d8626639aeadaf75de2420dd8bf4ac6efbbd6 Mon Sep 17 00:00:00 2001 From: Abel Thomas Date: Tue, 28 Jul 2026 15:02:23 +0200 Subject: [PATCH 138/189] pkcs7: use PKCS7_get_octet_string in PKCS7_stream signed arm Direct access to `p7->d.sign->contents->d.data` skips the content-type check: if the inner eContentType is a non-standard OID the ADB sets d.other (16 bytes) instead of d.data (24 bytes), and the subsequent os->flags write lands out of bounds. Replace with `PKCS7_get_octet_string()`, which returns NULL for any type that is not `NID_pkcs7_data`, matching the guard already used by `PKCS7_ctrl()` and `PKCS7_dataDecode()`. Added a unit-test (`pkcs7_stream_non_data_test`) to validate the change. Fixes #31681 Reviewed-by: Bob Beck Reviewed-by: Jakub Zelenka Reviewed-by: Eugene Syromiatnikov Merge-date: Tue Aug 18 07:47:41 2026 Merged-from: https://github.com/openssl/openssl/pull/31722 (cherry picked from commit eedaf1c2c46b5e511a603833a65a742085c01bb2) (cherry picked from commit 56c1e4fc7625295283c22108746cb974229d9575) --- crypto/pkcs7/pk7_lib.c | 8 +++++++- test/pkcs7_test.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index 0f9e77f8eef48..2fd753e873d09 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -755,7 +755,13 @@ int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); break; } - os = p7->d.sign->contents->d.data; + + if (!PKCS7_type_is_data(p7->d.sign->contents)) { + ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + break; + } + + os = PKCS7_get_octet_string(p7->d.sign->contents); break; default: diff --git a/test/pkcs7_test.c b/test/pkcs7_test.c index 01cbf6a7493b0..8ce14f40c15de 100644 --- a/test/pkcs7_test.c +++ b/test/pkcs7_test.c @@ -459,6 +459,44 @@ static int pkcs7_stream_enveloped_signed_no_content_test(void) return ret; } +static int pkcs7_stream_non_data_test(void) +{ + int ret = 0; + PKCS7 *p7 = NULL; + BIO *sink = NULL; + BIO *bio = NULL; + + /* clang-format off */ + static const unsigned char malformed_der[] = { + 0x30, 0x32, /* SEQUENCE, 50 bytes */ + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, /* pkcs7-signedData */ + 0xa0, 0x25, /* [0] EXPLICIT, 37 bytes */ + 0x30, 0x23, /* SEQUENCE PKCS7_SIGNED, 35 bytes */ + 0x02, 0x01, 0x01, /* INTEGER version=1 */ + 0x31, 0x00, /* SET{} md_algs */ + 0x30, 0x1a, /* SEQUENCE inner PKCS7 (contents), 26 bytes */ + 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x04, /* id-ct-TSTInfo */ + 0xa0, 0x0b, /* [0] EXPLICIT, 11 bytes (makes d.other non-NULL) */ + 0x30, 0x09, /* SEQUENCE */ + 0x02, 0x01, 0x01, /* INTEGER 1 */ + 0x04, 0x04, 0xde, 0xad, 0xbe, 0xef, /* OCTET STRING */ + 0x31, 0x00, /* SET{} signer_info */ + }; + /* clang-format on */ + + const unsigned char *ptr_malformed_der = malformed_der; + + ret = TEST_ptr(p7 = d2i_PKCS7(NULL, &ptr_malformed_der, sizeof(malformed_der))) + && TEST_ptr(sink = BIO_new(BIO_s_null())) + && TEST_ptr_null(bio = BIO_new_PKCS7(sink, p7)) + && TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()), PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + + BIO_free(bio); + BIO_free(sink); + PKCS7_free(p7); + return ret; +} + int setup_tests(void) { ADD_TEST(pkcs7_issuer_and_serial_negative_idx_test); @@ -468,5 +506,6 @@ int setup_tests(void) #endif /* OPENSSL_NO_EC */ ADD_TEST(pkcs7_stream_enveloped_no_content_test); ADD_TEST(pkcs7_stream_enveloped_signed_no_content_test); + ADD_TEST(pkcs7_stream_non_data_test); return 1; } From 15cccf99fb15d14c45693b7a8d44a1791e35fa66 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 10 Aug 2026 13:44:21 -0400 Subject: [PATCH 139/189] Reject DSA parameters where N exceeds 512 Update the FFC parameter validation to explicitly reject DSA configurations where the N parameter is greater than 512. Previously, the logic accepted any N >= 256 if L >= 3072. This change enforces the maximum supported limit for N and raises an error to prevent the use of invalid or unsupported parameter combinations. This is needed because generate_q_fips186_4() allocates a `md` buffer that is at most `EVP_MAX_MD_SIZE` long (64 bytes). If N is greater than 512 then the qsize parameter passed in input to generate_q_fips186_4() will be greater than 64 causing internal operations on the buffer to overflow. This was found by Red Hat with AISLE, but deemed not a security issue because there is no reasonable way to cause an attacket to set the qbits values directly, if this ever happen it is just misuse of an API by an application. Signed-off-by: Simo Sorce Reviewed-by: Richard Levitte Reviewed-by: Tomas Mraz Reviewed-by: Dmitry Belyavskiy MergeDate: Tue Aug 18 12:41:55 2026 (Merged from https://github.com/openssl/openssl/pull/32271) (cherry picked from commit 1bf213943b0f422ced4b0c2db51f626f488f89c7) --- crypto/ffc/ffc_params_generate.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c index 969cca76f999b..612b2508cd236 100644 --- a/crypto/ffc/ffc_params_generate.c +++ b/crypto/ffc/ffc_params_generate.c @@ -77,6 +77,13 @@ static int ffc_validate_LN(size_t L, size_t N, int type, int verify) ERR_raise(ERR_LIB_DH, DH_R_BAD_FFC_PARAMETERS); #endif } else if (type == FFC_PARAM_TYPE_DSA) { + if (N > 512) { +#ifndef OPENSSL_NO_DSA + ERR_raise_data(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS, + "N is %zu, but the maximum supported N is 512", N); +#endif + return 0; + } if (L >= 3072 && N >= 256) return 128; if (L >= 2048 && N >= 224) From dba14047ed3b1b96a139d535e7d4d8b5e4ade24f Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 2 Aug 2026 14:41:30 +0900 Subject: [PATCH 140/189] doc: document thread cancellation and non-local exits Document that OpenSSL provides no general guarantee that an in-progress call can be abandoned safely through thread cancellation, forced termination, or another non-local exit. Explain indirect cancellation points, the limits of thread-local cleanup, POSIX cancellation masking, and cooperative cancellation. Clarify in OPENSSL_init_crypto(3) that automatic thread cleanup does not unwind an interrupted call. Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Tomas Mraz Reviewed-by: Andrew Dinh Merge-date: Wed Aug 19 10:32:13 2026 Merged-from: https://github.com/openssl/openssl/pull/32139 --- doc/man3/OPENSSL_init_crypto.pod | 5 ++++- doc/man7/openssl-threads.pod | 30 ++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/doc/man3/OPENSSL_init_crypto.pod b/doc/man3/OPENSSL_init_crypto.pod index 1363693c779b7..d6d9ebfb1cf63 100644 --- a/doc/man3/OPENSSL_init_crypto.pod +++ b/doc/man3/OPENSSL_init_crypto.pod @@ -273,6 +273,9 @@ with those threads. The application should either call OPENSSL_thread_stop() on each thread prior to the dlclose() call, or alternatively the original dlopen() call should use the RTLD_NODELETE flag (where available on the platform). +Thread cleanup does not unwind an OpenSSL function interrupted by cancellation +or thread exit; see L. + =head1 RETURN VALUES The functions OPENSSL_init_crypto, OPENSSL_atexit() and @@ -280,7 +283,7 @@ OPENSSL_INIT_set_config_appname() return 1 on success or 0 on error. =head1 SEE ALSO -L +L, L =head1 HISTORY diff --git a/doc/man7/openssl-threads.pod b/doc/man7/openssl-threads.pod index 7f29a327ac6a3..ca8d879c457c2 100644 --- a/doc/man7/openssl-threads.pod +++ b/doc/man7/openssl-threads.pod @@ -84,9 +84,35 @@ In this specific case, and probably for factory methods in general, it is not safe to modify the factory object after it has been used to create other objects. +=head1 THREAD CANCELLATION + +Thread safety does not imply cancellation safety. +Unless a specific function documents otherwise, OpenSSL does not guarantee +that an in-progress call can be abandoned safely by thread cancellation or +forced termination. An interruption can leave locks held, resources unreleased, +or shared state inconsistent, making later use or cleanup unsafe. + +Deferred cancellation can take effect at a cancellation point reached directly +or through a callback, BIO, provider, or other pluggable implementation. +Automatic thread-local cleanup and L, when they run, do +not unwind the interrupted call. + +Applications should act on cancellation only between OpenSSL calls. On POSIX +systems, applications using pthread cancellation should disable cancellation +with B() before entering OpenSSL and restore it only +after OpenSSL returns at a point safe for cancellation. Callbacks invoked by +OpenSSL must not re-enable it. Disabling cancellation does not make a blocking +call return on a cancellation request; applications requiring prompt +cancellation should use nonblocking operation where available. + +The same restriction applies to other non-local exits which abandon an OpenSSL +call in progress, including direct thread exit, long jumps, and language +exceptions. + =head1 SEE ALSO -CRYPTO_THREAD_run_once(3), +L, L, +L, local system threads documentation. =head1 BUGS @@ -95,7 +121,7 @@ This page is admittedly very incomplete. =head1 COPYRIGHT -Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2026 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 From 9b53f8873a96574553f169c58e2f4b6c66070be7 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 2 Aug 2026 14:41:30 +0900 Subject: [PATCH 141/189] doc: document QUIC thread cancellation consequences Describe the domain-wide consequences of interrupting QUIC API processing while synchronisation is held or notification state is registered. Clarify that SSL_poll() can leave stale registrations in multiple notifier-enabled domains, and provide cooperative cancellation and application-driven event-loop guidance. Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Tomas Mraz Reviewed-by: Andrew Dinh Merge-date: Wed Aug 19 10:32:14 2026 Merged-from: https://github.com/openssl/openssl/pull/32139 --- doc/man3/SSL_poll.pod | 20 ++++++++++++++++-- doc/man7/openssl-quic-concurrency.pod | 29 +++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/doc/man3/SSL_poll.pod b/doc/man3/SSL_poll.pod index 6047bd6750f8f..be8f8a4f786c3 100644 --- a/doc/man3/SSL_poll.pod +++ b/doc/man3/SSL_poll.pod @@ -337,6 +337,20 @@ stream SSL objects, are supported. This limitation may be revised in a future release of OpenSSL. +=head1 THREAD CANCELLATION + +A finite I limits ordinary waiting by SSL_poll(), but does not make the +call safe against thread cancellation; see L. + +Cancellation can prevent SSL_poll() from removing internal wait state. Because +an I array can span multiple QUIC domains, one interrupted call can leave +stale state in several domains and cause later calls on those domains, including +SSL_poll() with a finite timeout, to block indefinitely. + +For cooperative cancellation, use a finite timeout and check a cancellation +condition between calls; see L +for the nonblocking alternative. + =head1 RETURN VALUES SSL_poll() returns 1 on success and 0 on failure. @@ -406,7 +420,9 @@ I. =head1 SEE ALSO L, L, -L, L +L, L, +L, L, +L =head1 HISTORY @@ -421,7 +437,7 @@ event types were not present. =head1 COPYRIGHT -Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2024-2026 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/doc/man7/openssl-quic-concurrency.pod b/doc/man7/openssl-quic-concurrency.pod index e79dd2a3a2c67..7f2e54bcb35c9 100644 --- a/doc/man7/openssl-quic-concurrency.pod +++ b/doc/man7/openssl-quic-concurrency.pod @@ -150,6 +150,29 @@ default concurrency model if the application does not explicitly specify a concurrency model or disable it. This is known as Legacy Blocking Compatibility Mode, and its usage is not recommended for multi-threaded applications. +=head1 THREAD CANCELLATION + +The restrictions in L also apply to +OpenSSL QUIC APIs, including calls used in nonblocking mode. + +CCM and TACM use domain-wide synchronisation during API processing. Event +processing may perform network I/O while it is held, which can be a POSIX +cancellation point. Interruption can leave later use or teardown of the domain +unsafe. + +TACM and CCM with B also maintain internal wait state +for blocking calls. If interruption prevents cleanup of this state, later calls +on the affected domain can block indefinitely. L can maintain such +state in multiple domains in one call. + +Because most blocking QUIC functions do not provide a per-call timeout, +applications requiring prompt cooperative cancellation should use nonblocking +mode and an application-driven event loop as described in +L, waiting for the application +cancellation event alongside QUIC events. Alternatively, an application can +call L with a finite timeout and check a cancellation condition +between calls. + =head1 RECOMMENDED USAGE New applications are advised to choose a concurrency model as follows: @@ -323,13 +346,15 @@ blocking mode can be changed explicitly using L. =head1 SEE ALSO -L, L, L, +L, L, L, +L, L, +L, L, L, L, L =head1 COPYRIGHT -Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2024-2026 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 From e424472cd4372adbd9125c6f39456a186dfd73dd Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Thu, 30 Jul 2026 16:02:57 +0200 Subject: [PATCH 142/189] SSL_dup() should copy additional members currently those members are missing to be copied in SSL_dup(3ossl) - server_cert_type - client_cert_type - ct_validation_callback - retsc->ext.status_type (typically needed for OCSP) All those missing members are usually set before handshake starts, so SSL_dup() needs to copy them so behavior of duplicated SSL object is consistent with its original. Reviewed-by: Neil Horman Reviewed-by: Andrew Dinh Merge-date: Wed Aug 19 14:26:25 2026 Merged-from: https://github.com/openssl/openssl/pull/32122 (cherry picked from commit 52ee7fdf278c2316f1ddd94526f8730e014dd58f) --- doc/man3/SSL_new.pod | 8 ++++++ ssl/ssl_lib.c | 25 ++++++++++++++++++ test/sslapitest.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/doc/man3/SSL_new.pod b/doc/man3/SSL_new.pod index d01996fba1432..ae91920a5e31d 100644 --- a/doc/man3/SSL_new.pod +++ b/doc/man3/SSL_new.pod @@ -94,6 +94,14 @@ SSL_set0_client_CA_list() or similar functions =item any client certificate types configured via SSL_set1_client_certificate_types +=item type of server certificate set via L. + +=item type of client certificate set via L. + +=item certificate transparency validation callback set via L, + +=item OCSP validation set via L. + =back SSL_dup() is not supported on QUIC SSL objects and returns NULL if called on diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 05b0209a76b32..ba494f5fc0d04 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -5226,6 +5226,31 @@ SSL *SSL_dup(SSL *s) || !dup_ca_names(&retsc->client_ca_names, sc->client_ca_names)) goto err; + if (sc->server_cert_type != NULL) { + OPENSSL_free(retsc->server_cert_type); + retsc->server_cert_type = OPENSSL_memdup(sc->server_cert_type, + sc->server_cert_type_len); + if (retsc->server_cert_type == NULL) + goto err; + retsc->server_cert_type_len = sc->server_cert_type_len; + } + + if (sc->client_cert_type != NULL) { + OPENSSL_free(retsc->client_cert_type); + retsc->client_cert_type = OPENSSL_memdup(sc->client_cert_type, + sc->client_cert_type_len); + if (retsc->client_cert_type == NULL) + goto err; + retsc->client_cert_type_len = sc->client_cert_type_len; + } + +#ifndef OPENSSL_NO_CT + retsc->ct_validation_callback = sc->ct_validation_callback; + retsc->ct_validation_callback_arg = sc->ct_validation_callback_arg; +#endif + + retsc->ext.status_type = sc->ext.status_type; + return ret; err: diff --git a/test/sslapitest.c b/test/sslapitest.c index 8174eeedc627f..ece9a59c822a4 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -10821,12 +10821,29 @@ static int test_pluggable_signature(int idx) #endif #ifndef OPENSSL_NO_TLS1_2 + +#define CERT_TYPE_C "\x0" /* TLSEXT_cert_type_x509 */ +#define CERT_TYPE_S "\x2" /* TLSEXT_cert_type_rpk */ + +#ifndef OPENSSL_NO_CT +#define CB_ARG "callback arg" + +/* ARGSUSED */ +static int validation_cbk(const CT_POLICY_EVAL_CTX *ctx, + const STACK_OF(SCT) *scts, void *arg) +{ + return 1; +} +#endif + static int test_ssl_dup(void) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL, *client2ssl = NULL; int testresult = 0; BIO *rbio = NULL, *wbio = NULL; + unsigned char *ctype; + size_t ctype_len; if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), @@ -10843,6 +10860,27 @@ static int test_ssl_dup(void) || !TEST_true(SSL_set_max_proto_version(clientssl, TLS1_2_VERSION))) goto end; + if (!TEST_true( + SSL_set1_client_cert_type(clientssl, + (const unsigned char *)CERT_TYPE_C, sizeof(CERT_TYPE_C) - 1))) + goto end; + + if (!TEST_true( + SSL_set1_server_cert_type(clientssl, + (const unsigned char *)CERT_TYPE_S, sizeof(CERT_TYPE_S) - 1))) + goto end; + +#ifndef OPENSSL_NO_CT + if (!TEST_true(SSL_set_ct_validation_callback(clientssl, validation_cbk, CB_ARG))) + goto end; +#endif + +#ifndef OPENSSL_NO_OCSP + if (!TEST_true( + SSL_set_tlsext_status_type(clientssl, TLSEXT_STATUSTYPE_ocsp))) + goto end; +#endif + client2ssl = SSL_dup(clientssl); rbio = SSL_get_rbio(clientssl); if (!TEST_ptr(rbio) @@ -10869,6 +10907,28 @@ static int test_ssl_dup(void) if (!TEST_true(create_ssl_connection(serverssl, client2ssl, SSL_ERROR_NONE))) goto end; + if (!TEST_true(SSL_get0_client_cert_type(client2ssl, &ctype, &ctype_len))) + goto end; + + if (!TEST_mem_eq(ctype, ctype_len, CERT_TYPE_C, sizeof(CERT_TYPE_C) - 1)) + goto end; + + if (!TEST_true(SSL_get0_server_cert_type(client2ssl, &ctype, &ctype_len))) + goto end; + + if (!TEST_mem_eq(ctype, ctype_len, CERT_TYPE_S, sizeof(CERT_TYPE_S) - 1)) + goto end; + +#ifndef OPENSSL_NO_CT + if (!TEST_true(SSL_ct_is_enabled(client2ssl))) + goto end; +#endif + +#ifndef OPENSSL_NO_OCSP + if (!TEST_long_eq(SSL_get_tlsext_status_type(client2ssl), TLSEXT_STATUSTYPE_ocsp)) + goto end; +#endif + SSL_free(clientssl); clientssl = SSL_dup(client2ssl); if (!TEST_ptr(clientssl) From 1fff7800e55f2c2dc9c76cacea9456037c38881a Mon Sep 17 00:00:00 2001 From: YZL0v3ZZ <2055877225@qq.com> Date: Wed, 11 Mar 2026 22:54:05 +0800 Subject: [PATCH 143/189] Fix system resource leak in TerminalSocket() When establishing a terminal socket on OpenVMS, if the async I/O read operation (sys$qio) fails, the error path returns early without freeing the allocated channel via sys$dassgn. Add sys$dassgn(TerminalDeviceChan) in the sys$qio error path during creation. Also ensure dassgn executes regardless of whether sys$cancel succeeds during deletion to avoid exhausting the I/O channel quota. Reviewed-by: Nikola Pajkovsky Reviewed-by: Richard Levitte Merge-date: Wed Aug 19 15:37:03 2026 Merged-from: https://github.com/openssl/openssl/pull/30375 (cherry picked from commit ee7c64fbcd24276233d238aff1cdf9996be943cd) --- apps/lib/vms_term_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c index faceb05d01451..85e726ee452e5 100644 --- a/apps/lib/vms_term_sock.c +++ b/apps/lib/vms_term_sock.c @@ -230,6 +230,7 @@ int TerminalSocket(int FunctionCode, int *ReturnSocket) LogMessage("TerminalSocket: SYS$QIO () - %08X", status); close(TerminalSocketPair[0]); close(TerminalSocketPair[1]); + sys$dassgn(TerminalDeviceChan); return TERM_SOCK_FAILURE; } @@ -248,6 +249,7 @@ int TerminalSocket(int FunctionCode, int *ReturnSocket) LogMessage("TerminalSocket: SYS$CANCEL () - %08X", status); close(TerminalSocketPair[0]); close(TerminalSocketPair[1]); + sys$dassgn(TerminalDeviceChan); return TERM_SOCK_FAILURE; } From bdeb0cd994d915342787f117ee75044f0dc36f34 Mon Sep 17 00:00:00 2001 From: Billy Brumley Date: Tue, 4 Aug 2026 07:35:48 -0400 Subject: [PATCH 144/189] Check the tag on EVP_Cipher() finalize: Poly1305 and OCB AEADs For the affected OpenSSL built-in provider AEAD implementations, EVP_Cipher(ctx, out, NULL, 0) reaches the ccipher callback as a NULL-input terminal call. OCB and ChaCha20-Poly1305 took an early exit on an empty message, with or without AAD, and returned success without comparing an explicitly supplied tag. Consequently a corrupted tag was accepted before this change. Make these built-in callbacks perform their terminal tag operation, aligning their explicit-tag handling with the streaming Final path without defining NULL input as part of the generic EVP_Cipher() contract. AES-GCM-SIV also failed to generate a tag when Final was its first empty-message operation. Generate the tag in that case and propagate failures from the matching empty-message decrypt operation. The stable ChaCha20-Poly1305 implementation aliases Update to the one-shot cipher callback, so this backport introduces a dedicated Update callback to preserve zero-length Update as a no-op. Follow-up to #31555 Fixes #32258 Fixes CVE-2026-75803 Assisted-by: Claude:claude-opus-4-8 Assisted-by: Codex:gpt-5.6-sol (cherry picked from commit 5741d29a5f356e05262cd0936a472a9961398d53) Co-authored-by: Mounir IDRASSI Reviewed-by: Bob Beck Reviewed-by: Tomas Mraz Merge-date: Wed Aug 19 17:41:16 2026 Merged-from: https://github.com/openssl/openssl/pull/32416 --- .../ciphers/cipher_aes_gcm_siv_hw.c | 14 +++++++--- .../implementations/ciphers/cipher_aes_ocb.c | 4 +++ .../ciphers/cipher_chacha20_poly1305.c | 27 ++++++++++++++----- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c index bf3275f97b380..c1079e0e7874a 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c +++ b/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c @@ -267,11 +267,17 @@ static int aes_gcm_siv_finish(PROV_AES_GCM_SIV_CTX *ctx) { int ret = 0; - if (ctx->enc) + if (ctx->enc) { + /* Generate the tag when Final is the first empty-message operation. */ + if (ctx->generated_tag == 0 + && aes_gcm_siv_encrypt(ctx, NULL, NULL, 0) == 0) + return 0; return ctx->generated_tag; - if (!ctx->generated_tag) - aes_gcm_siv_decrypt(ctx, NULL, NULL, 0); - ret = !CRYPTO_memcmp(ctx->tag, ctx->user_tag, sizeof(ctx->tag)); + } + if (ctx->generated_tag == 0 + && aes_gcm_siv_decrypt(ctx, NULL, NULL, 0) == 0) + return 0; + ret = CRYPTO_memcmp(ctx->tag, ctx->user_tag, sizeof(ctx->tag)) == 0; ret &= ctx->have_user_tag; return ret; } diff --git a/providers/implementations/ciphers/cipher_aes_ocb.c b/providers/implementations/ciphers/cipher_aes_ocb.c index 99254cb49a882..62e5a0c1a7665 100644 --- a/providers/implementations/ciphers/cipher_aes_ocb.c +++ b/providers/implementations/ciphers/cipher_aes_ocb.c @@ -509,6 +509,10 @@ static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl, if (!ossl_prov_is_running()) return 0; + /* NULL input indicates Final, which must generate or check the tag. */ + if (in == NULL) + return aes_ocb_block_final(vctx, out, outl, outsize); + if (outsize < inl) { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); return 0; diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305.c b/providers/implementations/ciphers/cipher_chacha20_poly1305.c index 977f7000c289e..673e18702cf72 100644 --- a/providers/implementations/ciphers/cipher_chacha20_poly1305.c +++ b/providers/implementations/ciphers/cipher_chacha20_poly1305.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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 @@ -30,11 +30,11 @@ static OSSL_FUNC_cipher_get_params_fn chacha20_poly1305_get_params; static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_poly1305_get_ctx_params; static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_poly1305_set_ctx_params; static OSSL_FUNC_cipher_cipher_fn chacha20_poly1305_cipher; +static OSSL_FUNC_cipher_update_fn chacha20_poly1305_update; static OSSL_FUNC_cipher_final_fn chacha20_poly1305_final; static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_poly1305_gettable_ctx_params; static OSSL_FUNC_cipher_settable_ctx_params_fn chacha20_poly1305_settable_ctx_params; #define chacha20_poly1305_gettable_params ossl_cipher_generic_gettable_params -#define chacha20_poly1305_update chacha20_poly1305_cipher static void *chacha20_poly1305_newctx(void *provctx) { @@ -301,11 +301,6 @@ static int chacha20_poly1305_cipher(void *vctx, unsigned char *out, if (!ossl_prov_is_running()) return 0; - if (inl == 0) { - *outl = 0; - return 1; - } - if (outsize < inl) { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); return 0; @@ -317,6 +312,24 @@ static int chacha20_poly1305_cipher(void *vctx, unsigned char *out, return 1; } +static int chacha20_poly1305_update(void *vctx, unsigned char *out, + size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) +{ + /* + * A zero-length update is a no-op. Only EVP_Cipher() and Final produce or + * check the authentication tag. + */ + if (inl == 0) { + if (!ossl_prov_is_running()) + return 0; + *outl = 0; + return 1; + } + + return chacha20_poly1305_cipher(vctx, out, outl, outsize, in, inl); +} + static int chacha20_poly1305_final(void *vctx, unsigned char *out, size_t *outl, size_t outsize) { From e9fb43aee8654b492ed8a239d3f2bacf13bb9081 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 10 Aug 2026 12:44:32 +0900 Subject: [PATCH 145/189] Add tests for empty AEAD EVP_Cipher() finalization Generate an empty-message tag with the streaming path, then check that EVP_Cipher() decryption accepts the correct tag and rejects a corrupted one. Also verify that EVP_Cipher() encryption produces the same tag. Cover AES-OCB, ChaCha20-Poly1305, and AES-GCM-SIV, with and without AAD. Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Bob Beck Reviewed-by: Tomas Mraz Merge-date: Wed Aug 19 17:41:17 2026 Merged-from: https://github.com/openssl/openssl/pull/32416 --- test/evp_extra_test.c | 121 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index fb013b0c0647c..cc635ecff6ec9 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -7407,6 +7407,12 @@ static const AEAD_ONESHOT_CFG aead_oneshot_cfgs[] = { { "ChaCha20-Poly1305", 32, 12, 16, 0 } }; +static const AEAD_ONESHOT_CFG aead_oneshot_zerolen_cfgs[] = { + { "AES-128-OCB", 16, 12, 16, 0 }, + { "ChaCha20-Poly1305", 32, 12, 16, 0 }, + { "AES-128-GCM-SIV", 16, 12, 16, 0 } +}; + /* * Drive an encrypt or decrypt operation. AAD always via EVP_CipherUpdate. * Body via EVP_Cipher() when oneshot_body is non-zero, EVP_CipherUpdate @@ -7627,6 +7633,119 @@ static int test_aead_oneshot_roundtrip(int idx) return ok; } +static EVP_CIPHER_CTX *aead_oneshot_zerolen_ctx(const EVP_CIPHER *cipher, + int enc, const unsigned char *key, const unsigned char *iv, + const unsigned char *aad, size_t aad_len, + const unsigned char *tag, size_t tag_len) +{ + EVP_CIPHER_CTX *ctx = NULL; + int outl = 0; + + if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + || !TEST_true(EVP_CipherInit_ex2(ctx, cipher, key, iv, enc, NULL)) + || (aad_len > 0 + && !TEST_true(EVP_CipherUpdate(ctx, NULL, &outl, aad, + (int)aad_len))) + || (!enc + && !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + (int)tag_len, (void *)tag), + 0))) { + EVP_CIPHER_CTX_free(ctx); + return NULL; + } + return ctx; +} + +/* + * For these built-in provider implementations, a NULL-input EVP_Cipher() call + * must produce or check the empty-message tag even when no payload Update was + * made. + */ +static int test_aead_oneshot_zerolen(int idx) +{ + static const unsigned char key[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; + static const unsigned char iv[12] = { + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab + }; + static const unsigned char aad[] = "empty message context"; + const AEAD_ONESHOT_CFG *cfg = &aead_oneshot_zerolen_cfgs[idx / 2]; + int with_aad = idx % 2; + size_t aad_len = with_aad ? sizeof(aad) - 1 : 0; + EVP_CIPHER *cipher = NULL; + EVP_CIPHER_CTX *ctx_oracle = NULL, *ctx_oneshot = NULL; + EVP_CIPHER_CTX *ctx_dec = NULL, *ctx_dec_bad = NULL; + static const unsigned char empty = 0; + unsigned char out[16] = { 0 }; + unsigned char tag_oracle[16] = { 0 }; + unsigned char tag_oneshot[16] = { 0 }; + unsigned char tag_bad[16] = { 0 }; + int outl = 0, ret = 0; + + ERR_set_mark(); + cipher = EVP_CIPHER_fetch(testctx, cfg->name, testpropq); + ERR_pop_to_mark(); + if (cipher == NULL) + return TEST_skip("'%s' is not available", cfg->name); + + /* + * The explicit zero-length Update provides an oracle that also works on + * the unpatched GCM-SIV implementation, whose empty Final cannot generate + * a tag. + */ + ctx_oracle = aead_oneshot_zerolen_ctx(cipher, 1, key, iv, aad, aad_len, + NULL, cfg->taglen); + if (!TEST_ptr(ctx_oracle) + || !TEST_true(EVP_EncryptUpdate(ctx_oracle, out, &outl, &empty, 0)) + || !TEST_true(EVP_EncryptFinal_ex(ctx_oracle, out, &outl)) + || !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx_oracle, EVP_CTRL_AEAD_GET_TAG, + (int)cfg->taglen, tag_oracle), + 0)) + goto end; + + ctx_dec = aead_oneshot_zerolen_ctx(cipher, 0, key, iv, aad, aad_len, + tag_oracle, cfg->taglen); + if (!TEST_ptr(ctx_dec) + || !TEST_int_ge(EVP_Cipher(ctx_dec, out, NULL, 0), 0)) + goto end; + + memcpy(tag_bad, tag_oracle, cfg->taglen); + tag_bad[0] ^= 1; + ctx_dec_bad = aead_oneshot_zerolen_ctx(cipher, 0, key, iv, aad, aad_len, + tag_bad, cfg->taglen); + if (!TEST_ptr(ctx_dec_bad) + || !TEST_int_lt(EVP_Cipher(ctx_dec_bad, out, NULL, 0), 0)) + goto end; + + ctx_oneshot = aead_oneshot_zerolen_ctx(cipher, 1, key, iv, aad, aad_len, + NULL, cfg->taglen); + if (!TEST_ptr(ctx_oneshot) + || !TEST_int_ge(EVP_Cipher(ctx_oneshot, out, NULL, 0), 0) + || !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx_oneshot, EVP_CTRL_AEAD_GET_TAG, + (int)cfg->taglen, tag_oneshot), + 0) + || !TEST_mem_eq(tag_oneshot, cfg->taglen, + tag_oracle, cfg->taglen)) + goto end; + + ret = 1; +end: + if (!ret) + TEST_info("zero-length %s test failed (%s)", cfg->name, + with_aad ? "with AAD" : "no AAD"); + EVP_CIPHER_CTX_free(ctx_oracle); + EVP_CIPHER_CTX_free(ctx_oneshot); + EVP_CIPHER_CTX_free(ctx_dec); + EVP_CIPHER_CTX_free(ctx_dec_bad); + EVP_CIPHER_free(cipher); + return ret; +} + #ifndef OPENSSL_NO_DES static int test_EVP_CIPHER_get_type_des_ede3(void) { @@ -8101,6 +8220,8 @@ int setup_tests(void) #endif ADD_ALL_TESTS(test_aead_oneshot_roundtrip, 2 * OSSL_NELEM(aead_oneshot_cfgs)); + ADD_ALL_TESTS(test_aead_oneshot_zerolen, + 2 * OSSL_NELEM(aead_oneshot_zerolen_cfgs)); ADD_ALL_TESTS(test_rsasve_degenerate_exponent, 2); ADD_ALL_TESTS(test_rsasve_degenerate_ciphertext, 3); From 9954679e9da1274fe4e62af058c0f3a52fa020ac Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 18 Jun 2026 19:29:20 +0200 Subject: [PATCH 146/189] Fix get_cert_by_subject_ex() to gracefully handle broken symlinks (but not on Windows) Also gloss over errors reading cert/CRL contents from existing symlinked files. Fixes #23882 Reviewed-by: Andrew Dinh Reviewed-by: Tomas Mraz MergeDate: Wed Aug 19 19:29:03 2026 (Merged from https://github.com/openssl/openssl/pull/31594) (cherry picked from commit 38dd8ec5e3be47325b09f08abdef5dbebe89100f) --- crypto/x509/by_dir.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index e8b7ca152b2c2..957db68da17fa 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -228,7 +228,7 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, X509 st_x509; X509_CRL crl; } data; - int ok = 0; + int res, ok = 0; int i, j, k; unsigned long h; BUF_MEM *b = NULL; @@ -320,25 +320,35 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, } #ifndef OPENSSL_NO_POSIX_IO #ifdef _WIN32 +#define lstat _stat #define stat _stat #endif { struct stat st; - if (stat(b->data, &st) < 0) - break; - } + if (lstat(b->data, &st) < 0) + break; /* file does not exist, not even a symlink */ +#ifndef _WIN32 + if (stat(b->data, &st) < 0) { + k++; + continue; /* symlink is broken: following it went wrong */ + } #endif - /* found one. */ - if (type == X509_LU_X509) { - if ((X509_load_cert_file_ex(xl, b->data, ent->dir_type, libctx, - propq)) - == 0) - break; - } else if (type == X509_LU_CRL) { - if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0) - break; } +#endif + res = 0; + ERR_set_mark(); + if (type == X509_LU_X509) + res = X509_load_cert_file_ex(xl, b->data, ent->dir_type, libctx, propq); + else if (type == X509_LU_CRL) + res = X509_load_crl_file(xl, b->data, ent->dir_type); /* else case will caught higher up */ + ERR_pop_to_mark(); + /* unless OPENSSL_NO_POSIX_IO, gracefully skip found file if cert/CRL fails to load. */ +#ifndef OPENSSL_NO_POSIX_IO + res = 1; +#endif + if (res == 0) + break; k++; } From 1edbbe38105b37d816ffeb91988d65953518324d Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 9 Aug 2026 18:20:35 +0900 Subject: [PATCH 147/189] CCM: authenticate empty Final when payload Update is skipped CCM Final was routed through an update helper whose pointer-based dispatch treats a NULL-input call as a no-op or a length declaration. If an empty message skips payload Update, decryption can therefore skip tag verification and encryption does not generate a tag. Process an empty payload during Final only when the existing state flags show that no payload operation took place. Route the NULL-input EVP_Cipher() form through the same Final path. Fixes #32253 Assisted-by: Codex:gpt-5.6-sol (cherry picked from commit 493a46c61983195c2b49bfde75ffba0321e5e69d) Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Nikola Pajkovsky Merge-date: Fri Aug 21 09:57:46 2026 Merged-from: https://github.com/openssl/openssl/pull/32427 --- .../implementations/ciphers/ciphercommon_ccm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/providers/implementations/ciphers/ciphercommon_ccm.c b/providers/implementations/ciphers/ciphercommon_ccm.c index 2b5bddddeb78f..f2621c7df9621 100644 --- a/providers/implementations/ciphers/ciphercommon_ccm.c +++ b/providers/implementations/ciphers/ciphercommon_ccm.c @@ -288,13 +288,19 @@ int ossl_ccm_stream_final(void *vctx, unsigned char *out, size_t *outl, size_t outsize) { PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; - int i; + unsigned char dummy_in = 0, dummy_out = 0; if (!ossl_prov_is_running()) return 0; - i = ccm_cipher_internal(ctx, out, outl, NULL, 0); - if (i <= 0) + /* + * Encryption sets tag_set after processing the payload, while successful + * decryption clears iv_set. Use those transitions to avoid processing an + * operation twice. + */ + if (!ctx->key_set + || (ctx->iv_set && (!ctx->enc || !ctx->tag_set) + && ccm_cipher_internal(ctx, &dummy_out, outl, &dummy_in, 0) <= 0)) return 0; *outl = 0; @@ -309,6 +315,9 @@ int ossl_ccm_cipher(void *vctx, unsigned char *out, size_t *outl, size_t outsize if (!ossl_prov_is_running()) return 0; + if (in == NULL) + return ossl_ccm_stream_final(vctx, out, outl, outsize); + if (outsize < inl) { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); return 0; From e44fbf2ca18146cbd4f4d71c6078c9738964ec12 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 19 Aug 2026 11:21:49 +0900 Subject: [PATCH 148/189] test: cover CCM empty Final without a payload Update Declare a zero payload length and supply AAD while deliberately omitting the payload Update. Check that streaming and one-shot Final generate the same tag, accept the correct tag, and reject a modified tag for every available built-in CCM cipher. Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Nikola Pajkovsky Merge-date: Fri Aug 21 09:57:47 2026 Merged-from: https://github.com/openssl/openssl/pull/32427 --- test/evp_extra_test.c | 184 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index cc635ecff6ec9..73d66a2f44df9 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -7746,6 +7746,189 @@ static int test_aead_oneshot_zerolen(int idx) return ret; } +static const AEAD_ONESHOT_CFG ccm_empty_final_cfgs[] = { + { "AES-128-CCM", 16, 12, 16, 1 }, + { "AES-192-CCM", 24, 12, 16, 1 }, + { "AES-256-CCM", 32, 12, 16, 1 }, + { "ARIA-128-CCM", 16, 12, 16, 1 }, + { "ARIA-192-CCM", 24, 12, 16, 1 }, + { "ARIA-256-CCM", 32, 12, 16, 1 }, + { "SM4-CCM", 16, 12, 16, 1 } +}; + +/* + * Finalize CCM after declaring an empty payload and supplying AAD, without a + * payload Update. Return one for authentication success, zero for an + * authentication failure, and minus one for any other failure. + */ +static int ccm_empty_final_op(const AEAD_ONESHOT_CFG *cfg, int enc, + int oneshot_final, const unsigned char *key, const unsigned char *iv, + const unsigned char *aad, size_t aad_len, unsigned char *tag, + const char **why) +{ + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER *cipher = NULL; + unsigned char out[1] = { 0 }; + int outl = 0, rv; + int ret = -1; + + *why = NULL; + + if (!TEST_ptr(cipher = EVP_CIPHER_fetch(testctx, cfg->name, testpropq))) { + *why = "CIPHER_FETCH"; + goto end; + } + if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())) { + *why = "CTX_NEW"; + goto end; + } + if (!TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc))) { + *why = "INIT_CIPHER"; + goto end; + } + if (!TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, + (int)cfg->ivlen, NULL), + 0)) { + *why = "SET_IVLEN"; + goto end; + } + if (!TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + (int)cfg->taglen, enc ? NULL : tag), + 0)) { + *why = "SET_TAG"; + goto end; + } + if (!TEST_true(EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc))) { + *why = "INIT_KEY_IV"; + goto end; + } + if (!TEST_true(EVP_CipherUpdate(ctx, NULL, &outl, NULL, 0))) { + *why = "LENGTH"; + goto end; + } + if (!TEST_true(EVP_CipherUpdate(ctx, NULL, &outl, aad, (int)aad_len))) { + *why = "AAD"; + goto end; + } + + if (oneshot_final) { + rv = EVP_Cipher(ctx, out, NULL, 0); + ret = rv >= 0; + if (ret && rv != 0) { + *why = "ONESHOT_FINAL_LENGTH"; + ret = -1; + goto end; + } + } else { + ret = EVP_CipherFinal_ex(ctx, out, &outl) > 0; + if (ret && outl != 0) { + *why = "STREAM_FINAL_LENGTH"; + ret = -1; + goto end; + } + } + + if (ret && enc + && !TEST_int_gt(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, + (int)cfg->taglen, tag), + 0)) { + *why = "GET_TAG"; + ret = -1; + } + +end: + EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_free(cipher); + return ret; +} + +static int test_ccm_empty_final(int idx) +{ + static const unsigned char fixed_key[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; + static const unsigned char fixed_iv[12] = { + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab + }; + static const unsigned char fixed_aad[] = "CCM empty-payload Final regression"; + const AEAD_ONESHOT_CFG *cfg = &ccm_empty_final_cfgs[idx]; + EVP_CIPHER *probe = NULL; + unsigned char tag_stream[16], tag_oneshot[16], bad_tag[16]; + const char *why = NULL; + int rv, ok = 0; + + ERR_set_mark(); + probe = EVP_CIPHER_fetch(testctx, cfg->name, testpropq); + ERR_pop_to_mark(); + if (probe == NULL) { + TEST_info("skipping, '%s' is not available", cfg->name); + return 1; + } + EVP_CIPHER_free(probe); + + memset(tag_stream, 0, sizeof(tag_stream)); + rv = ccm_empty_final_op(cfg, 1, 0, fixed_key, fixed_iv, fixed_aad, + sizeof(fixed_aad) - 1, tag_stream, &why); + if (!TEST_int_eq(rv, 1)) { + TEST_error("%s: streaming encryption failed at %s", + cfg->name, why ? why : "FINAL"); + goto end; + } + + memset(tag_oneshot, 0, sizeof(tag_oneshot)); + rv = ccm_empty_final_op(cfg, 1, 1, fixed_key, fixed_iv, fixed_aad, + sizeof(fixed_aad) - 1, tag_oneshot, &why); + if (!TEST_int_eq(rv, 1)) { + TEST_error("%s: one-shot encryption failed at %s", + cfg->name, why ? why : "FINAL"); + goto end; + } + if (!TEST_mem_eq(tag_stream, cfg->taglen, tag_oneshot, cfg->taglen)) { + TEST_error("%s: streaming and one-shot tags differ", cfg->name); + goto end; + } + + rv = ccm_empty_final_op(cfg, 0, 0, fixed_key, fixed_iv, fixed_aad, + sizeof(fixed_aad) - 1, tag_stream, &why); + if (!TEST_int_eq(rv, 1)) { + TEST_error("%s: streaming verification failed at %s", + cfg->name, why ? why : "FINAL"); + goto end; + } + rv = ccm_empty_final_op(cfg, 0, 1, fixed_key, fixed_iv, fixed_aad, + sizeof(fixed_aad) - 1, tag_stream, &why); + if (!TEST_int_eq(rv, 1)) { + TEST_error("%s: one-shot verification failed at %s", + cfg->name, why ? why : "FINAL"); + goto end; + } + + memcpy(bad_tag, tag_stream, cfg->taglen); + bad_tag[0] ^= 1; + rv = ccm_empty_final_op(cfg, 0, 0, fixed_key, fixed_iv, fixed_aad, + sizeof(fixed_aad) - 1, bad_tag, &why); + if (!TEST_int_eq(rv, 0)) { + TEST_error("%s: streaming Final accepted an invalid tag", cfg->name); + goto end; + } + ERR_clear_error(); + rv = ccm_empty_final_op(cfg, 0, 1, fixed_key, fixed_iv, fixed_aad, + sizeof(fixed_aad) - 1, bad_tag, &why); + if (!TEST_int_eq(rv, 0)) { + TEST_error("%s: one-shot Final accepted an invalid tag", cfg->name); + goto end; + } + ERR_clear_error(); + + ok = 1; +end: + return ok; +} + #ifndef OPENSSL_NO_DES static int test_EVP_CIPHER_get_type_des_ede3(void) { @@ -8225,6 +8408,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_rsasve_degenerate_exponent, 2); ADD_ALL_TESTS(test_rsasve_degenerate_ciphertext, 3); + ADD_ALL_TESTS(test_ccm_empty_final, OSSL_NELEM(ccm_empty_final_cfgs)); /* Test cases for CVE-2026-45446 */ ADD_TEST(test_aes_gcm_siv_empty_data); From b584ce6ec9693d40d063052e8aca976b9b0eff24 Mon Sep 17 00:00:00 2001 From: Abel Thomas Date: Wed, 19 Aug 2026 13:53:37 +0200 Subject: [PATCH 149/189] file_store_any2obj.c: validate blob length before allocation Both msblob2obj_decode() and pvk2obj_decode() computed an attacker-influenced buffer size (from `bitlen`, or from `saltlen + keylen`) and passed it to BUF_MEM_grow() without an upper bound. Resolves #31684 Fixes: f40c5f2c53b9 "PROV & STORE: Make the 'file:' store loader understand more binary formats" Fixes: 0f5493e60b9e "storemgmt: Validate msblob length before buffer allocation" Reviewed-by: Eugene Syromiatnikov Reviewed-by: Neil Horman Reviewed-by: Matt Caswell Merge-date: Fri Aug 21 10:10:35 2026 Merged-from: https://github.com/openssl/openssl/pull/31704 --- providers/implementations/storemgmt/file_store_any2obj.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/providers/implementations/storemgmt/file_store_any2obj.c b/providers/implementations/storemgmt/file_store_any2obj.c index 8b8663d7574a2..74c78db14e83e 100644 --- a/providers/implementations/storemgmt/file_store_any2obj.c +++ b/providers/implementations/storemgmt/file_store_any2obj.c @@ -192,11 +192,9 @@ static int msblob2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, ok = 0; mem_want = ossl_blob_length(bitlen, isdss, ispub); - if (bitlen > BLOB_MAX_LENGTH) { - ERR_raise(ERR_LIB_PEM, PEM_R_HEADER_TOO_LONG); - goto err; + if (mem_want > BLOB_MAX_LENGTH) { + goto next; } - if (!BUF_MEM_grow(mem, mem_len + mem_want)) { ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); goto err; From 35d15b5d4853528df7602b8d2f2ba67590b52b59 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 23 Jun 2026 23:45:51 +0200 Subject: [PATCH 150/189] cms: fix AuthEnvelopedData authAttrs tags and verify them as AEAD AAD The CMS_AuthEnvelopedData ASN.1 template used the implicit tags and the X509_ALGOR type copied from CMS_AuthenticatedData. Per RFC 5083 the authAttrs and unauthAttrs fields are [1] and [2] (not [2] and [3]) and are SET OF Attribute, so use X509_ATTRIBUTE with the correct tags, matching the STACK_OF(X509_ATTRIBUTE) members already declared in the structure. With the tags fixed, authEnvelopedData carrying authAttrs now parses, so the authenticated attributes must also be fed to the content cipher as the AEAD associated data required by RFC 5083 section 2.1. Encode their DER (with the universal SET OF tag) for both encryption and decryption; without this the GCM tag fails to verify against compliant senders such as BouncyCastle. RFC 5083 also requires that plaintext is not released until its integrity has been verified. The AEAD tag is only checked once all the ciphertext has been processed, so buffer the decrypted content and forward it to the output BIO only after that check succeeds; a tampered message then leaks nothing to -out. Add an interop test using a BouncyCastle-generated AES-128-GCM message with authenticated and unauthenticated attributes, plus a tampered copy that must fail the tag check and leave -out empty. Closes #31635 Closes #26101 Closes #31629 Assisted-by: Claude:claude-opus-4-8 Reviewed-by: Tomas Mraz Reviewed-by: Igor Ustinov Reviewed-by: Norbert Pocs Merge-date: Fri Aug 21 10:36:33 2026 Merged-from: https://github.com/openssl/openssl/pull/32076 --- crypto/cms/cms_asn1.c | 4 +- crypto/cms/cms_env.c | 40 +++++++++++++++++- crypto/cms/cms_local.h | 3 ++ crypto/cms/cms_smime.c | 39 ++++++++++++++++++ test/recipes/80-test_cms.t | 41 ++++++++++++++++++- .../80-test_cms_data/authenveloped_attrs.pem | 7 ++++ .../bad_authenveloped_attrs.pem | 7 ++++ 7 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 test/recipes/80-test_cms_data/authenveloped_attrs.pem create mode 100644 test/recipes/80-test_cms_data/bad_authenveloped_attrs.pem diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index 7fa90dfb3561b..b3c103699031b 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -245,9 +245,9 @@ ASN1_NDEF_SEQUENCE(CMS_AuthEnvelopedData) = { ASN1_IMP_OPT(CMS_AuthEnvelopedData, originatorInfo, CMS_OriginatorInfo, 0), ASN1_SET_OF(CMS_AuthEnvelopedData, recipientInfos, CMS_RecipientInfo), ASN1_SIMPLE(CMS_AuthEnvelopedData, authEncryptedContentInfo, CMS_EncryptedContentInfo), - ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, authAttrs, X509_ALGOR, 2), + ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, authAttrs, X509_ATTRIBUTE, 1), ASN1_SIMPLE(CMS_AuthEnvelopedData, mac, ASN1_OCTET_STRING), - ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, unauthAttrs, X509_ALGOR, 3) + ASN1_IMP_SET_OF_OPT(CMS_AuthEnvelopedData, unauthAttrs, X509_ATTRIBUTE, 2) } ASN1_NDEF_SEQUENCE_END(CMS_AuthEnvelopedData) ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = { diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 0041adcd41c11..ee86ae71d3ed6 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -1206,6 +1206,35 @@ BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) return cms_EnvelopedData_Decryption_init_bio(cms); } +/* The DER encoding of authAttrs, with the universal SET OF tag, is the AAD */ +static int cms_AuthEnvelopedData_set_aad(BIO *b, + STACK_OF(X509_ATTRIBUTE) *authAttrs) +{ + EVP_CIPHER_CTX *ctx; + unsigned char *aad = NULL; + int aadlen, outl, ok = 0; + const ASN1_ITEM *item; + + if (!BIO_get_cipher_ctx(b, &ctx)) + return 0; + item = EVP_CIPHER_CTX_is_encrypting(ctx) + ? ASN1_ITEM_rptr(CMS_Attributes_AadEncrypt) + : ASN1_ITEM_rptr(CMS_Attributes_AadDecrypt); + aadlen = ASN1_item_i2d((ASN1_VALUE *)authAttrs, &aad, item); + if (aadlen <= 0 || aad == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } + if (EVP_CipherUpdate(ctx, NULL, &outl, aad, aadlen) <= 0) { + ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE); + goto err; + } + ok = 1; +err: + OPENSSL_free(aad); + return ok; +} + BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms) { CMS_EncryptedContentInfo *ec; @@ -1222,9 +1251,16 @@ BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms) ec->taglen = aenv->mac->length; } ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms), 1); + if (ret == NULL) + return NULL; + + /* authAttrs, if present, are the AEAD associated data */ + if (aenv->authAttrs != NULL + && !cms_AuthEnvelopedData_set_aad(ret, aenv->authAttrs)) + goto err; - /* If error or no cipher end of processing */ - if (ret == NULL || ec->cipher == NULL) + /* If no cipher end of processing */ + if (ec->cipher == NULL) return ret; /* Now encrypt content key according to each RecipientInfo type */ diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 94496b3823ef0..55f41af054bed 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -371,6 +371,9 @@ DECLARE_ASN1_ITEM(CMS_EncryptedContentInfo) DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber) DECLARE_ASN1_ITEM(CMS_Attributes_Sign) DECLARE_ASN1_ITEM(CMS_Attributes_Verify) +/* The authAttrs AAD encoding matches the signed-attributes one */ +#define CMS_Attributes_AadEncrypt_it CMS_Attributes_Sign_it +#define CMS_Attributes_AadDecrypt_it CMS_Attributes_Verify_it DECLARE_ASN1_ITEM(CMS_RecipientInfo) DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo) DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber) diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 4b5009b9d5bf8..dea1df084764c 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -36,6 +36,7 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) unsigned char buf[4096]; int r = 0, i; BIO *tmpout; + BIO *aeadbuf = NULL; tmpout = cms_get_text_bio(out, flags); @@ -44,6 +45,33 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) goto err; } + /* + * For AEAD content (AuthEnvelopedData) the integrity tag is only verified + * once all the ciphertext has been processed, by the + * BIO_get_cipher_status() call below. RFC 5083 requires that the plaintext + * is not released to the caller until that verification succeeds, so + * buffer it in memory and only forward it to the output BIO once the tag + * has been checked. When CMS_TEXT is set tmpout is already a memory BIO + * that is flushed only on success, so the extra buffering is not needed. + */ + if (tmpout == out && BIO_method_type(in) == BIO_TYPE_CIPHER) { + EVP_CIPHER_CTX *ctx = NULL; + + if (BIO_get_cipher_ctx(in, &ctx) > 0 && ctx != NULL + && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx)) + & EVP_CIPH_FLAG_AEAD_CIPHER) + != 0) { + aeadbuf = BIO_new(BIO_s_mem()); + if (aeadbuf == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_BIO_LIB); + goto err; + } + /* Return 0 (EOF) rather than a retryable -1 once drained. */ + BIO_set_mem_eof_return(aeadbuf, 0); + tmpout = aeadbuf; + } + } + /* Read all content through chain to process digest, decrypt etc */ for (;;) { i = BIO_read(in, buf, sizeof(buf)); @@ -66,6 +94,17 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR); goto err; } + } else if (aeadbuf != NULL) { + /* Forward the AEAD BIO to out BIO as the tag has been verified. */ + for (;;) { + i = BIO_read(aeadbuf, buf, sizeof(buf)); + if (i < 0) + goto err; + if (i == 0) + break; + if (BIO_write(out, buf, i) != i) + goto err; + } } r = 1; diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index 0c6b301319ebe..b27a03d601627 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -53,7 +53,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) $no_rc2 = 1 if disabled("legacy"); -plan tests => 37; +plan tests => 38; ok(run(test(["pkcs7_test"])), "test pkcs7"); @@ -796,6 +796,18 @@ sub zero_compare { return (-e "$opts{output}.txt" && -z "$opts{output}.txt"); } +sub read_file_text { + my ($file) = @_; + open(my $fh, "<", $file) or return undef; + binmode $fh; + local $/; + my $data = <$fh>; + close($fh); + # Normalise line endings as -out is written in text mode on Windows. + $data =~ s/\r\n/\n/g if defined $data; + return $data; +} + subtest "CMS => PKCS#7 compatibility tests\n" => sub { plan tests => scalar @smime_pkcs7_tests; @@ -1027,6 +1039,33 @@ subtest "CMS parse authenticatedData authAttrs and unauthAttrs\n" => sub { "unauthAttrs parsed as SET OF Attribute"); }; +subtest "CMS decrypt authEnvelopedData with authenticated attributes\n" => sub { + plan tests => 4; + + # BouncyCastle AES-128-GCM authEnvelopedData (KEK) carrying authAttrs; + # a clean decrypt confirms the authAttrs are verified as the AEAD AAD. + 1 while unlink "authattrs.txt"; + ok(run(app(["openssl", "cms", @defaultprov, "-decrypt", "-inform", "PEM", + "-secretkey", "000102030405060708090A0B0C0D0E0F", + "-secretkeyid", "C0FEE0", + "-in", catfile($datadir, "authenveloped_attrs.pem"), + "-out", "authattrs.txt" ])), + "decrypt authEnvelopedData with authAttrs"); + is(read_file_text("authattrs.txt"), "Hello AuthEnvelopedData world\n", + "decrypted authEnvelopedData plaintext matches expected"); + + # A flipped authAttrs byte must fail the tag check and leave -out empty. + 1 while unlink "bad_authattrs.txt"; + ok(!run(app(["openssl", "cms", @defaultprov, "-decrypt", "-inform", "PEM", + "-secretkey", "000102030405060708090A0B0C0D0E0F", + "-secretkeyid", "C0FEE0", + "-in", catfile($datadir, "bad_authenveloped_attrs.pem"), + "-out", "bad_authattrs.txt" ])), + "reject authEnvelopedData with tampered authAttrs"); + ok(!-s "bad_authattrs.txt", + "tampered authEnvelopedData leaks no plaintext to -out"); +}; + subtest "CAdES <=> CAdES consistency tests\n" => sub { plan tests => (scalar @smime_cms_cades_tests); diff --git a/test/recipes/80-test_cms_data/authenveloped_attrs.pem b/test/recipes/80-test_cms_data/authenveloped_attrs.pem new file mode 100644 index 0000000000000..75c8eab00b886 --- /dev/null +++ b/test/recipes/80-test_cms_data/authenveloped_attrs.pem @@ -0,0 +1,7 @@ +-----BEGIN CMS----- +MIAGCyqGSIb3DQEJEAEXoIAwgAIBADEzojECAQQwBQQDwP7gMAsGCWCGSAFlAwQB +BQQYknpV85muZoLZSPkwi5Ll1Z1HwzAeZThVMIAGCSqGSIb3DQEHATAeBglghkgB +ZQMEAQYwEQQMkCQb305essfGO2nqAgEQoIAEHvYjM7EK9qZAHgoohdcbSHXe0lGJ +/Hjk3nkK5VsHxgAAAAChFjAUBgkrBgEEAYaNHwExBwwFaGVsbG8EENeGq4IXAd1O +iv8hMl+lHZOiFjAUBgkrBgEEAYaNHwIxBwwFd29ybGQAAAAAAAA= +-----END CMS----- diff --git a/test/recipes/80-test_cms_data/bad_authenveloped_attrs.pem b/test/recipes/80-test_cms_data/bad_authenveloped_attrs.pem new file mode 100644 index 0000000000000..e14946c96d881 --- /dev/null +++ b/test/recipes/80-test_cms_data/bad_authenveloped_attrs.pem @@ -0,0 +1,7 @@ +-----BEGIN CMS----- +MIAGCyqGSIb3DQEJEAEXoIAwgAIBADEzojECAQQwBQQDwP7gMAsGCWCGSAFlAwQB +BQQYknpV85muZoLZSPkwi5Ll1Z1HwzAeZThVMIAGCSqGSIb3DQEHATAeBglghkgB +ZQMEAQYwEQQMkCQb305essfGO2nqAgEQoIAEHvYjM7EK9qZAHgoohdcbSHXe0lGJ +/Hjk3nkK5VsHxgAAAAChFjAUBgkrBgEEAYaNHwExBwwFaWVsbG8EENeGq4IXAd1O +iv8hMl+lHZOiFjAUBgkrBgEEAYaNHwIxBwwFd29ybGQAAAAAAAA= +-----END CMS----- From c8ba7c89289074ca38b997b6559b664f52cd2387 Mon Sep 17 00:00:00 2001 From: Bob Beck Date: Tue, 18 Aug 2026 13:49:34 -0600 Subject: [PATCH 151/189] Free connections before listeners in the radix test cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A connection's assist thread reads from its network BIO, which for a dgram BIO pair belongs to the linked listener. Freeing a listener while the connection's assist thread is still running is a use-after-free. Freeing connections first joins their assist threads, so no thread is reading when the listener BIOs are freed. Fixes #32420 Reviewed-by: Saša Nedvědický Reviewed-by: Tomas Mraz Reviewed-by: Andrew Dinh Merge-date: Fri Aug 21 11:07:27 2026 Merged-from: https://github.com/openssl/openssl/pull/32421 --- test/radix/quic_bindings.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/radix/quic_bindings.c b/test/radix/quic_bindings.c index eb9423ef314e2..d58476e9aff8d 100644 --- a/test/radix/quic_bindings.c +++ b/test/radix/quic_bindings.c @@ -403,6 +403,22 @@ static int RADIX_PROCESS_join_all_threads(RADIX_PROCESS *rp, int *testresult) return ok; } +/* + * Free every non-listener object's SSL before cleanup_one() frees any listener. + * + * A connection's assist thread reads from its network BIO, and for a dgram BIO + * pair (see hf_link_dgram_pair) that BIO belongs to the linked listener. Freeing + * the connection joins its assist thread (see ossl_quic_free), so doing so first + * ensures no assist thread is still reading when the listener BIOs are freed. + */ +static void cleanup_nonlistener(RADIX_OBJ *obj) +{ + if (obj->ssl != NULL && !SSL_is_listener(obj->ssl)) { + SSL_free(obj->ssl); + obj->ssl = NULL; + } +} + static void cleanup_one(RADIX_OBJ *obj) { obj->registered = 0; @@ -423,6 +439,7 @@ static void RADIX_PROCESS_cleanup(RADIX_PROCESS *rp) sk_RADIX_THREAD_free(rp->threads); rp->threads = NULL; + lh_RADIX_OBJ_doall(rp->objs, cleanup_nonlistener); lh_RADIX_OBJ_doall(rp->objs, cleanup_one); lh_RADIX_OBJ_free(rp->objs); rp->objs = NULL; From 75b27b995fc4306bbd8b61ec7dd276aba1650b8e Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 23 Jul 2026 17:53:43 -0400 Subject: [PATCH 152/189] Rework how to fetch components in the drbg Commit c9a2ce61118c7f73bc4898eedec64c2bde8bb7a0 introduced some code into the drbg in an effort to get it to select the same provider as is specified for the drbg. Unfortunately this creates a problem when a user has altered the identity of a predefined provider (in this case fips). The DRBG is passed a set of parameters when instantiating, which includes the name of the provider. This provider uses the name that the core knows it as, which may be different than "fips", which the fips provider always referrs to itself as. Fix it by skipping the provider name check when operating in the fips module, as we should only ever get fips approved algs from within that space Fixes a customer issue, who noted that since this was introduced, using identity configurations no longer works. (cherry picked from commit 71ec72702be26ef9130530624fada6038e59fc01) Reviewed-by: Mounir Idrassi Reviewed-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs Merge-date: Fri Aug 21 11:51:12 2026 Merged-from: https://github.com/openssl/openssl/pull/32357 --- crypto/rand/rand_lib.c | 5 --- providers/implementations/rands/drbg_ctr.c | 43 +++++---------------- providers/implementations/rands/drbg_hash.c | 36 ++++++++++------- providers/implementations/rands/drbg_hmac.c | 39 +++++++++++-------- 4 files changed, 54 insertions(+), 69 deletions(-) diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 84455e229c23f..89becbd84eb94 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -674,7 +674,6 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, EVP_RAND_CTX *ctx; OSSL_PARAM params[9], *p = params; const OSSL_PARAM *settables; - const char *prov_name; char *name, *cipher; int use_df = 1; @@ -686,7 +685,6 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG); return NULL; } - prov_name = ossl_provider_name(EVP_RAND_get0_provider(rand)); ctx = EVP_RAND_CTX_new(rand, parent); EVP_RAND_free(rand); if (ctx == NULL) { @@ -704,9 +702,6 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, && OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_DIGEST)) *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, dgbl->rng_digest, 0); - if (prov_name != NULL) - *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_CORE_PROV_NAME, - (char *)prov_name, 0); if (dgbl->rng_propq != NULL) *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, dgbl->rng_propq, 0); diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c index b7b20e12f81aa..d3bf4f74d0a22 100644 --- a/providers/implementations/rands/drbg_ctr.c +++ b/providers/implementations/rands/drbg_ctr.c @@ -725,7 +725,6 @@ static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]) PROV_DRBG *ctx = (PROV_DRBG *)vctx; PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data; OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); - OSSL_PROVIDER *prov = NULL; const OSSL_PARAM *p; char *ecb; const char *propquery = NULL; @@ -743,19 +742,14 @@ static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]) != NULL) { if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; - propquery = (const char *)p->data; } - if ((p = OSSL_PARAM_locate_const(params, - OSSL_PROV_PARAM_CORE_PROV_NAME)) - != NULL) { - if (p->data_type != OSSL_PARAM_UTF8_STRING) - return 0; - if ((prov = ossl_provider_find(libctx, - (const char *)p->data, 1)) - == NULL) - return 0; - } +#ifndef FIPS_MODULE + propquery = "provider=default"; + if (p != NULL + && p->data_type == OSSL_PARAM_UTF8_STRING) + propquery = (const char *)p->data; +#endif if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_CIPHER)) != NULL) { const char *base = (const char *)p->data; @@ -764,50 +758,33 @@ static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]) if (p->data_type != OSSL_PARAM_UTF8_STRING || p->data_size < ctr_str_len) { - ossl_provider_free(prov); return 0; } if (OPENSSL_strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) { ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER); - ossl_provider_free(prov); return 0; } if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL) { - ossl_provider_free(prov); return 0; } strcpy(ecb + p->data_size - ecb_str_len, "ECB"); EVP_CIPHER_free(ctr->cipher_ecb); EVP_CIPHER_free(ctr->cipher_ctr); + ctr->cipher_ctr = NULL; + ctr->cipher_ecb = NULL; /* * Try to fetch algorithms from our own provider code, fallback * to generic fetch only if that fails */ - (void)ERR_set_mark(); - ctr->cipher_ctr = evp_cipher_fetch_from_prov(prov, base, NULL); - if (ctr->cipher_ctr == NULL) { - (void)ERR_pop_to_mark(); - ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery); - } else { - (void)ERR_clear_last_mark(); - } - (void)ERR_set_mark(); - ctr->cipher_ecb = evp_cipher_fetch_from_prov(prov, ecb, NULL); - if (ctr->cipher_ecb == NULL) { - (void)ERR_pop_to_mark(); - ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery); - } else { - (void)ERR_clear_last_mark(); - } + ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery); + ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery); OPENSSL_free(ecb); if (ctr->cipher_ctr == NULL || ctr->cipher_ecb == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS); - ossl_provider_free(prov); return 0; } cipher_init = 1; } - ossl_provider_free(prov); if (cipher_init && !drbg_ctr_init(ctx)) return 0; diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index 92eb443c6e829..03362e5c8bd43 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -508,23 +508,22 @@ static const OSSL_PARAM *drbg_hash_gettable_ctx_params(ossl_unused void *vctx, static int drbg_fetch_digest_from_prov(const OSSL_PARAM params[], OSSL_LIB_CTX *libctx, - EVP_MD **digest) + EVP_MD **digest, + const char *propq) { - OSSL_PROVIDER *prov = NULL; const OSSL_PARAM *p; EVP_MD *md = NULL; int ret = 0; + const char *propquery = NULL; - if (digest == NULL) - return 0; +#ifndef FIPS_MODULE + if (propq == NULL) + propquery = "provider=default"; + else + propquery = propq; +#endif - if ((p = OSSL_PARAM_locate_const(params, - OSSL_PROV_PARAM_CORE_PROV_NAME)) - == NULL) - return 0; - if (p->data_type != OSSL_PARAM_UTF8_STRING) - return 0; - if ((prov = ossl_provider_find(libctx, (const char *)p->data, 1)) == NULL) + if (digest == NULL) return 0; p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); @@ -536,15 +535,13 @@ static int drbg_fetch_digest_from_prov(const OSSL_PARAM params[], if (p->data_type != OSSL_PARAM_UTF8_STRING) goto done; - md = evp_digest_fetch_from_prov(prov, (const char *)p->data, NULL); + md = EVP_MD_fetch(libctx, p->data, propquery); if (md) { EVP_MD_free(*digest); *digest = md; ret = 1; } - done: - ossl_provider_free(prov); return ret; } @@ -556,15 +553,24 @@ static int drbg_hash_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[] EVP_MD *prov_md = NULL; const EVP_MD *md; int md_size; + const OSSL_PARAM *p; if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params, OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK)) return 0; /* try to fetch digest from provider */ + p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_PROPERTIES); (void)ERR_set_mark(); - if (!drbg_fetch_digest_from_prov(params, libctx, &prov_md)) { + if (!drbg_fetch_digest_from_prov(params, libctx, &prov_md, + (p != NULL && p->data_type == OSSL_PARAM_UTF8_STRING) ? p->data : NULL)) { (void)ERR_pop_to_mark(); + /* + * Its possible for drbg_fetch_digest_from_prov to return 0 after having set prov_md + * so we need to ensure we free it here + */ + EVP_MD_free(prov_md); + /* fall back to full implementation search */ if (!ossl_prov_digest_load_from_params(&hash->digest, params, libctx)) return 0; diff --git a/providers/implementations/rands/drbg_hmac.c b/providers/implementations/rands/drbg_hmac.c index d3191e55a9291..87050764fe463 100644 --- a/providers/implementations/rands/drbg_hmac.c +++ b/providers/implementations/rands/drbg_hmac.c @@ -412,27 +412,25 @@ static const OSSL_PARAM *drbg_hmac_gettable_ctx_params(ossl_unused void *vctx, static int drbg_fetch_algs_from_prov(const OSSL_PARAM params[], OSSL_LIB_CTX *libctx, EVP_MAC_CTX **macctx, - EVP_MD **digest) + EVP_MD **digest, const char *propq) { - OSSL_PROVIDER *prov = NULL; const OSSL_PARAM *p; const char *digest_name = NULL; const char *hmac_name = NULL; EVP_MD *md = NULL; EVP_MAC *mac = NULL; - OSSL_PARAM mac_params[2], *mp = mac_params; + OSSL_PARAM mac_params[3], *mp = mac_params; int ret = 0; + const char *propquery = NULL; - if (macctx == NULL || digest == NULL) - return 0; +#ifndef FIPS_MODULE + if (propq == NULL) + propquery = "provider=default"; + else + propquery = propq; +#endif - if ((p = OSSL_PARAM_locate_const(params, - OSSL_PROV_PARAM_CORE_PROV_NAME)) - == NULL) - return 0; - if (p->data_type != OSSL_PARAM_UTF8_STRING) - return 0; - if ((prov = ossl_provider_find(libctx, (const char *)p->data, 1)) == NULL) + if (macctx == NULL || digest == NULL) return 0; p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); @@ -441,7 +439,7 @@ static int drbg_fetch_algs_from_prov(const OSSL_PARAM params[], ERR_raise(ERR_LIB_PROV, PROV_R_VALUE_ERROR); goto done; } - md = evp_digest_fetch_from_prov(prov, digest_name, NULL); + md = EVP_MD_fetch(libctx, p->data, propquery); if (md) { EVP_MD_free(*digest); *digest = md; @@ -467,12 +465,14 @@ static int drbg_fetch_algs_from_prov(const OSSL_PARAM params[], EVP_MAC_CTX_free(*macctx); *macctx = NULL; - mac = evp_mac_fetch_from_prov(prov, hmac_name, NULL); + mac = EVP_MAC_fetch(libctx, hmac_name, propquery); if (mac) { *macctx = EVP_MAC_CTX_new(mac); /* The context holds on to the MAC */ EVP_MAC_free(mac); *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)digest_name, 0); + if (propquery) + *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES, (char *)propquery, 0); *mp = OSSL_PARAM_construct_end(); if (!EVP_MAC_CTX_set_params(*macctx, mac_params)) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC); @@ -484,7 +484,6 @@ static int drbg_fetch_algs_from_prov(const OSSL_PARAM params[], } done: - ossl_provider_free(prov); return ret; } @@ -496,15 +495,23 @@ static int drbg_hmac_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[] EVP_MD *prov_md = NULL; const EVP_MD *md; int md_size; + const OSSL_PARAM *p; if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params, OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK)) return 0; /* try to fetch mac and digest from provider */ + p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_PROPERTIES); (void)ERR_set_mark(); - if (!drbg_fetch_algs_from_prov(params, libctx, &hmac->ctx, &prov_md)) { + if (!drbg_fetch_algs_from_prov(params, libctx, &hmac->ctx, &prov_md, + (p != NULL && p->data_type == OSSL_PARAM_UTF8_STRING) ? p->data : NULL)) { (void)ERR_pop_to_mark(); + /* + * Its possible for drbg_fetch_algs_from_prov to return 0 and set prov_md here + * so we need to free prov_md to be leak free + */ + EVP_MD_free(prov_md); /* fall back to full implementation search */ if (!ossl_prov_digest_load_from_params(&hmac->digest, params, libctx)) return 0; From f544f4970f2719ddaeb3fa1e78572b95c99dd69f Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 24 Jul 2026 12:14:33 -0400 Subject: [PATCH 153/189] add a test to exercize the identity config directive on fips Reviewed-by: Bob Beck Reviewed-by: Simo Sorce MergeDate: Wed Aug 12 19:26:04 2026 (cherry picked from commit 42f8848ac6cbd727264fd3a9bfa97861e4ab71b5) Reviewed-by: Mounir Idrassi Reviewed-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs Merged-from: https://github.com/openssl/openssl/pull/32357 --- test/fipsidentity.cnf | 19 ++++++++++++++++ test/recipes/20-test_cli_fips.t | 40 ++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/fipsidentity.cnf diff --git a/test/fipsidentity.cnf b/test/fipsidentity.cnf new file mode 100644 index 0000000000000..34bf5881d4000 --- /dev/null +++ b/test/fipsidentity.cnf @@ -0,0 +1,19 @@ +openssl_conf = openssl_init + +# Comment out the next line to ignore configuration errors +config_diagnostics = 1 + +.include fipsmodule.cnf + +[openssl_init] +providers = provider_sect + +[provider_sect] +default = default_sect +fips = fips_sect + +[default_sect] +activate = yes + +[fips_sect] +identity = fips-identity diff --git a/test/recipes/20-test_cli_fips.t b/test/recipes/20-test_cli_fips.t index 2abc4d243414c..e4089cf03aa6b 100644 --- a/test/recipes/20-test_cli_fips.t +++ b/test/recipes/20-test_cli_fips.t @@ -26,11 +26,12 @@ use platform; my $no_check = disabled("fips") || disabled('fips-securitychecks'); plan skip_all => "Test only supported in a fips build with security checks" if $no_check; -plan tests => 12; +plan tests => 13; my $fipsmodule = bldtop_file('providers', platform->dso('fips')); my $fipsconf = srctop_file("test", "fips-and-base.cnf"); my $defaultconf = srctop_file("test", "default.cnf"); +my $identityconf = srctop_file("test" ,"fips-identity.cnf"); my $tbs_data = $fipsmodule; my $bogus_data = $fipsconf; @@ -282,6 +283,43 @@ SKIP: { }; } +SKIP: { + skip "FIPS RSA tests because of no rsa in this build", 1 + if disabled("rsa"); + + subtest RSA_identity => sub { + my $testtext_prefix = 'RSA'; + my $fips_key = $testtext_prefix.'.fips.priv.pem'; + my $fips_pub_key = $testtext_prefix.'.fips.pub.pem'; + my $nonfips_key = $testtext_prefix.'.nonfips.priv.pem'; + my $nonfips_pub_key = $testtext_prefix.'.nonfips.pub.pem'; + my $testtext = ''; + + plan tests => 2; + + my $destfips = bldtop_file("test-runs", "test_cli_fips", platform->dso("fips-identity")); + copy($fipsmodule, $destfips) or die("Couldn't copy file"); + $ENV{OPENSSL_CONF} = $identityconf; + my $oldmodules = $ENV{OPENSSL_MODULES}; + $ENV{OPENSSL_MODULES} = bldtop_dir("test-runs", "test_cli_fips"); + $testtext = $testtext_prefix.': '. + 'Generate a key with a non-FIPS algorithm with the default provider'; + print "Running genpkey"; + ok(run(app(['openssl', 'genpkey', '-algorithm', 'RSA', + '-pkeyopt', 'rsa_keygen_bits:512', + '-out', $nonfips_key])), + $testtext); + + $testtext = $testtext_prefix.': '. + 'Generate a key with a FIPS algorithm'; + ok(run(app(['openssl', 'genpkey', '-algorithm', 'RSA', + '-pkeyopt', 'rsa_keygen_bits:2048', + '-out', $fips_key])), + $testtext); + $ENV{OPENSSL_MODULES} = $oldmodules; + }; +} + SKIP : { skip "FIPS DSA tests because of no dsa in this build", 1 if disabled("dsa") || $dsasignpass == '0'; From 39a7a0f54975988a8452f9b83dbeb7224e72d914 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 13 Aug 2026 15:00:13 +0900 Subject: [PATCH 154/189] test: fix FIPS identity DRBG regression coverage Use the configuration filename that was actually added. Set the random configuration property to fips=yes so the existing RSA checks use a DRBG from the renamed FIPS provider, rather than one from the default provider. Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Nikola Pajkovsky Reviewed-by: Norbert Pocs Merge-date: Fri Aug 21 11:51:15 2026 Merged-from: https://github.com/openssl/openssl/pull/32357 --- test/fipsidentity.cnf | 4 ++++ test/recipes/20-test_cli_fips.t | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test/fipsidentity.cnf b/test/fipsidentity.cnf index 34bf5881d4000..30b7775275d6b 100644 --- a/test/fipsidentity.cnf +++ b/test/fipsidentity.cnf @@ -7,6 +7,7 @@ config_diagnostics = 1 [openssl_init] providers = provider_sect +random = random_sect [provider_sect] default = default_sect @@ -17,3 +18,6 @@ activate = yes [fips_sect] identity = fips-identity + +[random_sect] +properties = fips=yes diff --git a/test/recipes/20-test_cli_fips.t b/test/recipes/20-test_cli_fips.t index e4089cf03aa6b..daf7368e91c14 100644 --- a/test/recipes/20-test_cli_fips.t +++ b/test/recipes/20-test_cli_fips.t @@ -31,7 +31,7 @@ plan tests => 13; my $fipsmodule = bldtop_file('providers', platform->dso('fips')); my $fipsconf = srctop_file("test", "fips-and-base.cnf"); my $defaultconf = srctop_file("test", "default.cnf"); -my $identityconf = srctop_file("test" ,"fips-identity.cnf"); +my $identityconf = srctop_file("test" ,"fipsidentity.cnf"); my $tbs_data = $fipsmodule; my $bogus_data = $fipsconf; From c4c0b8cc2650b9731c91608a07ee4ee17b432c5c Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 20 Aug 2026 09:09:29 -0400 Subject: [PATCH 155/189] Allow X448MLKEM1024 to be fips approved According to lightship, we can allow X448MLKEM1024 to be an approved hybrid kem, we just can't allow it for use in TLS1.3 (which isn't currently possible anyway, given that there is no code point for it). So set FIPS_DEFAULT_PROPERTIES on this alg rather than FIPS_UNAPPROVED_PROPERTIES. Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale Merge-date: Fri Aug 21 14:34:08 2026 Merged-from: https://github.com/openssl/openssl/pull/32444 --- providers/fips/fipsprov.c | 6 +++--- providers/implementations/include/prov/names.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 8917166bce374..a29d3edcd334b 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -539,8 +539,8 @@ static const OSSL_ALGORITHM fips_asym_kem[] = { { PROV_NAMES_ML_KEM_768, FIPS_DEFAULT_PROPERTIES, ossl_ml_kem_asym_kem_functions }, { PROV_NAMES_ML_KEM_1024, FIPS_DEFAULT_PROPERTIES, ossl_ml_kem_asym_kem_functions }, #if !defined(OPENSSL_NO_ECX) - { "X25519MLKEM768", FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, - { "X448MLKEM1024", FIPS_UNAPPROVED_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, + { PROV_NAMES_X25519MLKEM768, FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, + { PROV_NAMES_X448MLKEM1024, FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, #endif #if !defined(OPENSSL_NO_EC) { "SecP256r1MLKEM768", FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, @@ -607,7 +607,7 @@ static const OSSL_ALGORITHM fips_keymgmt[] = { #if !defined(OPENSSL_NO_ECX) { PROV_NAMES_X25519MLKEM768, FIPS_DEFAULT_PROPERTIES, ossl_mlx_x25519_kem_kmgmt_functions, PROV_DESCS_X25519MLKEM768 }, - { PROV_NAMES_X448MLKEM1024, FIPS_UNAPPROVED_PROPERTIES, ossl_mlx_x448_kem_kmgmt_functions, + { PROV_NAMES_X448MLKEM1024, FIPS_DEFAULT_PROPERTIES, ossl_mlx_x448_kem_kmgmt_functions, PROV_DESCS_X448MLKEM1024 }, #endif #if !defined(OPENSSL_NO_EC) diff --git a/providers/implementations/include/prov/names.h b/providers/implementations/include/prov/names.h index 3b747ec92c048..7d78229fa9feb 100644 --- a/providers/implementations/include/prov/names.h +++ b/providers/implementations/include/prov/names.h @@ -404,7 +404,7 @@ #define PROV_NAMES_X25519MLKEM768 "X25519MLKEM768" #define PROV_DESCS_X25519MLKEM768 "X25519+ML-KEM-768 TLS hybrid implementation" #define PROV_NAMES_X448MLKEM1024 "X448MLKEM1024" -#define PROV_DESCS_X448MLKEM1024 "X448+ML-KEM-1024 TLS hybrid implementation" +#define PROV_DESCS_X448MLKEM1024 "X448+ML-KEM-1024 hybrid implementation" #define PROV_NAMES_SecP256r1MLKEM768 "SecP256r1MLKEM768" #define PROV_DESCS_SecP256r1MLKEM768 "P-256+ML-KEM-768 TLS hybrid implementation" #define PROV_NAMES_SecP384r1MLKEM1024 "SecP384r1MLKEM1024" From 0953b87193d9975fa5454862427c5119a7fa9061 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 24 Aug 2026 11:01:10 +0200 Subject: [PATCH 156/189] Revert "Allow X448MLKEM1024 to be fips approved" This reverts commit c4c0b8cc2650b9731c91608a07ee4ee17b432c5c. While this combination can be marked as approved (not for TLS), it could cause issues in the future. As there is no real user requirement for it, keep it disabled. Reviewed-by: Viktor Dukhovni Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz Merge-date: Mon Aug 24 10:14:50 2026 Merged-from: https://github.com/openssl/openssl/pull/32465 --- providers/fips/fipsprov.c | 6 +++--- providers/implementations/include/prov/names.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index a29d3edcd334b..8917166bce374 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -539,8 +539,8 @@ static const OSSL_ALGORITHM fips_asym_kem[] = { { PROV_NAMES_ML_KEM_768, FIPS_DEFAULT_PROPERTIES, ossl_ml_kem_asym_kem_functions }, { PROV_NAMES_ML_KEM_1024, FIPS_DEFAULT_PROPERTIES, ossl_ml_kem_asym_kem_functions }, #if !defined(OPENSSL_NO_ECX) - { PROV_NAMES_X25519MLKEM768, FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, - { PROV_NAMES_X448MLKEM1024, FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, + { "X25519MLKEM768", FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, + { "X448MLKEM1024", FIPS_UNAPPROVED_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, #endif #if !defined(OPENSSL_NO_EC) { "SecP256r1MLKEM768", FIPS_DEFAULT_PROPERTIES, ossl_mlx_kem_asym_kem_functions }, @@ -607,7 +607,7 @@ static const OSSL_ALGORITHM fips_keymgmt[] = { #if !defined(OPENSSL_NO_ECX) { PROV_NAMES_X25519MLKEM768, FIPS_DEFAULT_PROPERTIES, ossl_mlx_x25519_kem_kmgmt_functions, PROV_DESCS_X25519MLKEM768 }, - { PROV_NAMES_X448MLKEM1024, FIPS_DEFAULT_PROPERTIES, ossl_mlx_x448_kem_kmgmt_functions, + { PROV_NAMES_X448MLKEM1024, FIPS_UNAPPROVED_PROPERTIES, ossl_mlx_x448_kem_kmgmt_functions, PROV_DESCS_X448MLKEM1024 }, #endif #if !defined(OPENSSL_NO_EC) diff --git a/providers/implementations/include/prov/names.h b/providers/implementations/include/prov/names.h index 7d78229fa9feb..3b747ec92c048 100644 --- a/providers/implementations/include/prov/names.h +++ b/providers/implementations/include/prov/names.h @@ -404,7 +404,7 @@ #define PROV_NAMES_X25519MLKEM768 "X25519MLKEM768" #define PROV_DESCS_X25519MLKEM768 "X25519+ML-KEM-768 TLS hybrid implementation" #define PROV_NAMES_X448MLKEM1024 "X448MLKEM1024" -#define PROV_DESCS_X448MLKEM1024 "X448+ML-KEM-1024 hybrid implementation" +#define PROV_DESCS_X448MLKEM1024 "X448+ML-KEM-1024 TLS hybrid implementation" #define PROV_NAMES_SecP256r1MLKEM768 "SecP256r1MLKEM768" #define PROV_DESCS_SecP256r1MLKEM768 "P-256+ML-KEM-768 TLS hybrid implementation" #define PROV_NAMES_SecP384r1MLKEM1024 "SecP384r1MLKEM1024" From ef398036d1ad1acb707dd5fca6c5a02d21516860 Mon Sep 17 00:00:00 2001 From: Daniel Kubec Date: Tue, 21 Jul 2026 11:18:53 +0200 Subject: [PATCH 157/189] Add test for CVE-2026-63076 Assisted-by: Claude:claude-fable-5 Reviewed-by: Milan Broz Reviewed-by: Norbert Pocs Merge-date: Sat Aug 22 06:11:28 2026 --- test/cmp_protect_test.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/cmp_protect_test.c b/test/cmp_protect_test.c index 3bbdc095199b4..a6b2a9ddb9063 100644 --- a/test/cmp_protect_test.c +++ b/test/cmp_protect_test.c @@ -185,6 +185,38 @@ static int test_cmp_calc_protection_pbmac(void) EXECUTE_TEST(execute_calc_protection_pbmac_test, tear_down); return result; } + +/* + * Regression test for the ossl_cmp_calc_protection() protectionAlg + * type-confusion DoS: a PKIMessage whose protectionAlg has the + * id-PasswordBasedMAC OID but carries a BOOLEAN parameter instead of the + * expected PBMParameter SEQUENCE. X509_ALGOR_get0() then returns the boolean's + * union member (0xff) via ppval; the unpatched code took the non-NULL ppval as + * a valid ASN1_STRING * and dereferenced 0xff, crashing with a near-NULL + * access. The fixed code must reject the malformed parameter and return NULL. + */ +static int test_cmp_calc_protection_pbmac_bad_alg_param(void) +{ + unsigned char sec_insta[] = { 'i', 'n', 's', 't', 'a' }; + X509_ALGOR *alg = NULL; + + SETUP_TEST_FIXTURE(CMP_PROTECT_TEST_FIXTURE, set_up); + if (!TEST_true(OSSL_CMP_CTX_set1_secretValue(fixture->cmp_ctx, + sec_insta, sizeof(sec_insta))) + || !TEST_ptr(fixture->msg = load_pkimsg(ip_PBM_f, libctx)) + || !TEST_ptr(alg = X509_ALGOR_new()) + || !TEST_true(X509_ALGOR_set0(alg, OBJ_nid2obj(NID_id_PasswordBasedMAC), + V_ASN1_BOOLEAN, (void *)1))) { + X509_ALGOR_free(alg); + tear_down(fixture); + fixture = NULL; + } else { + X509_ALGOR_free(fixture->msg->header->protectionAlg); + fixture->msg->header->protectionAlg = alg; + } + EXECUTE_TEST(execute_calc_protection_fails_test, tear_down); + return result; +} static int execute_MSG_protect_test(CMP_PROTECT_TEST_FIXTURE *fixture) { return TEST_int_eq(fixture->expected, @@ -609,6 +641,7 @@ int setup_tests(void) ADD_TEST(test_cmp_calc_protection_pkey_Ed); #endif ADD_TEST(test_cmp_calc_protection_pbmac); + ADD_TEST(test_cmp_calc_protection_pbmac_bad_alg_param); ADD_TEST(test_MSG_protect_with_msg_sig_alg_protection_plus_rsa_key); ADD_TEST(test_MSG_protect_with_certificate_and_key); From 48c9aaf6cc3195d92fa31a3afc39b984778b5700 Mon Sep 17 00:00:00 2001 From: Daniel Kubec Date: Tue, 21 Jul 2026 11:19:29 +0200 Subject: [PATCH 158/189] Fix Remote NULL deref in ossl_cmp_calc_protection() via crafted protectionAlg ossl_cmp_calc_protection() only checked whether the protectionAlg parameter (ppval) was NULL before treating it as a PBMParameter ASN1_STRING. X509_ALGOR_get0() does not validate the ASN.1 type of the parameter against what the caller expects. For id-PasswordBasedMAC, a crafted message can encode the parameter as a BOOLEAN instead of the expected PBMParameter SEQUENCE. Because the ASN1_TYPE value union overlays the boolean int on the pointer field, ppval comes back as a bogus non-NULL pointer (e.g. 0xff). Fixes CVE-2026-63076 Reviewed-by: Milan Broz Reviewed-by: Norbert Pocs Merge-date: Sat Aug 22 06:11:29 2026 --- crypto/cmp/cmp_protect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c index 1c8d2135fdab6..19d729614a1e5 100644 --- a/crypto/cmp/cmp_protect.c +++ b/crypto/cmp/cmp_protect.c @@ -66,7 +66,7 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PBM_SECRET); return NULL; } - if (ppval == NULL) { + if (pptype != V_ASN1_SEQUENCE || ppval == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION); return NULL; } From 7c98d79738549df92868e7dd9be4bbf061eed709 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 9 Jul 2026 15:34:30 -0400 Subject: [PATCH 159/189] Don't store ACK-only frames in TX history for QUIC. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When QUIC sends an ACK-only frame, there is no expectation that the peer will ack that ack (i.e. it is itself not ack-eliciting). However, our implementation stores these frames in the TX history regardless. In and of itself thats ok, but if a malicious client establishes a connection, and then drives the connection such that ack-only frames are forced from the peer (i.e. by sending numerous ping frames), and then withholding any subseqent acks for ack-eliciting data, like legitimate data, said malicious client can force inappropriate memory growth on the server, leading to potential DOS attacks. Don't store any ACK-only frames in the TX history to address this. Record it in our TX history so that the send window moves forward appropriately, but for ack-only frames, immediately remove it, since we don't expect to get an ack for them anyway. Initially authored by Opal Wright The initial proposal had some shortcommings in which the highest pn acked value was not accounted for which I have fixed with the assistance of Claude Assisted-by: Anthopic Sonnet 5 Fixes CVE-2026-63075 Reviewed-by: Saša Nedvědický Reviewed-by: Bob Beck Merge-date: Mon Aug 24 12:21:56 2026 --- include/internal/quic_ackm.h | 5 ++++ ssl/quic/quic_ackm.c | 32 +++++++++++++++++++++++++ ssl/quic/quic_txp.c | 46 ++++++++++++++++++++++++++---------- 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/include/internal/quic_ackm.h b/include/internal/quic_ackm.h index c0617da4855f6..aa402d294eca2 100644 --- a/include/internal/quic_ackm.h +++ b/include/internal/quic_ackm.h @@ -129,6 +129,11 @@ struct ossl_ackm_tx_pkt_st { }; int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt); + +/* + * Records transmission of a packet containing only ACK frames. + */ +int ossl_ackm_on_tx_ack_only_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt); int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes); #define OSSL_ACKM_ECN_NONE 0 diff --git a/ssl/quic/quic_ackm.c b/ssl/quic/quic_ackm.c index 20697cd7c4e83..5da8af882adee 100644 --- a/ssl/quic/quic_ackm.c +++ b/ssl/quic/quic_ackm.c @@ -1135,6 +1135,38 @@ int ossl_ackm_on_tx_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt) return 1; } +int ossl_ackm_on_tx_ack_only_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt) +{ + struct tx_pkt_history_st *h; + unsigned int pkt_space; + + if (pkt == NULL || pkt->pkt_space >= QUIC_PN_SPACE_NUM) + return 0; + + /* + * A packet containing only an ACK frame must not be treated as + * in-flight or ack-eliciting; if it were, ossl_ackm_on_tx_packet() + * below would (correctly) perform bytes-in-flight/timer/CC bookkeeping + * for a packet we are about to discard from history, which would be + * incorrect. + */ + if (pkt->is_inflight || pkt->is_ack_eliciting) + return 0; + + pkt_space = pkt->pkt_space; + + /* + * No one can expect ACK for packet which carries ACK frames only + * (ack_only packet). The ACKM does not need to keep record for ack_only + * packet. For ack_only packet the ACKM manager must be updated by the + * highest packet number which got sent. + */ + h = get_tx_history(ackm, pkt_space); + h->highest_sent = pkt->pkt_num; + + return 1; +} + int ossl_ackm_on_rx_datagram(OSSL_ACKM *ackm, size_t num_bytes) { /* No-op on the client. */ diff --git a/ssl/quic/quic_txp.c b/ssl/quic/quic_txp.c index 5ce8e77f61e08..24314f6b34b7b 100644 --- a/ssl/quic/quic_txp.c +++ b/ssl/quic/quic_txp.c @@ -2935,6 +2935,20 @@ static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp, return TXP_ERR_INTERNAL; } +static int txp_pkt_is_ack_only(const QUIC_TXPIM_PKT *tpkt) +{ + return tpkt->had_ack_frame + && !tpkt->ackm_pkt.is_inflight + && !tpkt->ackm_pkt.is_ack_eliciting + && !tpkt->had_handshake_done_frame + && !tpkt->had_max_data_frame + && !tpkt->had_max_streams_bidi_frame + && !tpkt->had_max_streams_uni_frame + && !tpkt->had_conn_close + && tpkt->retx_head == NULL + && ossl_quic_txpim_pkt_get_num_chunks(tpkt) == 0; +} + /* * Commits and queues a packet for transmission. There is no backing out after * this. @@ -2943,8 +2957,9 @@ static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp, * * - Sends the packet to the QTX for encryption and transmission; * - * - Records the packet as having been transmitted in FIFM. ACKM is informed, - * etc. and the TXPIM record is filed. + * - Records non-ACK-only packets as having been transmitted in FIFM. ACKM is + * informed, etc. and the TXPIM record is filed only when later callbacks + * need it. * * - Informs various subsystems of frames that were sent and clears frame * wanted flags so that we do not generate the same frames again. @@ -2971,7 +2986,7 @@ static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, uint32_t archetype, int *txpim_pkt_reffed) { - int rc = 1; + int ack_only, rc = 1; uint32_t enc_level = pkt->h.enc_level; uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level); QUIC_TXPIM_PKT *tpkt = pkt->tpkt; @@ -3015,28 +3030,35 @@ static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, return 0; /* alloc error */ } - /* Dispatch to FIFD. */ - if (!ossl_quic_fifd_pkt_commit(&txp->fifd, tpkt)) + ack_only = txp_pkt_is_ack_only(tpkt); + + /* Dispatch packets that need loss/retransmit callbacks to FIFD. */ + if (!ack_only && !ossl_quic_fifd_pkt_commit(&txp->fifd, tpkt)) return 0; /* * Transmission and Post-Packet Generation Bookkeeping * =================================================== * - * No backing out anymore - at this point the ACKM has recorded the packet - * as having been sent, so we need to increment our next PN counter, or - * the ACKM will complain when we try to record a duplicate packet with - * the same PN later. At this point actually sending the packet may still - * fail. In this unlikely event it will simply be handled as though it - * were a lost packet. + * No backing out anymore - at this point we need to increment our next PN + * counter, or the ACKM will complain when we try to record a duplicate + * packet with the same PN later. Non-ACK-only packets have also been + * recorded in ACKM, so if QTX write fails they are handled as though they + * were lost. ACK-only packets are not recorded and will be cleaned up by + * the caller. */ ++txp->next_pn[pn_space]; - *txpim_pkt_reffed = 1; + if (!ack_only) + *txpim_pkt_reffed = 1; /* Send the packet. */ if (!ossl_qtx_write_pkt(txp->args.qtx, &txpkt)) return 0; + if (ack_only + && !ossl_ackm_on_tx_ack_only_packet(txp->args.ackm, &tpkt->ackm_pkt)) + rc = 0; + /* * Record FC and stream abort frames as sent; deactivate streams which no * longer have anything to do. From 2501a3760fa38801b88a8d14075b6715c9b3e82d Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 30 Jun 2026 14:52:18 -0400 Subject: [PATCH 160/189] Add a test for restricting growth in cmp cert cache Test to ensure that if certs are rejected we don't add them unboundedly to the cmp contexts cert cache. Assisted-by: Claude sonnet 4.6 Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Merge-date: Mon Aug 24 12:42:34 2026 --- test/build.info | 6 +- test/cmp_extracerts_dos_test.c | 338 +++++++++++++++++++++++++++++++++ test/recipes/65-test_cmp_msg.t | 7 +- 3 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 test/cmp_extracerts_dos_test.c diff --git a/test/build.info b/test/build.info index d9a87832d5018..03ce682e0279d 100644 --- a/test/build.info +++ b/test/build.info @@ -768,7 +768,7 @@ IF[{- !$disabled{tests} -}] IF[{- !$disabled{cmp} -}] PROGRAMS{noinst}=cmp_asn_test cmp_ctx_test cmp_status_test cmp_hdr_test \ cmp_protect_test cmp_msg_test cmp_vfy_test \ - cmp_server_test cmp_client_test + cmp_server_test cmp_client_test cmp_extracerts_dos_test ENDIF SOURCE[cmp_asn_test]=cmp_asn_test.c helpers/cmp_testlib.c @@ -795,6 +795,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[cmp_msg_test]=.. ../include ../apps/include DEPEND[cmp_msg_test]=../libcrypto.a libtestutil.a + SOURCE[cmp_extracerts_dos_test]=cmp_extracerts_dos_test.c helpers/cmp_testlib.c + INCLUDE[cmp_extracerts_dos_test]=.. ../include ../apps/include + DEPEND[cmp_extracerts_dos_test]=../libcrypto.a libtestutil.a + SOURCE[cmp_vfy_test]=cmp_vfy_test.c helpers/cmp_testlib.c INCLUDE[cmp_vfy_test]=.. ../include ../apps/include DEPEND[cmp_vfy_test]=../libcrypto.a libtestutil.a diff --git a/test/cmp_extracerts_dos_test.c b/test/cmp_extracerts_dos_test.c new file mode 100644 index 0000000000000..273281c94376a --- /dev/null +++ b/test/cmp_extracerts_dos_test.c @@ -0,0 +1,338 @@ +/* + * Copyright 2026 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 + */ + +/* + * Regression test for: CMP server unauthenticated memory/CPU DoS via + * cached extraCerts on failed protection checks. + * + * Root cause (crypto/cmp/cmp_vfy.c, ossl_cmp_msg_check_update(), current + * master as of this writing): + * + * res = ossl_x509_add_certs_new(&ctx->untrusted, msg->extraCerts, ...); + * ... + * res = OSSL_CMP_validate_msg(ctx, msg) || (cb...); // may be 0 (rejected) + * + * if (ctx->noCacheExtraCerts) // <-- rollback is + * while (num_added-- > 0) // gated on this + * X509_free(sk_X509_shift(ctx->untrusted)); // flag only, NOT + * // on the + * // validation + * // result (res) + * + * if (!res) { ...; return 0; } // certs from a REJECTED msg are kept + * + * This test exercises ossl_cmp_msg_check_update() directly -- no sockets, + * no HTTP server, no apps/cmp.c -- and asserts on the resulting size of + * ctx->untrusted. It builds a genuinely PBM-protected OSSL_CMP_MSG using + * the project's own internal message-creation function + * (ossl_cmp_genm_new(), same one exercised in test/cmp_msg_test.c) so the + * message is not hand-crafted to "look" rejectable -- it is rejected for a + * real reason (the receiving ctx has no matching secret configured), the + * same way OSSL_CMP_validate_msg() would reject any unauthenticated CMP + * request in the field. + * + * Expected results: + * - BEFORE the fix: untrusted_count_after == untrusted_count_before + N + * (every rejected message's extraCerts persist) + * - AFTER the fix: untrusted_count_after == untrusted_count_before + * (rejected messages leave no residue) + */ + +#include "helpers/cmp_testlib.h" + +#define NUM_REJECTED_REQUESTS 25 /* "attacker" sends this many distinct certs */ + +typedef struct test_fixture { + const char *test_case_name; + OSSL_CMP_CTX *server_ctx; /* long-lived ctx under test, mirrors srv_ctx->ctx */ +} CMP_DOS_TEST_FIXTURE; + +static OSSL_LIB_CTX *libctx = NULL; + +static CMP_DOS_TEST_FIXTURE *set_up(const char *const test_case_name) +{ + CMP_DOS_TEST_FIXTURE *fixture; + + if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture)))) + return NULL; + fixture->test_case_name = test_case_name; + + if (!TEST_ptr(fixture->server_ctx = OSSL_CMP_CTX_new(libctx, NULL))) { + OPENSSL_free(fixture); + return NULL; + } + /* + * Deliberately do NOT call OSSL_CMP_CTX_set1_secretValue() on the + * server ctx. Per OSSL_CMP_validate_msg() (crypto/cmp/cmp_vfy.c): + * case NID_id_PasswordBasedMAC: + * if (ctx->secretValue == NULL) { + * ossl_cmp_info(ctx, "no secret available for verifying.."); + * ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION); + * return 0; + * } + * so every PBM-protected message this ctx receives is unconditionally + * rejected -- a deterministic, content-independent rejection path that + * models "missing or invalid protection" from the report's repro + * steps, without needing to forge a bad MAC by hand. + * ctx->noCacheExtraCerts is left at its default (0), exactly as in the + * vulnerable deployment ("not setting -no_cache_extracerts"). + */ + return fixture; +} + +static void tear_down(CMP_DOS_TEST_FIXTURE *fixture) +{ + if (fixture == NULL) + return; + OSSL_CMP_CTX_free(fixture->server_ctx); + OPENSSL_free(fixture); +} + +/* Generates a throwaway EC P-256 keypair; cheap, and key strength is + * irrelevant to this test. */ +static EVP_PKEY *generate_throwaway_keypair(void) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + + if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))) + return NULL; + if (!TEST_int_gt(EVP_PKEY_keygen_init(pctx), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set_group_name(pctx, "P-256"), 0) + || !TEST_int_gt(EVP_PKEY_generate(pctx, &pkey), 0)) + pkey = NULL; + EVP_PKEY_CTX_free(pctx); + return pkey; +} + +/* + * Builds a minimal, self-signed, syntactically valid X509 with a unique + * subject/issuer per index, so X509_ADD_FLAG_NO_DUP cannot collapse it + * with any other generated cert (matching the report's exploitation + * requirement of "unique certificates across requests"). + */ +static X509 *generate_unique_self_signed_cert(EVP_PKEY *pkey, int index) +{ + X509 *cert = NULL; + X509_NAME *name = NULL; + ASN1_INTEGER *serial = NULL; + char cn[64]; + + BIO_snprintf(cn, sizeof(cn), "attacker-cert-%d", index); + + if (!TEST_ptr(cert = X509_new()) + || !TEST_true(X509_set_version(cert, X509_VERSION_3))) + goto err; + + if (!TEST_ptr(serial = ASN1_INTEGER_new()) + || !TEST_true(ASN1_INTEGER_set(serial, 1000L + index)) + || !TEST_true(X509_set_serialNumber(cert, serial))) + goto err; + + if (!TEST_ptr(X509_gmtime_adj(X509_getm_notBefore(cert), 0)) + || !TEST_ptr(X509_gmtime_adj(X509_getm_notAfter(cert), + 60L * 60L * 24L * 365L))) + goto err; + + if (!TEST_true(X509_set_pubkey(cert, pkey))) + goto err; + + if (!TEST_ptr(name = X509_NAME_new()) + || !TEST_true(X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, + (unsigned char *)"cmp-dos-test", + -1, -1, 0)) + || !TEST_true(X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (unsigned char *)cn, + -1, -1, 0)) + || !TEST_true(X509_set_subject_name(cert, name)) + || !TEST_true(X509_set_issuer_name(cert, name))) + goto err; + + if (!TEST_int_gt(X509_sign(cert, pkey, EVP_sha256()), 0)) + goto err; + + X509_NAME_free(name); + ASN1_INTEGER_free(serial); + return cert; + +err: + X509_NAME_free(name); + ASN1_INTEGER_free(serial); + X509_free(cert); + return NULL; +} + +/* + * Builds a real, internally consistent, PBM-protected CMP GenMsg carrying + * exactly one never-before-seen self-signed cert as its sole extraCert. + * Uses a throwaway *client*-side OSSL_CMP_CTX purely to drive message + * creation/protection (ossl_cmp_genm_new() both builds the body and calls + * ossl_cmp_msg_protect() internally, same as in test/cmp_msg_test.c). The + * client ctx's secret is intentionally never shared with the server ctx + * under test, so the message is protected (syntactically well-formed, + * non-empty protection field) but NOT verifiable by the receiver -- this + * is what "missing or invalid protection" means for a real attacker who + * has no credentials, not an empty/garbage protection field. + */ +static OSSL_CMP_MSG *build_rejectable_msg_with_unique_cert(int index) +{ + OSSL_CMP_CTX *client_ctx = NULL; + OSSL_CMP_MSG *msg = NULL; + EVP_PKEY *pkey = NULL; + X509 *fresh_cert = NULL; + STACK_OF(X509) *extra = NULL; + unsigned char ref[16], secret[16]; + + if (!TEST_ptr(client_ctx = OSSL_CMP_CTX_new(libctx, NULL))) + goto err; + + if (!TEST_ptr(pkey = generate_throwaway_keypair()) + || !TEST_ptr(fresh_cert = generate_unique_self_signed_cert(pkey, index))) + goto err; + + if (!TEST_ptr(extra = sk_X509_new_null()) + || !TEST_true(sk_X509_push(extra, fresh_cert))) + goto err; + fresh_cert = NULL; /* ownership now with the stack */ + + if (!TEST_true(OSSL_CMP_CTX_set1_extraCertsOut(client_ctx, extra))) + goto err; + + /* PBM protection with a secret the server ctx will never be given */ + memset(ref, (unsigned char)(0xA0 + (index & 0x0F)), sizeof(ref)); + memset(secret, (unsigned char)(0x50 + (index & 0x0F)), sizeof(secret)); + if (!TEST_true(OSSL_CMP_CTX_set_option(client_ctx, + OSSL_CMP_OPT_UNPROTECTED_SEND, 0)) + || !TEST_true(OSSL_CMP_CTX_set1_referenceValue(client_ctx, ref, + sizeof(ref))) + || !TEST_true(OSSL_CMP_CTX_set1_secretValue(client_ctx, secret, + sizeof(secret)))) + goto err; + + /* GenMsg is the lightest standard body type for this purpose */ + if (!TEST_ptr(msg = ossl_cmp_genm_new(client_ctx))) + goto err; + + sk_X509_pop_free(extra, X509_free); + X509_free(fresh_cert); + EVP_PKEY_free(pkey); + OSSL_CMP_CTX_free(client_ctx); + return msg; + +err: + sk_X509_pop_free(extra, X509_free); + X509_free(fresh_cert); + EVP_PKEY_free(pkey); + OSSL_CMP_CTX_free(client_ctx); + OSSL_CMP_MSG_free(msg); + return NULL; +} + +/* + * Core assertion: N distinct rejected requests must not grow + * server_ctx->untrusted at all. + * + * Before the fix this fails with e.g.: + * ERROR: untrusted count after (25) != count before (0) + */ +static int execute_no_unbounded_growth_test(CMP_DOS_TEST_FIXTURE *fixture) +{ + OSSL_CMP_CTX *server_ctx = fixture->server_ctx; + int count_before, count_after, i; + + count_before = sk_X509_num(OSSL_CMP_CTX_get0_untrusted(server_ctx)); + if (count_before < 0) + count_before = 0; + + for (i = 0; i < NUM_REJECTED_REQUESTS; i++) { + OSSL_CMP_MSG *msg = build_rejectable_msg_with_unique_cert(i); + int check_result; + + if (!TEST_ptr(msg)) + return 0; + + check_result = ossl_cmp_msg_check_update(server_ctx, msg, NULL, 0); + OSSL_CMP_MSG_free(msg); + + if (!TEST_int_eq(check_result, 0)) { + TEST_note("expected request #%d to be rejected (server ctx has" + " no matching PBM secret) but it was accepted -- test" + " setup is wrong, not exercising the rejection path", + i); + return 0; + } + } + + count_after = sk_X509_num(OSSL_CMP_CTX_get0_untrusted(server_ctx)); + if (count_after < 0) + count_after = 0; + + if (!TEST_int_eq(count_after, count_before)) { + TEST_note("server_ctx->untrusted grew from %d to %d after %d" + " rejected requests -- failed-request extraCerts caching" + " bug is present (see ossl_cmp_msg_check_update() in" + " crypto/cmp/cmp_vfy.c)", + count_before, count_after, + NUM_REJECTED_REQUESTS); + return 0; + } + return 1; +} + +/* + * Single-request variant of the same check, useful in isolation since it + * pins down that even ONE rejected request leaves no residue -- ruling out + * X509_ADD_FLAG_NO_DUP coincidentally masking the bug in the N-request test. + */ +static int execute_single_rejected_request_test(CMP_DOS_TEST_FIXTURE *fixture) +{ + OSSL_CMP_CTX *server_ctx = fixture->server_ctx; + OSSL_CMP_MSG *msg = build_rejectable_msg_with_unique_cert(999); + int count_before, count_after; + + if (!TEST_ptr(msg)) + return 0; + + count_before = sk_X509_num(OSSL_CMP_CTX_get0_untrusted(server_ctx)); + if (count_before < 0) + count_before = 0; + + if (!TEST_int_eq(ossl_cmp_msg_check_update(server_ctx, msg, NULL, 0), 0)) { + OSSL_CMP_MSG_free(msg); + return 0; + } + OSSL_CMP_MSG_free(msg); + + count_after = sk_X509_num(OSSL_CMP_CTX_get0_untrusted(server_ctx)); + if (count_after < 0) + count_after = 0; + + return TEST_int_eq(count_after, count_before); +} + +static int test_single_rejected_request_leaves_no_residue(void) +{ + SETUP_TEST_FIXTURE(CMP_DOS_TEST_FIXTURE, set_up); + EXECUTE_TEST(execute_single_rejected_request_test, tear_down); + return result; +} + +static int test_no_unbounded_growth_on_rejected_requests(void) +{ + SETUP_TEST_FIXTURE(CMP_DOS_TEST_FIXTURE, set_up); + EXECUTE_TEST(execute_no_unbounded_growth_test, tear_down); + return result; +} + +int setup_tests(void) +{ + ADD_TEST(test_single_rejected_request_leaves_no_residue); + ADD_TEST(test_no_unbounded_growth_on_rejected_requests); + return 1; +} diff --git a/test/recipes/65-test_cmp_msg.t b/test/recipes/65-test_cmp_msg.t index d104576a9d60e..19c17efca4eab 100644 --- a/test/recipes/65-test_cmp_msg.t +++ b/test/recipes/65-test_cmp_msg.t @@ -20,17 +20,22 @@ use lib srctop_dir('Configurations'); use lib bldtop_dir('.'); my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); +my $no_ec = disabled('ec'); plan skip_all => "This test is not supported in a no-cmp build" if disabled("cmp"); -plan tests => 2 + ($no_fips ? 0 : 1); #fips test +plan tests => 2 + ($no_fips ? 0 : 1) + ($no_ec ? 0 : 1); #fips test and ec test my @basic_cmd = ("cmp_msg_test", data_file("new.key"), data_file("server.crt"), data_file("pkcs10.der")); +unless ($no_ec) { + ok(run(test(["cmp_extracerts_dos_test"]))); +} + ok(run(test([@basic_cmd, "none"]))); ok(run(test([@basic_cmd, "default", srctop_file("test", "default.cnf")]))); From 75360af9650d4e0c82ba0050c5c9912cd79e54af Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 30 Jun 2026 15:09:01 -0400 Subject: [PATCH 161/189] Fix unbounded cert cache growth in cmp If a remote user sends cmp messages to a server with a list of extraCerts and the message is rejected, the extraCerts from the message remain in the server contexts untrusted certificate stack. This exposes servers with long lived ctx objects to denial of service attacks in which an attacker sends messages intending to be rejected with a large list of additional cerificated repeatedly, forcing the server to store them indefinately. Fix it by rolling back the added extra certs if the message is rejected, using the same method we do when the context is configured to not do caching at all. Fixes openssl/srt#224 Fixes CVE-2026-63074 Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Merge-date: Mon Aug 24 12:42:35 2026 --- crypto/cmp/cmp_vfy.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 28dd74f73066f..71562241e9157 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -778,8 +778,13 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, res = 1; /* support more aggressive fuzzing by letting invalid msg pass */ #endif - /* remove extraCerts again if not caching */ - if (ctx->noCacheExtraCerts) + /* + * remove extraCerts again if not caching + * or if we failed validation above, lest a remote user + * starts sending us lots of certificates in invalid messages + * leading to a DOS from unbounded certificate stack growth + */ + if (ctx->noCacheExtraCerts || res != 1) while (num_added-- > 0) X509_free(sk_X509_shift(ctx->untrusted)); From d0af20478688a6aa2f59d61caa3f82136b181d7f Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Sat, 27 Jun 2026 01:02:53 +1000 Subject: [PATCH 162/189] Handle signature_algorithms_cert extension in key-only context Servers or clients that configure only a private key in expectation of always negotiating use of RFC7250 raw public keys failed to handle the "signature_algorithms_cert" extension. The issue is now resolved and the RPK tests now check that key-only configurations are robust also when the extension is sent by the peer. Key-only configurations are quite uncommon. As a best practice, RPK-capable servers and clients pair their private key with a (possibly self-signed) certificate, enabling fallback to X.509 handshakes with non-RPK peers. Fixes CVE-2026-14457 Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz Reviewed-by: Norbert Pocs Merge-date: Mon Aug 24 12:49:30 2026 --- ssl/t1_lib.c | 14 ++++++++++ test/rpktest.c | 76 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index a4d212c2550f0..ef1114172a283 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -4442,6 +4442,20 @@ static int check_cert_usable(SSL_CONNECTION *s, const SIGALG_LOOKUP *sig, if (supported <= 0) return 0; + /* + * When RPK is negotiated there are no certificate signatures to + * constrain, and there may not even be a certificate configured. + */ + if (TLSEXT_cert_type_rpk == (s->server ? s->ext.server_cert_type : s->ext.client_cert_type)) + return 1; + + /* + * RPK was enabled, adding candidate private-key-only slots, but was not + * negotiated, so the key-only slot is not usable. + */ + if (x == NULL) + return 0; + /* * The TLS 1.3 signature_algorithms_cert extension places restrictions * on the sigalg with which the certificate was signed (by its issuer). diff --git a/test/rpktest.c b/test/rpktest.c index 338c33f80cb5b..f3de1a8b143d9 100644 --- a/test/rpktest.c +++ b/test/rpktest.c @@ -38,6 +38,37 @@ static OSSL_PROVIDER *defctxnull = NULL; static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 }; static const unsigned char SID_CTX[] = { 'r', 'p', 'k' }; +/* + * Wire form of a SignatureSchemeList that lists rsa_pkcs1_sha256 + * and ed448 -- between them they cover the issuer signature on + * every cert this file loads from test/certs + * (sha256WithRSAEncryption for the RSA/ECDSA/Ed25519 leaves and + * ED448 for the Ed448 leaf), so the extension is harmless when + * the handshake is non-RPK and the server's check_cert_usable() + * has to walk the list against a real cert. When RPK is + * negotiated check_cert_usable() returns early without inspecting + * the list, and when the slot is an RPK-listed key-only slot but + * X509 was negotiated check_cert_usable() returns 0 on the x == + * NULL path -- the inevitable outcome, now discovered earlier. + * + * Payload: length, rsa_pkcs1_sha256, ed448 + */ +static const unsigned char sigalgs_cert_payload[] = { + 0x00, 0x04, + 0x04, 0x01, + 0x08, 0x08 +}; + +static int sigalgs_cert_add_cb(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char **out, size_t *outlen, + X509 *x, size_t chainidx, int *al, void *add_arg) +{ + *out = sigalgs_cert_payload; + *outlen = sizeof(sigalgs_cert_payload); + return 1; +} + static int rpk_verify_client_cb(int ok, X509_STORE_CTX *ctx) { int err = X509_STORE_CTX_get_error(ctx); @@ -255,18 +286,43 @@ static int test_rpk(int idx) /* NEW */ SSL_CTX_set_verify(cctx, SSL_VERIFY_PEER, rpk_verify_client_cb); - if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, - NULL, NULL))) + /* + * Send signature_algorithms_cert in every ClientHello, and in + * every TLS 1.3 CertificateRequest. The OpenSSL stack doesn't + * construct this extension by default in either direction, so + * register a custom add hook on both ends. This exercises the + * three distinct paths through check_cert_usable() on whichever + * side receives the extension: + * - RPK was negotiated for this side's cert -- early return 1, + * list contents ignored. + * - RPK was offered but X509 was negotiated and this side's + * slot holds only a private key -- x == NULL, return 0 + * (any peer-sent signature_algorithms_cert against a key-only + * slot would otherwise trigger a crash). + * - X509 negotiated with a real cert -- walk the list, find + * a match against the issuer's signature algorithm. + * The server's registration only fires on TLS 1.3 connections + * where the server requests a client certificate (case 2, 9, + * 10 etc.); on TLS 1.2 the sigalgs travel inside the + * CertificateRequest body, not as a separate extension. + */ + if (!TEST_true(SSL_CTX_add_custom_ext(cctx, + TLSEXT_TYPE_signature_algorithms_cert, + SSL_EXT_CLIENT_HELLO, + sigalgs_cert_add_cb, NULL, NULL, + NULL, NULL)) + || !TEST_true(SSL_CTX_add_custom_ext(sctx, + TLSEXT_TYPE_signature_algorithms_cert, + SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + sigalgs_cert_add_cb, NULL, NULL, + NULL, NULL)) + || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_int_gt(SSL_dane_enable(serverssl, NULL), 0) + || !TEST_int_gt(SSL_dane_enable(clientssl, "example.com"), 0) + || !TEST_int_eq(SSL_use_PrivateKey_file(serverssl, privkey_file, SSL_FILETYPE_PEM), 1)) goto end; - if (!TEST_int_gt(SSL_dane_enable(serverssl, NULL), 0)) - goto end; - if (!TEST_int_gt(SSL_dane_enable(clientssl, "example.com"), 0)) - goto end; - - /* Set private key and certificate */ - if (!TEST_int_eq(SSL_use_PrivateKey_file(serverssl, privkey_file, SSL_FILETYPE_PEM), 1)) - goto end; /* Only a private key */ if (idx == 1) { if (idx_server_server_rpk == 0 || idx_client_server_rpk == 0) { From 0cc20b322639919aa423e90799d9a57c3b4b76ca Mon Sep 17 00:00:00 2001 From: Norbert Pocs Date: Mon, 20 Jul 2026 14:10:47 +0200 Subject: [PATCH 163/189] CMP unexpected sender DN used as format string in ERR_raise_data() ossl_cmp_msg_check_update() converts an unexpected CMP response sender DN with X509_NAME_oneline() and passes that peer-controlled string directly as the format argument to ERR_raise_data(). Printable percent characters survive the DN conversion, so a sender such as CN=%s%n reaches vsnprintf() as active format syntax without matching varargs. Fixes: CVE-2026-63073 Original patch by: Filipe Casal of Trail of Bits in collaboration with OpenAI Signed-off-by: Norbert Pocs Reviewed-by: Milan Broz Reviewed-by: Igor Ustinov Merge-date: Mon Aug 24 13:02:10 2026 --- crypto/cmp/cmp_vfy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 71562241e9157..e79adb09d3879 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -734,7 +734,7 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, "expected sender", expected_sender)) { str = X509_NAME_oneline(actual_sender, NULL, 0); ERR_raise_data(ERR_LIB_CMP, CMP_R_UNEXPECTED_SENDER, - str != NULL ? str : ""); + "%s", str != NULL ? str : ""); OPENSSL_free(str); return 0; } From 9d838f67fec7ff72cf02322856f1220738a17430 Mon Sep 17 00:00:00 2001 From: Norbert Pocs Date: Wed, 22 Jul 2026 21:34:49 +0200 Subject: [PATCH 164/189] Add test for CVE-2026-63073 Signed-off-by: Norbert Pocs Reviewed-by: Milan Broz Reviewed-by: Igor Ustinov Merge-date: Mon Aug 24 13:02:11 2026 --- test/cmp_vfy_test.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/cmp_vfy_test.c b/test/cmp_vfy_test.c index 70d776c0f572e..cbfe78911d6eb 100644 --- a/test/cmp_vfy_test.c +++ b/test/cmp_vfy_test.c @@ -572,6 +572,55 @@ static int test_msg_check_recipient_nonce_bad(void) } #endif +/* Regression test for CVE-2026-63073 */ +static int execute_msg_check_update_malicious_sender(CMP_VFY_TEST_FIXTURE *fixture) +{ + const char *data = NULL; + unsigned long err; + + if (!TEST_int_eq(ossl_cmp_msg_check_update(fixture->cmp_ctx, fixture->msg, NULL, 0), 0) + || !TEST_int_ne((err = ERR_peek_last_error_all(NULL, NULL, NULL, &data, NULL)), 0) + || !TEST_int_eq(ERR_GET_LIB(err), ERR_LIB_CMP) + || !TEST_int_eq(ERR_GET_REASON(err), CMP_R_UNEXPECTED_SENDER) + || !TEST_ptr(data) + || !TEST_str_eq(data, "/CN=%n")) + return 0; + return 1; +} + +static int test_msg_check_update_malicious_sender(void) +{ + OSSL_CMP_PKIHEADER *hdr; + X509_NAME *expected = X509_NAME_new(); + X509_NAME *actual = X509_NAME_new(); + + if (expected == NULL || actual == NULL) { + X509_NAME_free(expected); + return 0; + } + + SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); + if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f, libctx)) + || !TEST_ptr(hdr = OSSL_CMP_MSG_get0_header(fixture->msg)) + || !TEST_int_eq(X509_NAME_add_entry_by_txt(expected, "CN", MBSTRING_ASC, + (unsigned char *)"%n", -1, -1, 0), + 1) + || !TEST_int_eq(X509_NAME_add_entry_by_txt(actual, "CN", MBSTRING_ASC, + (unsigned char *)"actual", -1, -1, 0), + 1) + || !TEST_int_eq(ossl_cmp_hdr_set1_sender(hdr, expected), 1) + || !TEST_int_eq(OSSL_CMP_CTX_set1_expected_sender(fixture->cmp_ctx, actual), 1)) { + X509_NAME_free(expected); + X509_NAME_free(actual); + tear_down(fixture); + return 0; + } + EXECUTE_TEST(execute_msg_check_update_malicious_sender, tear_down); + X509_NAME_free(expected); + X509_NAME_free(actual); + return result; +} + void cleanup_tests(void) { X509_free(srvcert); @@ -712,6 +761,7 @@ int setup_tests(void) #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ADD_TEST(test_msg_check_recipient_nonce_bad); #endif + ADD_TEST(test_msg_check_update_malicious_sender); return 1; From d384598500595e963383d9a17bf2a2ed0b607434 Mon Sep 17 00:00:00 2001 From: Daniel Kubec Date: Thu, 23 Jul 2026 11:09:55 +0200 Subject: [PATCH 165/189] Add test for CVE-2026-63072 Assisted-by: Claude:claude-fable-5 Reviewed-by: Milan Broz Reviewed-by: Andrew Dinh Merge-date: Mon Aug 24 14:42:04 2026 --- test/cmsapitest.c | 103 +++++++++++++++++++++++++++++++++- test/recipes/80-test_cmsapi.t | 3 +- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/test/cmsapitest.c b/test/cmsapitest.c index 2b5d08329ba68..cc58641e89a34 100644 --- a/test/cmsapitest.c +++ b/test/cmsapitest.c @@ -22,6 +22,7 @@ static EVP_PKEY *privkey = NULL; static char *derin = NULL; static char *too_long_iv_cms_in = NULL; static char *pwri_kek_oob_der_in = NULL; +static char *ec_recip_in = NULL; /* * This is our bad cms data, it contains an AuthEnvelopedData field @@ -739,7 +740,100 @@ static int test_pwri_kek_unwrap_short_encrypted_key(void) return ret; } -OPT_TEST_DECLARE_USAGE("certfile privkeyfile derfile tooLongIVpem pwriKekOobDer\n") +#ifndef OPENSSL_NO_EC + +/* + * Regression test for CVE-2026-63072: an 8-byte out-of-bounds heap write + * reachable through CMS_decrypt() when a KeyAgreeRecipientInfo names an + * id-aesNNN-wrap-pad key-wrap OID. CMS sizes the unwrap output buffer from + * the cipher's length query (inlen - 8), but AES-WRAP-PAD unwrap cleanses + * inlen bytes of it on every RFC 5649 integrity-failure path. + * + * We build a valid ECDH KARI message (which uses non-padded id-aes256-wrap), + * flip the single OID byte an attacker would flip on the wire to turn it into + * id-aes256-wrap-pad (key length unchanged), and decrypt with the matching + * private key. The unwrap must fail its integrity check without writing past + * the CMS-allocated buffer; CMS_decrypt() must fail cleanly. Under a + * memory-checking build (e.g. valgrind) the overflow is flagged directly. + */ +static int test_kari_wrap_pad_unwrap_overflow(void) +{ + /* DER encoding of the id-aes256-wrap OID (2.16.840.1.101.3.4.1.45). */ + static const unsigned char aes256_wrap_oid[] = { + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2d + }; + int ret = 0; + X509 *eccert = NULL; + EVP_PKEY *eckey = NULL; + BIO *certbio = NULL, *keybio = NULL, *msgbio = NULL, *outbio = NULL; + STACK_OF(X509) *recips = NULL; + CMS_ContentInfo *cms = NULL, *cms2 = NULL; + unsigned char *der = NULL; + const unsigned char *p; + int derlen, i, patched = 0; + const char *msg = "secret content for kari"; + + if ((certbio = BIO_new_file(ec_recip_in, "r")) == NULL + || PEM_read_bio_X509(certbio, &eccert, NULL, NULL) == NULL + || (keybio = BIO_new_file(ec_recip_in, "r")) == NULL + || PEM_read_bio_PrivateKey(keybio, &eckey, NULL, NULL) == NULL) { + goto end; + } + + if (!TEST_ptr(recips = sk_X509_new_null()) + || !TEST_int_gt(sk_X509_push(recips, eccert), 0)) + goto end; + + /* Build a normal ECDH KARI message; it uses non-padded id-aes256-wrap. */ + if (!TEST_ptr(msgbio = BIO_new_mem_buf(msg, (int)strlen(msg))) + || !TEST_ptr(cms = CMS_encrypt(recips, msgbio, EVP_aes_256_cbc(), + CMS_BINARY))) + goto end; + + if (!TEST_int_gt(derlen = i2d_CMS_ContentInfo(cms, &der), 0)) + goto end; + + /* Swap id-aes256-wrap -> id-aes256-wrap-pad (0x2d -> 0x30). */ + for (i = 0; i + (int)sizeof(aes256_wrap_oid) <= derlen; i++) { + if (memcmp(der + i, aes256_wrap_oid, sizeof(aes256_wrap_oid)) == 0) { + der[i + sizeof(aes256_wrap_oid) - 1] = 0x30; + patched = 1; + break; + } + } + if (!TEST_true(patched)) + goto end; + + p = der; + if (!TEST_ptr(cms2 = d2i_CMS_ContentInfo(NULL, &p, derlen))) + goto end; + + /* + * The wrap-pad unwrap fails the AIV check; with the fix it does so without + * writing past the CMS-allocated buffer. CMS_decrypt() must fail cleanly. + */ + if (!TEST_ptr(outbio = BIO_new(BIO_s_mem())) + || !TEST_false(CMS_decrypt(cms2, eckey, eccert, NULL, outbio, 0))) + goto end; + + ret = 1; +end: + ERR_clear_error(); + OPENSSL_free(der); + sk_X509_free(recips); + CMS_ContentInfo_free(cms); + CMS_ContentInfo_free(cms2); + BIO_free(certbio); + BIO_free(keybio); + BIO_free(msgbio); + BIO_free(outbio); + X509_free(eccert); + EVP_PKEY_free(eckey); + return ret; +} +#endif + +OPT_TEST_DECLARE_USAGE("certfile privkeyfile derfile tooLongIVpem pwriKekOobDer ecrecip\n") int setup_tests(void) { @@ -755,7 +849,8 @@ int setup_tests(void) || !TEST_ptr(privkeyin = test_get_argument(1)) || !TEST_ptr(derin = test_get_argument(2)) || !TEST_ptr(too_long_iv_cms_in = test_get_argument(3)) - || !TEST_ptr(pwri_kek_oob_der_in = test_get_argument(4))) + || !TEST_ptr(pwri_kek_oob_der_in = test_get_argument(4)) + || !TEST_ptr(ec_recip_in = test_get_argument(5))) return 0; certbio = BIO_new_file(certin, "r"); @@ -796,6 +891,10 @@ int setup_tests(void) ADD_ALL_TESTS(test_d2i_CMS_decode, 2); ADD_TEST(test_cms_aesgcm_iv_too_long); ADD_TEST(test_pwri_kek_unwrap_short_encrypted_key); + +#ifndef OPENSSL_NO_EC + ADD_TEST(test_kari_wrap_pad_unwrap_overflow); +#endif return 1; } diff --git a/test/recipes/80-test_cmsapi.t b/test/recipes/80-test_cmsapi.t index 3d1dae8464646..1f5f7ae233ee9 100644 --- a/test/recipes/80-test_cmsapi.t +++ b/test/recipes/80-test_cmsapi.t @@ -20,5 +20,6 @@ ok(run(test(["cmsapitest", srctop_file("test", "certs", "servercert.pem"), srctop_file("test", "certs", "serverkey.pem"), srctop_file("test", "recipes", "80-test_cmsapi_data", "encryptedData.der"), srctop_file("test", "recipes", "80-test_cmsapi_data", "encDataWithTooLongIV.pem"), - srctop_file("test", "recipes", "80-test_cmsapi_data", "cms_pwri_kek_oob.der")])), + srctop_file("test", "recipes", "80-test_cmsapi_data", "cms_pwri_kek_oob.der"), + srctop_file("test", "smime-certs", "smec1.pem")])), "running cmsapitest"); From 87784ad619af36b8807c2044b3940006fccc1e42 Mon Sep 17 00:00:00 2001 From: Daniel Kubec Date: Sun, 2 Aug 2026 00:23:39 +0000 Subject: [PATCH 166/189] Fix heap buffer overflow (8-byte OOB write) in AES-WRAP-PAD unwrap On its integrity-failure paths that primitive writes and cleanses up to inlen bytes of the output buffer. Size the buffer for that worst case so a failed unwrap cannot write past the allocation. Fixes CVE-2026-63072 Reviewed-by: Milan Broz Reviewed-by: Andrew Dinh Merge-date: Mon Aug 24 14:42:05 2026 --- crypto/cms/cms_kari.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c index 519e19bc087d1..bc08f2d4d9f15 100644 --- a/crypto/cms/cms_kari.c +++ b/crypto/cms/cms_kari.c @@ -218,6 +218,7 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, unsigned char *out = NULL; size_t out_alloc_len = 0; int outlen; + size_t outsize; keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx); if (keklen > EVP_MAX_KEY_LENGTH) @@ -231,7 +232,13 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, /* obtain output length of ciphered key */ if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) goto err; - out = OPENSSL_malloc(outlen); + /* + * On its integrity-failure paths that primitive writes and cleanses up to + * inlen bytes of the output buffer. Size the buffer for that worst case so + * a failed unwrap cannot write past the allocation. + */ + outsize = (size_t)outlen < inlen ? inlen : (size_t)outlen; + out = OPENSSL_malloc(outsize); if (out == NULL) goto err; out_alloc_len = (size_t)outlen; From 4808b5d64176451f3d93d87d0ac9c81a9b13fb23 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 23 Jun 2026 11:53:17 +0100 Subject: [PATCH 167/189] Avoid full read buffer allocation when buffering DTLS next-epoch records dtls_rlayer_buffer_record() buffers records that arrive early for the next epoch while a handshake is in progress. It did this by taking ownership of the entire live read buffer (sized for the largest possible record, ~16.7KB) and allocating a brand new one to carry on reading, regardless of how small the buffered record actually was. With the queue capped at 100 entries, a peer could send around 100 tiny bogus next-epoch records (~14 bytes each on the wire) and force around 1.7MB of heap allocation per connection. Instead, copy only the record's own on-wire bytes (header and ciphertext) into the queue entry, and leave the live read buffer untouched. Memory use is now proportional to what the peer actually sends. Fixes CVE-2026-54874 Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Andrew Dinh Merge-date: Mon Aug 24 15:38:54 2026 --- ssl/record/methods/dtls_meth.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/ssl/record/methods/dtls_meth.c b/ssl/record/methods/dtls_meth.c index 8cbd7678e193b..22e1afe9ad9ed 100644 --- a/ssl/record/methods/dtls_meth.c +++ b/ssl/record/methods/dtls_meth.c @@ -299,29 +299,26 @@ static int dtls_rlayer_buffer_record(OSSL_RECORD_LAYER *rl, struct pqueue_st *qu return -1; } - rdata->packet = rl->packet; + /* + * Take a copy of just this record's on-wire bytes (header + ciphertext) + * rather than the whole (much larger) read buffer. The live rl->rbuf is + * left untouched and continues to be used for subsequent reads. + */ rdata->packet_length = rl->packet_length; - memcpy(&(rdata->rbuf), &rl->rbuf, sizeof(TLS_BUFFER)); - memcpy(&(rdata->rrec), &rl->rrec[0], sizeof(TLS_RL_RECORD)); - - item->data = rdata; - - rl->packet = NULL; - rl->packet_length = 0; - memset(&rl->rbuf, 0, sizeof(TLS_BUFFER)); - memset(&rl->rrec[0], 0, sizeof(rl->rrec[0])); - - if (!tls_setup_read_buffer(rl)) { - /* RLAYERfatal() already called */ - OPENSSL_free(rdata->rbuf.buf); + rdata->packet = OPENSSL_memdup(rl->packet, rl->packet_length); + if (rdata->packet == NULL) { OPENSSL_free(rdata); pitem_free(item); + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB); return -1; } + memcpy(&(rdata->rrec), &rl->rrec[0], sizeof(TLS_RL_RECORD)); + + item->data = rdata; if (pqueue_insert(queue, item) == NULL) { /* Must be a duplicate so ignore it */ - OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(rdata->packet); OPENSSL_free(rdata); pitem_free(item); } @@ -607,7 +604,7 @@ static int dtls_free(OSSL_RECORD_LAYER *rl) /* Push to the next record layer */ ret &= BIO_write_ex(rl->next, rdata->packet, rdata->packet_length, &written); - OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(rdata->packet); OPENSSL_free(item->data); pitem_free(item); } From 23537da45353db20d3e5725e22b2b950b9ffda72 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 23 Jun 2026 12:06:56 +0100 Subject: [PATCH 168/189] ssl/record/methods/dtls_meth.c: lower the unprocessed_rcds queue limit 100 buffered next-epoch records is far more than a normal handshake ever needs. A peer that has already completed its side of the epoch transition may send more than one record under the new epoch before we catch up and bump our own receive epoch - for example, application data sent immediately once the peer considers the handshake done - but real-world bursts like that are still small. Now that each entry only costs as much memory as the record actually received, the limit mainly serves as a ceiling on worst-case per-connection memory use, so lower it to 16 to keep that ceiling smaller while still leaving ample headroom over legitimate usage. Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Andrew Dinh Merge-date: Mon Aug 24 15:38:55 2026 --- ssl/record/methods/dtls_meth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl/record/methods/dtls_meth.c b/ssl/record/methods/dtls_meth.c index 22e1afe9ad9ed..0b68cf7a325ec 100644 --- a/ssl/record/methods/dtls_meth.c +++ b/ssl/record/methods/dtls_meth.c @@ -287,7 +287,7 @@ static int dtls_rlayer_buffer_record(OSSL_RECORD_LAYER *rl, struct pqueue_st *qu pitem *item; /* Limit the size of the queue to prevent DOS attacks */ - if (pqueue_size(queue) >= 100) + if (pqueue_size(queue) >= 16) return 0; rdata = OPENSSL_malloc(sizeof(*rdata)); From 6f72c9af9aa48427af1d8f9b62ce863200fb0ec4 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 23 Jun 2026 11:55:43 +0100 Subject: [PATCH 169/189] ssl/record: remove dead DTLS processed_rcds record queue rl->processed_rcds and the functions that serviced it (dtls_copy_rlayer_record(), dtls_retrieve_rlayer_buffered_record()) were unreachable: nothing in the codebase ever inserted a record into that queue, so the only consumer of it - the check at the top of dtls_get_more_records() - always saw an empty queue. The real mechanism for handing buffered next-epoch records to the next epoch's record layer is the unrelated forwarding code in dtls_free(), which pushes the raw bytes from rl->unprocessed_rcds onto rl->next. Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Andrew Dinh Merge-date: Mon Aug 24 15:38:56 2026 --- ssl/record/methods/dtls_meth.c | 58 +--------------------------- ssl/record/methods/recmethod_local.h | 4 +- 2 files changed, 2 insertions(+), 60 deletions(-) diff --git a/ssl/record/methods/dtls_meth.c b/ssl/record/methods/dtls_meth.c index 0b68cf7a325ec..6116e343853b3 100644 --- a/ssl/record/methods/dtls_meth.c +++ b/ssl/record/methods/dtls_meth.c @@ -326,44 +326,6 @@ static int dtls_rlayer_buffer_record(OSSL_RECORD_LAYER *rl, struct pqueue_st *qu return 1; } -/* copy buffered record into OSSL_RECORD_LAYER structure */ -static int dtls_copy_rlayer_record(OSSL_RECORD_LAYER *rl, pitem *item) -{ - DTLS_RLAYER_RECORD_DATA *rdata; - - rdata = (DTLS_RLAYER_RECORD_DATA *)item->data; - - ossl_tls_buffer_release(&rl->rbuf); - - rl->packet = rdata->packet; - rl->packet_length = rdata->packet_length; - memcpy(&rl->rbuf, &(rdata->rbuf), sizeof(TLS_BUFFER)); - memcpy(&rl->rrec[0], &(rdata->rrec), sizeof(TLS_RL_RECORD)); - - /* Set proper sequence number for mac calculation */ - memcpy(&(rl->sequence[2]), &(rdata->packet[5]), 6); - - return 1; -} - -static int dtls_retrieve_rlayer_buffered_record(OSSL_RECORD_LAYER *rl, - struct pqueue_st *queue) -{ - pitem *item; - - item = pqueue_pop(queue); - if (item) { - dtls_copy_rlayer_record(rl, item); - - OPENSSL_free(item->data); - pitem_free(item); - - return 1; - } - - return 0; -} - /*- * Call this to get a new input record. * It will return <= 0 if more data is needed, normally due to an error @@ -397,12 +359,6 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl) } again: - /* if we're renegotiating, then there may be buffered records */ - if (dtls_retrieve_rlayer_buffered_record(rl, rl->processed_rcds)) { - rl->num_recs = 1; - return OSSL_RECORD_RETURN_SUCCESS; - } - /* get something from the wire */ /* check if we have the header */ @@ -611,16 +567,6 @@ static int dtls_free(OSSL_RECORD_LAYER *rl) pqueue_free(rl->unprocessed_rcds); } - if (rl->processed_rcds != NULL) { - while ((item = pqueue_pop(rl->processed_rcds)) != NULL) { - rdata = (DTLS_RLAYER_RECORD_DATA *)item->data; - OPENSSL_free(rdata->rbuf.buf); - OPENSSL_free(item->data); - pitem_free(item); - } - pqueue_free(rl->processed_rcds); - } - return tls_free(rl) && ret; } @@ -650,10 +596,8 @@ dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers, return ret; (*retrl)->unprocessed_rcds = pqueue_new(); - (*retrl)->processed_rcds = pqueue_new(); - if ((*retrl)->unprocessed_rcds == NULL - || (*retrl)->processed_rcds == NULL) { + if ((*retrl)->unprocessed_rcds == NULL) { dtls_free(*retrl); *retrl = NULL; ERR_raise(ERR_LIB_SSL, ERR_R_SSL_LIB); diff --git a/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h index 4ffce8d66385c..a0d547257fb74 100644 --- a/ssl/record/methods/recmethod_local.h +++ b/ssl/record/methods/recmethod_local.h @@ -344,9 +344,8 @@ struct ossl_record_layer_st { size_t taglen; - /* DTLS received handshake records (processed and unprocessed) */ + /* DTLS received handshake records awaiting the next epoch */ struct pqueue_st *unprocessed_rcds; - struct pqueue_st *processed_rcds; /* records being received in the current epoch */ DTLS_BITMAP bitmap; @@ -374,7 +373,6 @@ struct ossl_record_layer_st { typedef struct dtls_rlayer_record_data_st { unsigned char *packet; size_t packet_length; - TLS_BUFFER rbuf; TLS_RL_RECORD rrec; } DTLS_RLAYER_RECORD_DATA; From 967582d5037f01a26b6d19beae19af62a1b15c3c Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Wed, 5 Aug 2026 00:56:25 +0200 Subject: [PATCH 170/189] Avoid double free of qrx in port_default_packet_handler() port_default_packet_handler() may perform double free of qrx when channel creation fails. The port_default_packet_handler() transfers ownership of qrx to channel/connection via call to port_bind_channel(). The port_bind_channel() however may release the qrx when channel can not be bound. The error is then detected in port_default_packet_handler() which then agains releases qrx for the second time. The fix is to add a reference counter to QRX object so transfer of ownership between port_default_packet_handler() and QUIC_CHANNEL can be handled safely. Fixes CVE-2026-18798 Reviewed-by: Igor Ustinov Reviewed-by: Andrew Dinh Merge-date: Mon Aug 24 15:48:03 2026 --- include/internal/quic_record_rx.h | 11 +++++++-- ssl/quic/quic_port.c | 40 +++++++++++++++++++++---------- ssl/quic/quic_record_rx.c | 32 +++++++++++++++++++++---- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/include/internal/quic_record_rx.h b/include/internal/quic_record_rx.h index 287837b2a5610..175d3b2f30e7a 100644 --- a/include/internal/quic_record_rx.h +++ b/include/internal/quic_record_rx.h @@ -51,8 +51,9 @@ typedef struct ossl_qrx_args_st { OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args); /* - * Frees the QRX. All packets obtained using ossl_qrx_read_pkt must already - * have been released by calling ossl_qrx_release_pkt. + * Frees the QRX/reference to QRX. Frees the QRX object, if all references are + * gone. All packets obtained using ossl_qrx_read_pkt must already have been + * released by calling ossl_qrx_release_pkt. * * You do not need to call ossl_qrx_remove_dst_conn_id first; this function will * unregister the QRX from the demuxer for all registered destination connection @@ -60,6 +61,12 @@ OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args); */ void ossl_qrx_free(OSSL_QRX *qrx); +/* + * Obtains a new reference to QRX object. Returns NULL if reference can not + * be obtained. + */ +OSSL_QRX *ossl_qrx_newref(OSSL_QRX *qrx); + /* Setters for the msg_callback and msg_callback_arg */ void ossl_qrx_set_msg_callback(OSSL_QRX *qrx, ossl_msg_cb msg_callback, SSL *msg_callback_ssl); diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 50b7cd7f5c3c0..aad9c3a5b3d56 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -534,8 +534,10 @@ static QUIC_CHANNEL *port_make_channel(QUIC_PORT *port, SSL *tls, OSSL_QRX *qrx, * start by allocation and provisioning as much of the channel as we can */ ch = ossl_quic_channel_alloc(&args); - if (ch == NULL) + if (ch == NULL) { + ossl_qrx_free(qrx); return NULL; + } /* * Fixup the channel tls connection here before we init the channel @@ -1491,7 +1493,7 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, QUIC_CHANNEL *ch = NULL, *new_ch = NULL; QUIC_CONN_ID odcid; uint8_t gen_new_token = 0; - OSSL_QRX *qrx = NULL; + OSSL_QRX *qrx = NULL, *qrx_ref; OSSL_QRX *qrx_src = NULL; OSSL_QRX_ARGS qrx_args = { 0 }; uint64_t cause_flags = 0; @@ -1684,8 +1686,22 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, } } + qrx_ref = NULL; + if (qrx != NULL) { + /* + * if we are here, then client is validated via retry packet + * (client sent a valid token). In this case the qrx has valid + * secrets set for QUIC initial level encryption. We can pass + * reference to qrx to newly created channel. + * + * Note: port_bind_channel()/channel becomes owner of qrx_ref. + */ + qrx_ref = ossl_qrx_newref(qrx); + if (qrx_ref == NULL) + goto undesirable; + } port_bind_channel(port, &e->peer, &hdr.dst_conn_id, - &odcid, qrx, &new_ch); + &odcid, qrx_ref, &new_ch); /* * if packet validates it gets moved to channel, we've just bound @@ -1700,19 +1716,19 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, if (gen_new_token == 1) generate_new_token(new_ch, &e->peer); - if (qrx != NULL) { + if (qrx_src != NULL) { /* - * The qrx belongs to channel now, so don't free it. - */ - qrx = NULL; - } else { - /* - * We still need to salvage packets from almost forgotten qrx - * and pass them to channel. + * Time to reinject packets from qrx to channel before + * qrx will be destroyed here. */ while (ossl_qrx_read_pkt(qrx_src, &qrx_pkt) == 1) ossl_quic_channel_inject_pkt(new_ch, qrx_pkt); ossl_qrx_update_pn_space(qrx_src, new_ch->qrx); + /* + * transfer ownership back to qrx; + */ + qrx = qrx_src; + qrx_src = NULL; } /* @@ -1729,7 +1745,7 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, */ undesirable: - ossl_qrx_free(qrx); + ossl_qrx_free(qrx); /* releases reference */ ossl_qrx_free(qrx_src); ossl_quic_demux_release_urxe(port->demux, e); } diff --git a/ssl/quic/quic_record_rx.c b/ssl/quic/quic_record_rx.c index 8897cc6c2df0d..0065f1c1e5735 100644 --- a/ssl/quic/quic_record_rx.c +++ b/ssl/quic/quic_record_rx.c @@ -171,6 +171,8 @@ struct ossl_qrx_st { ossl_msg_cb msg_callback; void *msg_callback_arg; SSL *msg_callback_ssl; + + uint32_t refcount; }; static RXE *qrx_ensure_free_rxe(OSSL_QRX *qrx, size_t alloc_len); @@ -212,6 +214,7 @@ OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args) qrx->short_conn_id_len = args->short_conn_id_len; qrx->init_key_phase_bit = args->init_key_phase_bit; qrx->max_deferred = args->max_deferred; + qrx->refcount = 1; return qrx; } @@ -247,13 +250,10 @@ void ossl_qrx_update_pn_space(OSSL_QRX *src, OSSL_QRX *dst) return; } -void ossl_qrx_free(OSSL_QRX *qrx) +static void qrx_destroy(OSSL_QRX *qrx) { uint32_t i; - if (qrx == NULL) - return; - /* Free RXE queue data. */ qrx_cleanup_rxl(&qrx->rx_free); qrx_cleanup_rxl(&qrx->rx_pending); @@ -267,6 +267,30 @@ void ossl_qrx_free(OSSL_QRX *qrx) OPENSSL_free(qrx); } +void ossl_qrx_free(OSSL_QRX *qrx) +{ + if (qrx == NULL) + return; + + qrx->refcount--; + if (qrx->refcount == 0) + qrx_destroy(qrx); +} + +OSSL_QRX *ossl_qrx_newref(OSSL_QRX *qrx) +{ + OSSL_QRX *rv_qrx; + + if (qrx != NULL && qrx->refcount != (uint32_t)~0) { + qrx->refcount++; + rv_qrx = qrx; + } else { + rv_qrx = NULL; + } + + return rv_qrx; +} + void ossl_qrx_inject_urxe(OSSL_QRX *qrx, QUIC_URXE *urxe) { /* Initialize our own fields inside the URXE and add to the pending list. */ From 9bde5cc62e3394e44d9d2160a9de5f0a16d1571d Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Mon, 24 Aug 2026 07:17:05 +0200 Subject: [PATCH 171/189] CHANGES.md: rephrase TLS 1.3 ticket lifetime cap change log record Complements: b0576dc5d422 "Enforce RFC 8446 ticket lifetime limit for TLS 1.3 client" Signed-off-by: Eugene Syromiatnikov Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Bob Beck Merge-date: Tue Aug 25 11:36:54 2026 --- CHANGES.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index edf00dc80f98e..a73259bdaa4c1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,15 +30,11 @@ OpenSSL 3.5 ### Changes between 3.5.7 and 3.5.8 [xx XXX xxxx] - * Add client-side validation for TLS 1.3 session ticket lifetimes. - - In accordance with [RFC 8446 Section 4.6.1](https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.1), - TLS 1.3 clients must not cache session tickets - for longer than 7 days (604800 seconds). - When processing a new session ticket message with a - `ticket_lifetime_hint` value greater than 7 days, - the client now caps the lifetime to the - maximum permitted value of 7 days (604800 seconds). + * Updated compliance with TLS 1.3 session ticket lifetime requirements. + TLS 1.3 clients now cap `ticket_lifetime_hint` to 7 days (604800 seconds) + when processing new session ticket messages, in accordance + with [RFC 8446 Section 4.6.1]. + *Abel Thomas* @@ -22314,4 +22310,5 @@ ndif [RFC 3211]: https://datatracker.ietf.org/doc/html/rfc3211 [RFC 5297]: https://datatracker.ietf.org/doc/html/rfc5297 [RFC 8446]: https://datatracker.ietf.org/doc/html/rfc8446 +[RFC 8446 Section 4.6.1]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.1 [RFC 8452]: https://datatracker.ietf.org/doc/html/rfc8452 From ffdd18b969117556d20852288c7c2d2ca1493e89 Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Mon, 24 Aug 2026 07:20:12 +0200 Subject: [PATCH 172/189] CHANGES.md, NEWS.md: reorder HollowByte change log record, add missing period Move HollowByte change log record after records with assigned CVE numbers and severity ratings, add period at the end of the lead sentence, add a link to the PR in the comment. Complements: 4db90ebab383 "Update CHANGES/NEWS to mention the HollowByte fix" Signed-off-by: Eugene Syromiatnikov Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Bob Beck Merge-date: Tue Aug 25 11:36:55 2026 --- CHANGES.md | 29 +++++++++++++++-------------- NEWS.md | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a73259bdaa4c1..05bc7508fea7d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -40,20 +40,6 @@ OpenSSL 3.5 ### Changes between 3.5.6 and 3.5.7 [9 Jun 2026] - * Fixed excessive allocation of the handshake message buffer (aka HollowByte) - - Previously, we would allocate a buffer large enough to hold the full size of - an incoming handshake message as advertised by the peer. This could be quite - large (although it is bounded, e.g. for ClientHello this is approximately - 128 KiB). If the peer then fails to send the full handshake message, then the - endpoint is left waiting for the remainder of the message to arrive and the - memory is still allocated (i.e. a Slowloris attack). To prevent this, we - incrementally grow the buffer as we receive the data. - - This issue was reported by Okta Red Team. - - *Matt Caswell* - * Fixed heap use-after-free in `PKCS7_verify()`. Severity: High @@ -330,6 +316,21 @@ OpenSSL 3.5 *Dmitry Belyavskiy (Red Hat)* + * Fixed excessive allocation of the handshake message buffer (aka HollowByte). + + Previously, we would allocate a buffer large enough to hold the full size of + an incoming handshake message as advertised by the peer. This could be quite + large (although it is bounded, e.g. for ClientHello this is approximately + 128 KiB). If the peer then fails to send the full handshake message, then the + endpoint is left waiting for the remainder of the message to arrive and the + memory is still allocated (i.e. a Slowloris attack). To prevent this, we + incrementally grow the buffer as we receive the data. + + This issue was reported by Okta Red Team. + + + *Matt Caswell* + * Fixed TLS 1.3 server not sending `NewSessionTicket` message after ciphersuite mismatch. diff --git a/NEWS.md b/NEWS.md index d3c228eac929c..49ebf3a6466e8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -82,7 +82,7 @@ This release incorporates the following bug fixes and mitigations: and AES-SIV modes. ([CVE-2026-45446]) - * Fixed excessive allocation of the handshake message buffer (aka HollowByte) + * Fixed excessive allocation of the handshake message buffer (aka HollowByte). ### Major changes between OpenSSL 3.5.5 and OpenSSL 3.5.6 [7 Apr 2026] From 4d79d67312c6cf8c0d620be2653fab0ffedabede Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Mon, 24 Aug 2026 07:24:24 +0200 Subject: [PATCH 173/189] CHANGES.md, NEWS.md: update for 3.5.8 3.5.8 CHANGES.md includes the following: * CVE-2026-14456, CVE-2026-14457, CVE-2026-18798, CVE-2026-54874, CVE-2026-63072, CVE-2026-63073, CVE-2026-63074, CVE-2026-63075, CVE-2026-63076, CVE-2026-75803 * https://github.com/openssl/openssl/pull/31174 "Enforce RFC 8446 ticket lifetime limit for TLS 1.3 client" (already present) * https://github.com/openssl/openssl/pull/31572 "[4.0, 3.6, 3.5, 3.4] Add icx compiler version support in perl asm scripts" * https://github.com/openssl/openssl/pull/31749 "Add documentation for OPENSSL_armcap" * https://github.com/openssl/openssl/pull/32052 "QUIC server: limit the number of pending connections" (included as CVE-2026-14456) * https://github.com/openssl/openssl/pull/32416 "[3.5,3.4] Reject explicitly supplied invalid tags and generate tags for empty AEAD messages" (included as CVE-2026-75803) * https://github.com/openssl/openssl/pull/32427 "Backport #32256 openssl 4.0 to 3.0" 3.5.8 NEWS.md includes the following: * CVE-2026-14456, CVE-2026-14457, CVE-2026-18798, CVE-2026-54874, CVE-2026-63072, CVE-2026-63073, CVE-2026-63074, CVE-2026-63075, CVE-2026-63076, CVE-2026-75803 * https://github.com/openssl/openssl/pull/32052 "QUIC server: limit the number of pending connections" (included as CVE-2026-14456) * https://github.com/openssl/openssl/pull/32416 "[3.5,3.4] Reject explicitly supplied invalid tags and generate tags for empty AEAD messages" (included as CVE-2026-75803) * https://github.com/openssl/openssl/pull/32427 "Backport #32256 openssl 4.0 to 3.0" Signed-off-by: Eugene Syromiatnikov Reviewed-by: Milan Broz Reviewed-by: Tomas Mraz Reviewed-by: Bob Beck Merge-date: Tue Aug 25 11:36:56 2026 --- CHANGES.md | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++++ NEWS.md | 52 +++++++++++- 2 files changed, 283 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 05bc7508fea7d..a02d74d447cf1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,6 +30,221 @@ OpenSSL 3.5 ### Changes between 3.5.7 and 3.5.8 [xx XXX xxxx] + * Fixed QUIC server being able to trigger double free when processing `INITIAL` + packet. + + Severity: Moderate + + Issue summary: QUIC server may double free QRX (QUIC record layer RX) object + when channel creation fails for initial packet. + + Impact summary: Double free leads to heap corruption, which typically results + in termination of QUIC server process, leading to a Denial of Service. + There is so far no evidence that this double free is exploitable for remote + code execution, thus it is considered highly improbable. + + Reported by: Fuzz0x (ZKSC Institute of Security Research), Emilio Galle, + and Feng Xue (ThreatBoon). + + ([CVE-2026-18798]) + + *Alexandr Nedvědický* + + * Fixed heap buffer overflow in CMS key unwrapping. + + Severity: Moderate + + Issue summary: OpenSSL CMS decryption sizes the key-unwrap output buffer + based on querying the unwrapped key size, but the AES-WRAP-PAD unwrap + primitive can write and cleanse more bytes than that query reports, causing + an 8-byte out-of-bounds heap write. + + Impact summary: An attacker who supplies a crafted CMS message can trigger + a deterministic 8-byte out-of-bounds heap write when the victim decrypts it + with `CMS_decrypt()`, corrupting the heap and typically resulting in a Denial + of Service. + + Reported by: Bhabani Sankar Das and Filipe Casal (Trail of Bits). + + ([CVE-2026-63072]) + + *Daniel Kubec* + + * Fixed invalid pointer dereference in CMP server via crafted `protectionAlg`. + + Severity: Moderate + + Issue Summary: The OpenSSL Certificate Management Protocol (CMP) + password-based protection verification only checks whether + the `protectionAlg` parameter was not NULL and not its ASN.1 type, + before treating it as a `PBMParameter`. A crafted message can contain + a parameter of a different type, which is then dereferenced as an invalid + pointer. + + Impact summary: A remote, unauthenticated attacker can crash an application + acting as a CMP server that accepts PBM-protected messages, or a CMP client + talking to a malicious or intercepted CMP server, resulting in a Denial + of Service. + + Reported by: Ying Dong and Bhabani Sankar Das. + + ([CVE-2026-63076]) + + *Daniel Kubec* + + * Fixed unbounded memory growth in QUIC server incoming channel queue. + + Severity: Low + + Issue summary: When an OpenSSL QUIC server (Listener SSL object) processes + valid QUIC Initial packets for unknown destination connection IDs, it can + allocate and queue new incoming channels without enforcing any limit. + + Impact summary: A remote peer that can make many `INITIAL` packets reach + the server listener faster than the application accepts connections can + cause the memory allocated to store the per-channel state to grow + without any limits, potentially making the QUIC listener unavailable + and causing a Denial of Service. + + Reported by: Filipe Casal (Trail of Bits) in collaboration with OpenAI. + + ([CVE-2026-14456]) + + + *Filipe Casal* + + * Fixed RPK server signature algorithm selection being able to dereference + a missing certificate. + + Severity: Low + + Issue summary: In a server or client configuration with [RFC 7250] Raw Public + Keys (RPKs) enabled, and only the private key (with no associated + certificate) configured locally, a NULL pointer dereference may occur + when the remote peer solicits raw public keys and also sends the typically + omitted `signature_algorithms_cert` TLS extension. + + Impact summary: The impact is limited to a possible Denial of Service + as a result of an application abort, no data disclosure or remote command + execution are possible. + + Reported by: Filipe Casal (Trail of Bits) in collaboration with OpenAI. + + ([CVE-2026-14457]) + + *Viktor Dukhovni* + + * Fixed excessive memory use buffering DTLS records for a future epoch. + + Severity: Low + + Issue summary: Receiving a DTLS record for a future epoch while a handshake + is in progress causes OpenSSL to buffer far more memory than the record + itself requires. + + Impact summary: A peer can use a small amount of network traffic to make + an OpenSSL DTLS endpoint retain a disproportionately large amount of memory, + which may lead to a Denial of Service. + + Reported by: Amazon Web Services. + + ([CVE-2026-54874]) + + *Matt Caswell* + + * Fixed untrusted Sender DN being used as a format string in CMP response + validation. + + Severity: Low + + Issue Summary: The OpenSSL Certificate Management Protocol (CMP) response + validation passed an unexpected response sender distinguished name directly + as the format string to `ERR_raise_data()`. + + Impact summary: A malicious or intercepted CMP endpoint can crash a CMP + client that enforces an expected sender or uses a pinned server certificate + whose subject becomes the default expected sender. + + Reported by: Filipe Casal (Trail of Bits) in collaboration with OpenAI, + Brandon Luo, and TrendAI Zero Day Initiative. + + ([CVE-2026-63073]) + + *Filipe Casal* + + * Fixed CMP indefinite cache growth of `extraCerts`. + + Severity: Low + + Issue Summary: The OpenSSL Certificate Management Protocol (CMP) caches + additional certificates (`extraCerts`) sent in a CMP message, but never + expunges them (for instance, if they are invalid). If a server reuses + an `OSSL_CMP_CTX` object frequently, this cache of `extraCerts` may grow + unboundedly, and a malicious client may flood a CMP server with requests + driving this growth. + + Impact Summary: Users utilizing a CMP server that reuses a single + `OSSL_CMP_CTX` object for the lifetime of a server process may observe + unbounded memory growth in the event a malicious client repeatedly sends + requests containing unique extra certificates, which may lead to OOM + conditions. + + Reported by: Pavol Zacik (Red Hat). + + ([CVE-2026-63074]) + + *Neil Horman* + + * Fixed QUIC ACK-only packet retention being able to cause memory exhaustion. + + Severity: Low + + Issue Summary: When OpenSSL processes QUIC traffic from a peer + that repeatedly sends ACK-eliciting packets while not acknowledging ACK-only + responses, the QUIC stack can retain ACK-only packet metadata + for the lifetime of the connection. + + Impact Summary: A remote peer that can complete a QUIC handshake can cause + connection-scoped memory growth, which may lead to a Denial of Service + through memory exhaustion, especially with sustained traffic or many + concurrent QUIC connections. + + Reported by: Opal Wright (Trail of Bits). + + ([CVE-2026-63075]) + + *Neil Horman* + + * Fixed possibility of AEAD forgeries with empty ciphertext when using + `EVP_Cipher()`. + + Severity: Low + + Issue summary: ChaCha20-Poly1305 and AES-OCB decryption with an empty + ciphertext can report success without verifying the supplied authentication + tag when the operation is finalized by calling the `EVP_Cipher()` function. + + Impact summary: Applications calling `EVP_Cipher()` on an empty ciphertext + and expecting the call to check the AEAD tag may accept forged messages. + + Reported by: Billy Brumley (Rochester Institute of Technology). + + ([CVE-2026-75803]) + + + *Billy Bob Brumley* + + * Added `OPENSSL_armcap(3)` documentation page. + + + *Paul Elliott* + + * Added support for selecting assembly code paths for LLVM-based Intel's `icx` + compiler. + + + *Wolfgang Beck* + * Updated compliance with TLS 1.3 session ticket lifetime requirements. TLS 1.3 clients now cap `ticket_lifetime_hint` to 7 days (604800 seconds) when processing new session ticket messages, in accordance @@ -38,6 +253,12 @@ OpenSSL 3.5 *Abel Thomas* + * Fixed checking of authentication tags for empty ciphertexts for AEAD ciphers + in CCM cipher mode. + + + *Mounir IDRASSI* + ### Changes between 3.5.6 and 3.5.7 [9 Jun 2026] * Fixed heap use-after-free in `PKCS7_verify()`. @@ -22285,6 +22506,9 @@ ndif [CVE-2026-2673]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-2673 [CVE-2026-7383]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-7383 [CVE-2026-9076]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-9076 +[CVE-2026-14456]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-14456 +[CVE-2026-14457]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-14457 +[CVE-2026-18798]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-18798 [CVE-2026-22795]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-22795 [CVE-2026-22796]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-22796 [CVE-2026-28387]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-28387 @@ -22306,10 +22530,18 @@ ndif [CVE-2026-45445]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-45445 [CVE-2026-45446]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-45446 [CVE-2026-45447]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-45447 +[CVE-2026-54874]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-54874 +[CVE-2026-63072]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63072 +[CVE-2026-63073]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63073 +[CVE-2026-63074]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63074 +[CVE-2026-63075]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63075 +[CVE-2026-63076]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63076 +[CVE-2026-75803]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-75803 [ESV]: https://csrc.nist.gov/Projects/cryptographic-module-validation-program/entropy-validations [RFC 2578 (STD 58), section 3.5]: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5 [RFC 3211]: https://datatracker.ietf.org/doc/html/rfc3211 [RFC 5297]: https://datatracker.ietf.org/doc/html/rfc5297 +[RFC 7250]: https://datatracker.ietf.org/doc/html/rfc7250 [RFC 8446]: https://datatracker.ietf.org/doc/html/rfc8446 [RFC 8446 Section 4.6.1]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.1 [RFC 8452]: https://datatracker.ietf.org/doc/html/rfc8452 diff --git a/NEWS.md b/NEWS.md index 49ebf3a6466e8..bf9631179595b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -25,7 +25,47 @@ OpenSSL 3.5 ### Major changes between OpenSSL 3.5.7 and OpenSSL 3.5.8 [under development] - * none +OpenSSL 3.5.8 is a security patch release. The most severe CVE fixed +in this release is Moderate. + +This release incorporates the following bug fixes and mitigations: + + * Fixed QUIC server being able to trigger double free when processing + `INITIAL` packet. + ([CVE-2026-18798]) + + * Fixed heap buffer overflow in CMS key unwrapping. + ([CVE-2026-63072]) + + * Fixed invalid pointer dereference in CMP server via crafted `protectionAlg`. + ([CVE-2026-63076]) + + * Fixed unbounded memory growth in QUIC server incoming channel queue. + ([CVE-2026-14456]) + + * Fixed RPK server signature algorithm selection being able to dereference + a missing certificate. + ([CVE-2026-14457]) + + * Fixed excessive memory use buffering DTLS records for a future epoch. + ([CVE-2026-54874]) + + * Fixed untrusted Sender DN being used as a format string in CMP response + validation. + ([CVE-2026-63073]) + + * Fixed CMP indefinite cache growth of `extraCerts`. + ([CVE-2026-63074]) + + * Fixed QUIC ACK-only packet retention being able to cause memory exhaustion. + ([CVE-2026-63075]) + + * Fixed possibility of AEAD forgeries with empty ciphertext when using + `EVP_Cipher()`. + ([CVE-2026-75803]) + + * Fixed checking of authentication tags for empty ciphertexts for AEAD ciphers + in CCM cipher mode. ### Major changes between OpenSSL 3.5.6 and OpenSSL 3.5.7 [9 Jun 2026] @@ -2273,6 +2313,9 @@ OpenSSL 0.9.x [CVE-2026-2673]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-2673 [CVE-2026-7383]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-7383 [CVE-2026-9076]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-9076 +[CVE-2026-14456]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-14456 +[CVE-2026-14457]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-14457 +[CVE-2026-18798]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-18798 [CVE-2026-22795]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-22795 [CVE-2026-22796]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-22796 [CVE-2026-28387]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-28387 @@ -2294,6 +2337,13 @@ OpenSSL 0.9.x [CVE-2026-45445]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-45445 [CVE-2026-45446]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-45446 [CVE-2026-45447]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-45447 +[CVE-2026-54874]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-54874 +[CVE-2026-63072]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63072 +[CVE-2026-63073]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63073 +[CVE-2026-63074]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63074 +[CVE-2026-63075]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63075 +[CVE-2026-63076]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-63076 +[CVE-2026-75803]: https://openssl-library.org/news/vulnerabilities/#CVE-2026-75803 [ESV]: https://csrc.nist.gov/Projects/cryptographic-module-validation-program/entropy-validations [OpenSSL Guide]: https://www.openssl.org/docs/manmaster/man7/ossl-guide-introduction.html [README-QUIC.md]: ./README-QUIC.md From 48f2ead61df5b2068875d321bd4de9e217d540b8 Mon Sep 17 00:00:00 2001 From: openssl-machine Date: Tue, 25 Aug 2026 11:54:36 +0000 Subject: [PATCH 174/189] Copyright year updates Reviewed-by: Neil Horman Reviewed-by: Milan Broz MergeDate: Tue Aug 25 11:54:37 2026 Release: yes --- apps/lib/s_cb.c | 2 +- apps/lib/vms_term_sock.c | 2 +- crypto/aes/asm/aesni-mb-x86_64.pl | 2 +- crypto/aes/asm/aesni-sha1-x86_64.pl | 2 +- crypto/aes/asm/aesni-sha256-x86_64.pl | 2 +- crypto/armcap.c | 2 +- crypto/bn/asm/rsaz-2k-avx512.pl | 2 +- crypto/bn/asm/rsaz-3k-avx512.pl | 2 +- crypto/bn/asm/rsaz-4k-avx512.pl | 2 +- crypto/bn/asm/rsaz-avx2.pl | 2 +- crypto/bn/asm/rsaz-x86_64.pl | 2 +- crypto/bn/asm/x86_64-mont.pl | 2 +- crypto/bn/asm/x86_64-mont5.pl | 2 +- crypto/bn/bn_add.c | 2 +- crypto/bn/bn_lib.c | 2 +- crypto/chacha/asm/chacha-x86.pl | 2 +- crypto/chacha/asm/chacha-x86_64.pl | 2 +- crypto/cmp/cmp_protect.c | 2 +- crypto/cms/cms_kari.c | 2 +- crypto/ct/ct_b64.c | 2 +- crypto/ctype.c | 2 +- crypto/dh/dh_backend.c | 2 +- crypto/dh/dh_check.c | 2 +- crypto/dsa/dsa_key.c | 2 +- crypto/ec/asm/ecp_nistz256-x86_64.pl | 2 +- crypto/ec/asm/x25519-x86_64.pl | 2 +- crypto/ec/ec_key.c | 2 +- crypto/evp/exchange.c | 2 +- crypto/ffc/ffc_params_generate.c | 2 +- crypto/hmac/hmac.c | 2 +- crypto/ml_dsa/ml_dsa_encoders.c | 2 +- crypto/ml_dsa/ml_dsa_matrix.c | 2 +- crypto/ml_dsa/ml_dsa_sample.c | 2 +- crypto/ml_dsa/ml_dsa_sign.c | 2 +- crypto/ml_dsa/ml_dsa_vector.h | 2 +- crypto/ml_kem/ml_kem.c | 2 +- crypto/modes/asm/aes-gcm-avx512.pl | 2 +- crypto/modes/asm/aesni-gcm-x86_64.pl | 2 +- crypto/modes/asm/ghash-x86_64.pl | 2 +- crypto/pem/pvkfmt.c | 2 +- crypto/pkcs12/p12_add.c | 2 +- crypto/poly1305/asm/poly1305-x86.pl | 2 +- crypto/poly1305/asm/poly1305-x86_64.pl | 2 +- crypto/rand/rand_lib.c | 2 +- crypto/rsa/rsa_gen.c | 2 +- crypto/rsa/rsa_ossl.c | 2 +- crypto/sha/asm/sha1-586.pl | 2 +- crypto/sha/asm/sha1-mb-x86_64.pl | 2 +- crypto/sha/asm/sha1-x86_64.pl | 2 +- crypto/sha/asm/sha256-586.pl | 2 +- crypto/sha/asm/sha256-mb-x86_64.pl | 2 +- crypto/sha/asm/sha512-x86_64.pl | 2 +- crypto/sha/sha_riscv.c | 2 +- crypto/slh_dsa/slh_dsa_hash_ctx.c | 2 +- crypto/slh_dsa/slh_dsa_local.h | 2 +- crypto/slh_dsa/slh_fors.c | 2 +- crypto/slh_dsa/slh_hash.c | 2 +- crypto/slh_dsa/slh_hypertree.c | 2 +- crypto/slh_dsa/slh_wots.c | 2 +- crypto/slh_dsa/slh_xmss.c | 2 +- crypto/x509/by_dir.c | 2 +- crypto/x509/pcy_cache.c | 2 +- crypto/x509/v3_akid.c | 2 +- crypto/x509/v3_ncons.c | 2 +- crypto/x509/x509_err.c | 2 +- crypto/x509/x509_lu.c | 2 +- crypto/x509/x_crl.c | 2 +- doc/internal/man3/DEFINE_LIST_OF.pod | 2 +- doc/man1/openssl.pod | 2 +- doc/man3/ASN1_INTEGER_get_int64.pod | 2 +- doc/man3/ASN1_aux_cb.pod | 2 +- doc/man3/BIO_s_datagram.pod | 2 +- doc/man3/BIO_s_file.pod | 2 +- doc/man3/BN_generate_prime.pod | 2 +- doc/man3/CMS_EncryptedData_decrypt.pod | 2 +- doc/man3/OPENSSL_init_crypto.pod | 2 +- doc/man3/SSL_CTX_set_msg_callback.pod | 2 +- doc/man3/SSL_CTX_set_verify.pod | 2 +- doc/man3/SSL_get_value_uint.pod | 2 +- doc/man3/SSL_new.pod | 2 +- doc/man3/X509_get_default_cert_file.pod | 2 +- doc/man3/X509_verify_cert.pod | 2 +- doc/man7/fips_module.pod | 2 +- doc/man7/openssl-core_dispatch.h.pod | 2 +- doc/man7/provider-kem.pod | 2 +- fuzz/provider.c | 2 +- include/internal/hashtable.h | 2 +- include/internal/list.h | 2 +- include/internal/quic_ackm.h | 2 +- include/internal/quic_port.h | 2 +- include/internal/quic_record_rx.h | 2 +- include/internal/quic_ssl.h | 2 +- include/openssl/x509err.h | 2 +- providers/baseprov.c | 2 +- providers/fips/fipsprov.c | 2 +- providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c | 2 +- providers/implementations/ciphers/ciphercommon_ccm.c | 2 +- providers/implementations/encode_decode/encode_key2ms.c | 2 +- providers/implementations/kem/ml_kem_kem.c | 2 +- providers/implementations/kem/mlx_kem.c | 2 +- providers/implementations/keymgmt/dh_kmgmt.c | 2 +- providers/implementations/keymgmt/ec_kmgmt.c | 2 +- providers/implementations/keymgmt/ml_dsa_kmgmt.c | 2 +- providers/implementations/keymgmt/slh_dsa_kmgmt.c | 2 +- providers/implementations/macs/cmac_prov.c | 2 +- providers/implementations/rands/drbg_ctr.c | 2 +- providers/implementations/rands/drbg_hash.c | 2 +- providers/implementations/rands/seeding/rand_unix.c | 2 +- providers/implementations/rands/test_rng.c | 2 +- providers/implementations/storemgmt/file_store_any2obj.c | 2 +- ssl/quic/quic_port_local.h | 2 +- ssl/record/methods/dtls_meth.c | 2 +- ssl/record/methods/recmethod_local.h | 2 +- ssl/record/rec_layer_s3.c | 2 +- ssl/rio/poll_builder.c | 2 +- ssl/rio/poll_builder.h | 2 +- ssl/rio/poll_immediate.c | 2 +- ssl/rio/rio_notifier.c | 2 +- ssl/ssl_cert.c | 2 +- ssl/ssl_local.h | 2 +- ssl/statem/extensions.c | 2 +- test/ca_internals_test.c | 2 +- test/cmp_protect_test.c | 2 +- test/cmp_vfy_test.c | 2 +- test/crltest.c | 2 +- test/helpers/quictestlib.c | 2 +- test/helpers/quictestlib.h | 2 +- test/helpers/ssltestlib.c | 2 +- test/helpers/ssltestlib.h | 2 +- test/list_test.c | 2 +- test/p_test.c | 2 +- test/pairwise_fail_test.c | 2 +- test/pkcs7_test.c | 2 +- test/punycode_test.c | 2 +- test/quic_ackm_test.c | 2 +- test/quic_multistream_test.c | 2 +- test/quic_tserver_test.c | 2 +- test/radix/quic_bindings.c | 2 +- test/radix/quic_ops.c | 2 +- test/recipes/20-test_cli_fips.t | 2 +- test/recipes/30-test_evp_data/evprand.txt | 2 +- test/recipes/30-test_pairwise_fail.t | 2 +- test/recipes/65-test_cmp_msg.t | 2 +- test/recipes/70-test_sslrecords.t | 2 +- test/recipes/80-test_ssl_new.t | 2 +- test/rpktest.c | 2 +- test/secmemtest.c | 2 +- util/perl/TLSProxy/Proxy.pm | 2 +- 148 files changed, 148 insertions(+), 148 deletions(-) diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c index f65606302fb1d..760ad010988b3 100644 --- a/apps/lib/s_cb.c +++ b/apps/lib/s_cb.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c index 85e726ee452e5..15bc6665694d0 100644 --- a/apps/lib/vms_term_sock.c +++ b/apps/lib/vms_term_sock.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2026 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 diff --git a/crypto/aes/asm/aesni-mb-x86_64.pl b/crypto/aes/asm/aesni-mb-x86_64.pl index 791e161f67059..87ed95cdf33c1 100644 --- a/crypto/aes/asm/aesni-mb-x86_64.pl +++ b/crypto/aes/asm/aesni-mb-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2026 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/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/aes/asm/aesni-sha1-x86_64.pl index 47f4422b56acf..bc08da9460641 100644 --- a/crypto/aes/asm/aesni-sha1-x86_64.pl +++ b/crypto/aes/asm/aesni-sha1-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2011-2026 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/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/aes/asm/aesni-sha256-x86_64.pl index fdace4ced8cf8..6715ba2e11a76 100644 --- a/crypto/aes/asm/aesni-sha256-x86_64.pl +++ b/crypto/aes/asm/aesni-sha256-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2026 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/crypto/armcap.c b/crypto/armcap.c index 345d600fcd6cd..3005d295cfd0b 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2026 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/crypto/bn/asm/rsaz-2k-avx512.pl b/crypto/bn/asm/rsaz-2k-avx512.pl index 7e1db31e223ac..6c0cb566f9d7a 100644 --- a/crypto/bn/asm/rsaz-2k-avx512.pl +++ b/crypto/bn/asm/rsaz-2k-avx512.pl @@ -1,4 +1,4 @@ -# Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2020-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2020, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/crypto/bn/asm/rsaz-3k-avx512.pl b/crypto/bn/asm/rsaz-3k-avx512.pl index 403e09099f732..fe5b1ebefab6e 100644 --- a/crypto/bn/asm/rsaz-3k-avx512.pl +++ b/crypto/bn/asm/rsaz-3k-avx512.pl @@ -1,4 +1,4 @@ -# Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2021, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/crypto/bn/asm/rsaz-4k-avx512.pl b/crypto/bn/asm/rsaz-4k-avx512.pl index f41c1c60df838..b07180f6feca7 100644 --- a/crypto/bn/asm/rsaz-4k-avx512.pl +++ b/crypto/bn/asm/rsaz-4k-avx512.pl @@ -1,4 +1,4 @@ -# Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2021, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/crypto/bn/asm/rsaz-avx2.pl b/crypto/bn/asm/rsaz-avx2.pl index 56973a19f5347..29243a7c0b76e 100755 --- a/crypto/bn/asm/rsaz-avx2.pl +++ b/crypto/bn/asm/rsaz-avx2.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2012, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl index 16e215c2e8b53..3ceacea1d338d 100755 --- a/crypto/bn/asm/rsaz-x86_64.pl +++ b/crypto/bn/asm/rsaz-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2012, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl index 6c8aa647e20d6..9c7b3091f4349 100755 --- a/crypto/bn/asm/x86_64-mont.pl +++ b/crypto/bn/asm/x86_64-mont.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2026 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/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl index fc32e76c9014e..52f95a485317a 100755 --- a/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/bn/asm/x86_64-mont5.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2011-2026 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/crypto/bn/bn_add.c b/crypto/bn/bn_add.c index 52f456850c04c..9c028269840cc 100644 --- a/crypto/bn/bn_add.c +++ b/crypto/bn/bn_add.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index f22f6f49fb4bd..7961906f9ae73 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/chacha/asm/chacha-x86.pl b/crypto/chacha/asm/chacha-x86.pl index 7a825f133965a..b95d4df379792 100755 --- a/crypto/chacha/asm/chacha-x86.pl +++ b/crypto/chacha/asm/chacha-x86.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2026 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/crypto/chacha/asm/chacha-x86_64.pl b/crypto/chacha/asm/chacha-x86_64.pl index 40a30b27fa847..69e5319ad43ef 100755 --- a/crypto/chacha/asm/chacha-x86_64.pl +++ b/crypto/chacha/asm/chacha-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2026 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/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c index 19d729614a1e5..110693b84038e 100644 --- a/crypto/cmp/cmp_protect.c +++ b/crypto/cmp/cmp_protect.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2026 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c index bc08f2d4d9f15..459991525f09b 100644 --- a/crypto/cms/cms_kari.c +++ b/crypto/cms/cms_kari.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2013-2026 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/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c index f863ff716c48c..01bd8fc508d6d 100644 --- a/crypto/ct/ct_b64.c +++ b/crypto/ct/ct_b64.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2026 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/crypto/ctype.c b/crypto/ctype.c index 75192b11f4af7..4f19d6002c5e7 100644 --- a/crypto/ctype.c +++ b/crypto/ctype.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2026 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/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c index 5844c3556062f..77b0b3257fb7e 100644 --- a/crypto/dh/dh_backend.c +++ b/crypto/dh/dh_backend.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2026 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/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 96256f9283487..8787945f8a1cd 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index a07f866a218a7..738915cc4f3d5 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/ec/asm/ecp_nistz256-x86_64.pl index 2bb961aeba596..12a104b5ec0fb 100755 --- a/crypto/ec/asm/ecp_nistz256-x86_64.pl +++ b/crypto/ec/asm/ecp_nistz256-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2014-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2014-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2014, Intel Corporation. All Rights Reserved. # Copyright (c) 2015 CloudFlare, Inc. # diff --git a/crypto/ec/asm/x25519-x86_64.pl b/crypto/ec/asm/x25519-x86_64.pl index 4c066eb120824..204c518548139 100755 --- a/crypto/ec/asm/x25519-x86_64.pl +++ b/crypto/ec/asm/x25519-x86_64.pl @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2018-2026 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/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 8dbbdc91a1e50..71f1c63e2ab62 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2026 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index 5820e3e877def..30299d67defd0 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c index 612b2508cd236..94b1602dd28e8 100644 --- a/crypto/ffc/ffc_params_generate.c +++ b/crypto/ffc/ffc_params_generate.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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/crypto/hmac/hmac.c b/crypto/hmac/hmac.c index fa54540be322d..77b97b6bef6ad 100644 --- a/crypto/hmac/hmac.c +++ b/crypto/hmac/hmac.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/ml_dsa/ml_dsa_encoders.c b/crypto/ml_dsa/ml_dsa_encoders.c index be687f2326604..9ebe5ae02d9b7 100644 --- a/crypto/ml_dsa/ml_dsa_encoders.c +++ b/crypto/ml_dsa/ml_dsa_encoders.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/ml_dsa/ml_dsa_matrix.c b/crypto/ml_dsa/ml_dsa_matrix.c index 5a9811df12e02..94fd16936c8b5 100644 --- a/crypto/ml_dsa/ml_dsa_matrix.c +++ b/crypto/ml_dsa/ml_dsa_matrix.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/ml_dsa/ml_dsa_sample.c b/crypto/ml_dsa/ml_dsa_sample.c index 66f48b584e72f..f8ce638dc2295 100644 --- a/crypto/ml_dsa/ml_dsa_sample.c +++ b/crypto/ml_dsa/ml_dsa_sample.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/ml_dsa/ml_dsa_sign.c b/crypto/ml_dsa/ml_dsa_sign.c index b3f3e20d357c0..166a604bcd577 100644 --- a/crypto/ml_dsa/ml_dsa_sign.c +++ b/crypto/ml_dsa/ml_dsa_sign.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/ml_dsa/ml_dsa_vector.h b/crypto/ml_dsa/ml_dsa_vector.h index de97dc1b3084c..1f3e6a03299cf 100644 --- a/crypto/ml_dsa/ml_dsa_vector.h +++ b/crypto/ml_dsa/ml_dsa_vector.h @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c index 2729c971e44b4..6c3141ca2d32e 100644 --- a/crypto/ml_kem/ml_kem.c +++ b/crypto/ml_kem/ml_kem.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/modes/asm/aes-gcm-avx512.pl b/crypto/modes/asm/aes-gcm-avx512.pl index ad6461f9e52fb..3da7c69cb985c 100644 --- a/crypto/modes/asm/aes-gcm-avx512.pl +++ b/crypto/modes/asm/aes-gcm-avx512.pl @@ -1,4 +1,4 @@ -# Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2021, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/modes/asm/aesni-gcm-x86_64.pl index 682a8318dd059..202883dac35e5 100644 --- a/crypto/modes/asm/aesni-gcm-x86_64.pl +++ b/crypto/modes/asm/aesni-gcm-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2026 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/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl index 01d9468c4b09f..181793c5523cc 100644 --- a/crypto/modes/asm/ghash-x86_64.pl +++ b/crypto/modes/asm/ghash-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2010-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2010-2026 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/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c index 31b46183a4043..8b81f66e0e3b7 100644 --- a/crypto/pem/pvkfmt.c +++ b/crypto/pem/pvkfmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2026 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/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c index 938e6eb842602..977aa8b658358 100644 --- a/crypto/pkcs12/p12_add.c +++ b/crypto/pkcs12/p12_add.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2026 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/crypto/poly1305/asm/poly1305-x86.pl b/crypto/poly1305/asm/poly1305-x86.pl index 2d9f49d673c98..6d367d858da72 100755 --- a/crypto/poly1305/asm/poly1305-x86.pl +++ b/crypto/poly1305/asm/poly1305-x86.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2026 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/crypto/poly1305/asm/poly1305-x86_64.pl b/crypto/poly1305/asm/poly1305-x86_64.pl index 9647335a426bc..081fe4117ad90 100755 --- a/crypto/poly1305/asm/poly1305-x86_64.pl +++ b/crypto/poly1305/asm/poly1305-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2026 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/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 89becbd84eb94..df70d1c2b1dad 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c index 5b407696092ab..777a485422dda 100644 --- a/crypto/rsa/rsa_gen.c +++ b/crypto/rsa/rsa_gen.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c index 3dc26c56d0667..73a4b7c20a47e 100644 --- a/crypto/rsa/rsa_ossl.c +++ b/crypto/rsa/rsa_ossl.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/sha/asm/sha1-586.pl b/crypto/sha/asm/sha1-586.pl index 3b2927748f605..81c3658b0adfb 100644 --- a/crypto/sha/asm/sha1-586.pl +++ b/crypto/sha/asm/sha1-586.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1998-2026 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/crypto/sha/asm/sha1-mb-x86_64.pl b/crypto/sha/asm/sha1-mb-x86_64.pl index b252473ee56b1..59042c90b2fec 100644 --- a/crypto/sha/asm/sha1-mb-x86_64.pl +++ b/crypto/sha/asm/sha1-mb-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2026 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/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl index 990e3afc5b2c6..829fe16a82724 100755 --- a/crypto/sha/asm/sha1-x86_64.pl +++ b/crypto/sha/asm/sha1-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2006-2026 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/crypto/sha/asm/sha256-586.pl b/crypto/sha/asm/sha256-586.pl index 06aab0a28d69c..3983e55ff9e89 100644 --- a/crypto/sha/asm/sha256-586.pl +++ b/crypto/sha/asm/sha256-586.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2007-2026 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/crypto/sha/asm/sha256-mb-x86_64.pl b/crypto/sha/asm/sha256-mb-x86_64.pl index b619e6bafb744..e53517d787f69 100644 --- a/crypto/sha/asm/sha256-mb-x86_64.pl +++ b/crypto/sha/asm/sha256-mb-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2026 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/crypto/sha/asm/sha512-x86_64.pl b/crypto/sha/asm/sha512-x86_64.pl index 8a74d56b70eb5..cbdd7df67561b 100755 --- a/crypto/sha/asm/sha512-x86_64.pl +++ b/crypto/sha/asm/sha512-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2005-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2026 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/crypto/sha/sha_riscv.c b/crypto/sha/sha_riscv.c index fb05fa886447a..dad1b1187671c 100644 --- a/crypto/sha/sha_riscv.c +++ b/crypto/sha/sha_riscv.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2023-2026 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/crypto/slh_dsa/slh_dsa_hash_ctx.c b/crypto/slh_dsa/slh_dsa_hash_ctx.c index 820b1d37b278b..513f7f7dafc15 100644 --- a/crypto/slh_dsa/slh_dsa_hash_ctx.c +++ b/crypto/slh_dsa/slh_dsa_hash_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/slh_dsa/slh_dsa_local.h b/crypto/slh_dsa/slh_dsa_local.h index 3327d5dd3c72e..d2eccdd08a9a3 100644 --- a/crypto/slh_dsa/slh_dsa_local.h +++ b/crypto/slh_dsa/slh_dsa_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/slh_dsa/slh_fors.c b/crypto/slh_dsa/slh_fors.c index a4359801ba14e..7c8854cc9b386 100644 --- a/crypto/slh_dsa/slh_fors.c +++ b/crypto/slh_dsa/slh_fors.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/slh_dsa/slh_hash.c b/crypto/slh_dsa/slh_hash.c index d05e431e3693b..b0023c955c3e8 100644 --- a/crypto/slh_dsa/slh_hash.c +++ b/crypto/slh_dsa/slh_hash.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/slh_dsa/slh_hypertree.c b/crypto/slh_dsa/slh_hypertree.c index 781bddbc93a9f..e1e2901ce5f32 100644 --- a/crypto/slh_dsa/slh_hypertree.c +++ b/crypto/slh_dsa/slh_hypertree.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/slh_dsa/slh_wots.c b/crypto/slh_dsa/slh_wots.c index c478f282d3639..79f3bca8747d4 100644 --- a/crypto/slh_dsa/slh_wots.c +++ b/crypto/slh_dsa/slh_wots.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/slh_dsa/slh_xmss.c b/crypto/slh_dsa/slh_xmss.c index 9d0b18608e6c9..a53a6c1e99117 100644 --- a/crypto/slh_dsa/slh_xmss.c +++ b/crypto/slh_dsa/slh_xmss.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 957db68da17fa..df92e1d1d5894 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/x509/pcy_cache.c b/crypto/x509/pcy_cache.c index bffa96fd6c51d..b3b6a3da1a9a2 100644 --- a/crypto/x509/pcy_cache.c +++ b/crypto/x509/pcy_cache.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2026 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/crypto/x509/v3_akid.c b/crypto/x509/v3_akid.c index 06b79c26d3aa5..9721518ecc0d5 100644 --- a/crypto/x509/v3_akid.c +++ b/crypto/x509/v3_akid.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2026 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/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c index a22531a71043e..a0b97bb7081e2 100644 --- a/crypto/x509/v3_ncons.c +++ b/crypto/x509/v3_ncons.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2003-2026 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/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index 90fdc60f25a61..7ed046fef4934 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index fc9e43e185a27..00fe2bbe04155 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/crypto/x509/x_crl.c b/crypto/x509/x_crl.c index b320b6ca2c230..1b498ee6b57d0 100644 --- a/crypto/x509/x_crl.c +++ b/crypto/x509/x_crl.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/doc/internal/man3/DEFINE_LIST_OF.pod b/doc/internal/man3/DEFINE_LIST_OF.pod index 6291a2d91062c..95693cf0b2a90 100644 --- a/doc/internal/man3/DEFINE_LIST_OF.pod +++ b/doc/internal/man3/DEFINE_LIST_OF.pod @@ -135,7 +135,7 @@ The rest of the functions described here was added in OpenSSL 3.2. =head1 COPYRIGHT -Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2022-2026 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/doc/man1/openssl.pod b/doc/man1/openssl.pod index 077fc76c53d49..1963715f38a05 100644 --- a/doc/man1/openssl.pod +++ b/doc/man1/openssl.pod @@ -801,7 +801,7 @@ that program with no arguments is now equivalent to C. =head1 COPYRIGHT -Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2026 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/doc/man3/ASN1_INTEGER_get_int64.pod b/doc/man3/ASN1_INTEGER_get_int64.pod index d25c87a5e25c2..69fff46460f25 100644 --- a/doc/man3/ASN1_INTEGER_get_int64.pod +++ b/doc/man3/ASN1_INTEGER_get_int64.pod @@ -123,7 +123,7 @@ were added in OpenSSL 1.1.0. =head1 COPYRIGHT -Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2026 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/doc/man3/ASN1_aux_cb.pod b/doc/man3/ASN1_aux_cb.pod index 9a38ab168ff31..49299492ad492 100644 --- a/doc/man3/ASN1_aux_cb.pod +++ b/doc/man3/ASN1_aux_cb.pod @@ -314,7 +314,7 @@ B operation types were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2026 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/doc/man3/BIO_s_datagram.pod b/doc/man3/BIO_s_datagram.pod index ed2e6881ee17c..9b8c98801ff82 100644 --- a/doc/man3/BIO_s_datagram.pod +++ b/doc/man3/BIO_s_datagram.pod @@ -260,7 +260,7 @@ L, L, L, L =head1 COPYRIGHT -Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2022-2026 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/doc/man3/BIO_s_file.pod b/doc/man3/BIO_s_file.pod index 6cd1da02a3eae..3b867aa6efa86 100644 --- a/doc/man3/BIO_s_file.pod +++ b/doc/man3/BIO_s_file.pod @@ -157,7 +157,7 @@ L, L =head1 COPYRIGHT -Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2026 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/doc/man3/BN_generate_prime.pod b/doc/man3/BN_generate_prime.pod index 4c83fd4a5e4b0..876c26816ccb6 100644 --- a/doc/man3/BN_generate_prime.pod +++ b/doc/man3/BN_generate_prime.pod @@ -248,7 +248,7 @@ BN_check_prime() was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2026 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/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod index f7375f2c58b1b..c2b00b0584f0c 100644 --- a/doc/man3/CMS_EncryptedData_decrypt.pod +++ b/doc/man3/CMS_EncryptedData_decrypt.pod @@ -58,7 +58,7 @@ CMS_EnvelopedData_decrypt() was added in OpenSSL 3.2. =head1 COPYRIGHT -Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2026 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/doc/man3/OPENSSL_init_crypto.pod b/doc/man3/OPENSSL_init_crypto.pod index d6d9ebfb1cf63..d36aef69521d1 100644 --- a/doc/man3/OPENSSL_init_crypto.pod +++ b/doc/man3/OPENSSL_init_crypto.pod @@ -293,7 +293,7 @@ and OPENSSL_INIT_free() functions were added in OpenSSL 1.1.0. =head1 COPYRIGHT -Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2026 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/doc/man3/SSL_CTX_set_msg_callback.pod b/doc/man3/SSL_CTX_set_msg_callback.pod index c1748bbd8a894..f2bdfd7eace55 100644 --- a/doc/man3/SSL_CTX_set_msg_callback.pod +++ b/doc/man3/SSL_CTX_set_msg_callback.pod @@ -181,7 +181,7 @@ the pseudo content type B for DTLS records. =head1 COPYRIGHT -Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2001-2026 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/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod index 1a9ef7d83e323..7ab3575cc5a72 100644 --- a/doc/man3/SSL_CTX_set_verify.pod +++ b/doc/man3/SSL_CTX_set_verify.pod @@ -371,7 +371,7 @@ and SSL_set_post_handshake_auth() functions were added in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2026 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/doc/man3/SSL_get_value_uint.pod b/doc/man3/SSL_get_value_uint.pod index 0e2fb79414e04..907662dc76068 100644 --- a/doc/man3/SSL_get_value_uint.pod +++ b/doc/man3/SSL_get_value_uint.pod @@ -359,7 +359,7 @@ The remaining functions and values described here were all added in OpenSSL 3.3. =head1 COPYRIGHT -Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2026 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/doc/man3/SSL_new.pod b/doc/man3/SSL_new.pod index ae91920a5e31d..25926d492a440 100644 --- a/doc/man3/SSL_new.pod +++ b/doc/man3/SSL_new.pod @@ -135,7 +135,7 @@ L =head1 COPYRIGHT -Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2026 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/doc/man3/X509_get_default_cert_file.pod b/doc/man3/X509_get_default_cert_file.pod index a604cf5571774..982c8954d89a2 100644 --- a/doc/man3/X509_get_default_cert_file.pod +++ b/doc/man3/X509_get_default_cert_file.pod @@ -76,7 +76,7 @@ L =head1 COPYRIGHT -Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2022-2026 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/doc/man3/X509_verify_cert.pod b/doc/man3/X509_verify_cert.pod index 2bbfa25006f9d..bcd4c05399a30 100644 --- a/doc/man3/X509_verify_cert.pod +++ b/doc/man3/X509_verify_cert.pod @@ -480,7 +480,7 @@ X509_build_chain() and X509_STORE_CTX_verify() were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2009-2026 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/doc/man7/fips_module.pod b/doc/man7/fips_module.pod index 6e30f5c5ca6fc..9bd82f46d25d7 100644 --- a/doc/man7/fips_module.pod +++ b/doc/man7/fips_module.pod @@ -617,7 +617,7 @@ FIPS indicators were added in OpenSSL 3.4. =head1 COPYRIGHT -Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2026 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/doc/man7/openssl-core_dispatch.h.pod b/doc/man7/openssl-core_dispatch.h.pod index 7f99fe2a811bd..84668b8047610 100644 --- a/doc/man7/openssl-core_dispatch.h.pod +++ b/doc/man7/openssl-core_dispatch.h.pod @@ -46,7 +46,7 @@ The types and macros described here were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2026 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/doc/man7/provider-kem.pod b/doc/man7/provider-kem.pod index 943f2b69dc319..739264ec329f0 100644 --- a/doc/man7/provider-kem.pod +++ b/doc/man7/provider-kem.pod @@ -253,7 +253,7 @@ were added in OpenSSL 3.4. =head1 COPYRIGHT -Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2026 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/fuzz/provider.c b/fuzz/provider.c index 5cdea4bd9c01b..69905223fbb40 100644 --- a/fuzz/provider.c +++ b/fuzz/provider.c @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2023-2026 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. diff --git a/include/internal/hashtable.h b/include/internal/hashtable.h index edc447b50b290..8bfa539236168 100644 --- a/include/internal/hashtable.h +++ b/include/internal/hashtable.h @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/internal/list.h b/include/internal/list.h index cd43471409f53..270e3f1dbb937 100644 --- a/include/internal/list.h +++ b/include/internal/list.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/internal/quic_ackm.h b/include/internal/quic_ackm.h index aa402d294eca2..5b325e166bd54 100644 --- a/include/internal/quic_ackm.h +++ b/include/internal/quic_ackm.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/internal/quic_port.h b/include/internal/quic_port.h index e9c81d9a52ae2..88fb126e99492 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2023-2026 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/internal/quic_record_rx.h b/include/internal/quic_record_rx.h index 175d3b2f30e7a..a4e9e7cacd259 100644 --- a/include/internal/quic_record_rx.h +++ b/include/internal/quic_record_rx.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/internal/quic_ssl.h b/include/internal/quic_ssl.h index fade4d6316312..a9c17e1087a3d 100644 --- a/include/internal/quic_ssl.h +++ b/include/internal/quic_ssl.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/x509err.h b/include/openssl/x509err.h index 53d3a540f2746..4bbff54a380eb 100644 --- a/include/openssl/x509err.h +++ b/include/openssl/x509err.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/providers/baseprov.c b/providers/baseprov.c index f517e5ae81b53..ad08765f006cf 100644 --- a/providers/baseprov.c +++ b/providers/baseprov.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2026 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/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 8917166bce374..3c749018bcfc4 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c index 0f9027a7d12b2..1bd0d6a5fc81c 100644 --- a/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c +++ b/providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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/providers/implementations/ciphers/ciphercommon_ccm.c b/providers/implementations/ciphers/ciphercommon_ccm.c index f2621c7df9621..7a70b1b099957 100644 --- a/providers/implementations/ciphers/ciphercommon_ccm.c +++ b/providers/implementations/ciphers/ciphercommon_ccm.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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/providers/implementations/encode_decode/encode_key2ms.c b/providers/implementations/encode_decode/encode_key2ms.c index 7500235399d32..2c9bff42bbba1 100644 --- a/providers/implementations/encode_decode/encode_key2ms.c +++ b/providers/implementations/encode_decode/encode_key2ms.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2026 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/providers/implementations/kem/ml_kem_kem.c b/providers/implementations/kem/ml_kem_kem.c index b584c2862088d..14c670784c544 100644 --- a/providers/implementations/kem/ml_kem_kem.c +++ b/providers/implementations/kem/ml_kem_kem.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/providers/implementations/kem/mlx_kem.c b/providers/implementations/kem/mlx_kem.c index fb0a50f753709..a917fa93d5ca7 100644 --- a/providers/implementations/kem/mlx_kem.c +++ b/providers/implementations/kem/mlx_kem.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index a56f1569b93c2..eac99a4fed07d 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index a61d912207edc..1d740307f6a45 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2026 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/providers/implementations/keymgmt/ml_dsa_kmgmt.c b/providers/implementations/keymgmt/ml_dsa_kmgmt.c index 3b7b608651a3f..70e943ff5a03e 100644 --- a/providers/implementations/keymgmt/ml_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/ml_dsa_kmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/providers/implementations/keymgmt/slh_dsa_kmgmt.c b/providers/implementations/keymgmt/slh_dsa_kmgmt.c index 05aa0da7ca5ed..8799df6be6d52 100644 --- a/providers/implementations/keymgmt/slh_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/slh_dsa_kmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/providers/implementations/macs/cmac_prov.c b/providers/implementations/macs/cmac_prov.c index 8cf8ab0342981..14542c6716f2c 100644 --- a/providers/implementations/macs/cmac_prov.c +++ b/providers/implementations/macs/cmac_prov.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2026 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/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c index d3bf4f74d0a22..57da1cfdf33df 100644 --- a/providers/implementations/rands/drbg_ctr.c +++ b/providers/implementations/rands/drbg_ctr.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2026 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/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index 03362e5c8bd43..504af87d5e131 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2026 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/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 6878421ce2b8c..0b8a9ec341d92 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c index d7dff7fd414de..88e5fb982aed9 100644 --- a/providers/implementations/rands/test_rng.c +++ b/providers/implementations/rands/test_rng.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2026 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/providers/implementations/storemgmt/file_store_any2obj.c b/providers/implementations/storemgmt/file_store_any2obj.c index 74c78db14e83e..03560ab4902d6 100644 --- a/providers/implementations/storemgmt/file_store_any2obj.c +++ b/providers/implementations/storemgmt/file_store_any2obj.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2026 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/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index cb04598db829a..0cfc75da0ba1c 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2023-2026 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/ssl/record/methods/dtls_meth.c b/ssl/record/methods/dtls_meth.c index 6116e343853b3..c282efc5ca077 100644 --- a/ssl/record/methods/dtls_meth.c +++ b/ssl/record/methods/dtls_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2026 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/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h index a0d547257fb74..5e3fdd1d05874 100644 --- a/ssl/record/methods/recmethod_local.h +++ b/ssl/record/methods/recmethod_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 71cedd641b652..3ab50facc93eb 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 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/ssl/rio/poll_builder.c b/ssl/rio/poll_builder.c index 8088b17ad7ada..f808e9b01e748 100644 --- a/ssl/rio/poll_builder.c +++ b/ssl/rio/poll_builder.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/ssl/rio/poll_builder.h b/ssl/rio/poll_builder.h index 0fcd543b5935b..48605d7182234 100644 --- a/ssl/rio/poll_builder.h +++ b/ssl/rio/poll_builder.h @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/ssl/rio/poll_immediate.c b/ssl/rio/poll_immediate.c index 6807926f1ae28..95410df0d8f43 100644 --- a/ssl/rio/poll_immediate.c +++ b/ssl/rio/poll_immediate.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/ssl/rio/rio_notifier.c b/ssl/rio/rio_notifier.c index 5dd42537e877c..abc1755dae029 100644 --- a/ssl/rio/rio_notifier.c +++ b/ssl/rio/rio_notifier.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/ssl/ssl_cert.c b/ssl/ssl_cert.c index e9b05225ad7a8..43d1191c6e2e7 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 893a2c004f17f..d974ac6ecfe0b 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 33642ea8df0ab..13846bc115962 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2026 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/test/ca_internals_test.c b/test/ca_internals_test.c index ed922a36dd28a..94fd7b5f7aefe 100644 --- a/test/ca_internals_test.c +++ b/test/ca_internals_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2021-2026 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/test/cmp_protect_test.c b/test/cmp_protect_test.c index a6b2a9ddb9063..dce083714393f 100644 --- a/test/cmp_protect_test.c +++ b/test/cmp_protect_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2026 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * diff --git a/test/cmp_vfy_test.c b/test/cmp_vfy_test.c index cbfe78911d6eb..d18e2eb533ead 100644 --- a/test/cmp_vfy_test.c +++ b/test/cmp_vfy_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2026 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * diff --git a/test/crltest.c b/test/crltest.c index 904cf089440ba..c4419e299b7b3 100644 --- a/test/crltest.c +++ b/test/crltest.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2026 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/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index 05bae3189a15e..c73431338d9e7 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/test/helpers/quictestlib.h b/test/helpers/quictestlib.h index a60d40ffe3c14..c03bfac78fec9 100644 --- a/test/helpers/quictestlib.h +++ b/test/helpers/quictestlib.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/test/helpers/ssltestlib.c b/test/helpers/ssltestlib.c index 7173415a7217b..27c113383c64a 100644 --- a/test/helpers/ssltestlib.c +++ b/test/helpers/ssltestlib.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2026 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/test/helpers/ssltestlib.h b/test/helpers/ssltestlib.h index d8bb3bfe62f8a..86397f2b6fbd2 100644 --- a/test/helpers/ssltestlib.h +++ b/test/helpers/ssltestlib.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2026 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/test/list_test.c b/test/list_test.c index 7798ea68348ed..4170df92cd39c 100644 --- a/test/list_test.c +++ b/test/list_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/test/p_test.c b/test/p_test.c index 655cb7ce6fc8f..aca1707b05cb0 100644 --- a/test/p_test.c +++ b/test/p_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2026 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/test/pairwise_fail_test.c b/test/pairwise_fail_test.c index 3446d23166e52..628f123cb2711 100644 --- a/test/pairwise_fail_test.c +++ b/test/pairwise_fail_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2023-2026 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/test/pkcs7_test.c b/test/pkcs7_test.c index 8ce14f40c15de..8d9c111e58bbc 100644 --- a/test/pkcs7_test.c +++ b/test/pkcs7_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2021-2026 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/test/punycode_test.c b/test/punycode_test.c index 3591f0dc19a09..7911b9d6d8578 100644 --- a/test/punycode_test.c +++ b/test/punycode_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/test/quic_ackm_test.c b/test/quic_ackm_test.c index 88cd033837cdb..a23ea28a6b3f8 100644 --- a/test/quic_ackm_test.c +++ b/test/quic_ackm_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/test/quic_multistream_test.c b/test/quic_multistream_test.c index 1987bd826136e..93a7bd2ff2ec7 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2023-2026 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/test/quic_tserver_test.c b/test/quic_tserver_test.c index a80987296724e..559a7d954fa8b 100644 --- a/test/quic_tserver_test.c +++ b/test/quic_tserver_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2026 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/test/radix/quic_bindings.c b/test/radix/quic_bindings.c index d58476e9aff8d..ab39a89412e6c 100644 --- a/test/radix/quic_bindings.c +++ b/test/radix/quic_bindings.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2024-2026 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/test/radix/quic_ops.c b/test/radix/quic_ops.c index 88b8b0e371a27..5e0642ec56f33 100644 --- a/test/radix/quic_ops.c +++ b/test/radix/quic_ops.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2025-2026 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/test/recipes/20-test_cli_fips.t b/test/recipes/20-test_cli_fips.t index daf7368e91c14..fd8842b867e58 100644 --- a/test/recipes/20-test_cli_fips.t +++ b/test/recipes/20-test_cli_fips.t @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2020-2026 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/test/recipes/30-test_evp_data/evprand.txt b/test/recipes/30-test_evp_data/evprand.txt index bf7db44030023..6f12c73c26942 100644 --- a/test/recipes/30-test_evp_data/evprand.txt +++ b/test/recipes/30-test_evp_data/evprand.txt @@ -1,5 +1,5 @@ # -# Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2020-2026 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/test/recipes/30-test_pairwise_fail.t b/test/recipes/30-test_pairwise_fail.t index ca2d1f96e497c..1b3269a9824b6 100644 --- a/test/recipes/30-test_pairwise_fail.t +++ b/test/recipes/30-test_pairwise_fail.t @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2023-2026 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/test/recipes/65-test_cmp_msg.t b/test/recipes/65-test_cmp_msg.t index 19c17efca4eab..ac6648296749d 100644 --- a/test/recipes/65-test_cmp_msg.t +++ b/test/recipes/65-test_cmp_msg.t @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2007-2026 The OpenSSL Project Authors. All Rights Reserved. # Copyright Nokia 2007-2019 # Copyright Siemens AG 2015-2019 # diff --git a/test/recipes/70-test_sslrecords.t b/test/recipes/70-test_sslrecords.t index 3dc7762b606ad..e2738cf8bb676 100644 --- a/test/recipes/70-test_sslrecords.t +++ b/test/recipes/70-test_sslrecords.t @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2026 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/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index 95383108384b7..44183f6756f09 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2026 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/test/rpktest.c b/test/rpktest.c index f3de1a8b143d9..f81a60c2f6411 100644 --- a/test/rpktest.c +++ b/test/rpktest.c @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2023-2026 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/test/secmemtest.c b/test/secmemtest.c index b0ac91a38f6a1..8bac1be2eca0b 100644 --- a/test/secmemtest.c +++ b/test/secmemtest.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2026 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/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm index d2fda702bfaf9..729b351b3f0af 100644 --- a/util/perl/TLSProxy/Proxy.pm +++ b/util/perl/TLSProxy/Proxy.pm @@ -1,4 +1,4 @@ -# Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2026 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 From 2197faa57894849539d2bde0f869fe73d648d4d1 Mon Sep 17 00:00:00 2001 From: openssl-machine Date: Tue, 25 Aug 2026 11:56:38 +0000 Subject: [PATCH 175/189] make update Reviewed-by: Neil Horman Reviewed-by: Milan Broz MergeDate: Tue Aug 25 11:56:39 2026 Release: yes --- providers/fips-sources.checksums | 152 +++++++++++++++---------------- providers/fips.checksum | 2 +- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/providers/fips-sources.checksums b/providers/fips-sources.checksums index a2f5817e26de4..85af251d79e22 100644 --- a/providers/fips-sources.checksums +++ b/providers/fips-sources.checksums @@ -20,12 +20,12 @@ f1d8b7a3da1ec053d38be4fc776fef1e4fba328bfa2bfd928c2a2cd3b14f08ff crypto/aes/asm ee4e8cacef972942d2a89c1a83c984df9cad87c61a54383403c5c4864c403ba1 crypto/aes/asm/aes-sparcv9.pl 391497550eaca253f64b2aba7ba2e53c6bae7dff01583bc6bfc12e930bb7e217 crypto/aes/asm/aes-x86_64.pl 3b5ee174fa52d732d882ab4b2ffe59235d3bff66651714f32e743fcadaf1d970 crypto/aes/asm/aesfx-sparcv9.pl -14359dc32b7f4e5c08227fb9ac8f9232c1287399463b233fec4a2ab0c19f68d1 crypto/aes/asm/aesni-mb-x86_64.pl -f525e1bca51d39adcd411cbf8f874fe1441b23a6f614644da78dfd8544d13b23 crypto/aes/asm/aesni-sha1-x86_64.pl -895f94d7befb90e82f9d300ed8f870e790101f30ba72b249a2c503f07aec7dd2 crypto/aes/asm/aesni-sha256-x86_64.pl +e220d630965eb2672dca757aefcb9654928288772fd495da3a495b405b5f21ff crypto/aes/asm/aesni-mb-x86_64.pl +83a08babb80e15606bb52c6b4fcd1a6416d3b165b9cbfa42678ebe2e27c3b8d4 crypto/aes/asm/aesni-sha1-x86_64.pl +6808938757a489c3827e6da78f9ce227d88efcc29c3467fa0329b50b761523eb crypto/aes/asm/aesni-sha256-x86_64.pl 4ff74d4e629a88ef5a9e3d3f5b340fc0a4793d16d7cc7f1b70da62512a856248 crypto/aes/asm/aesni-x86.pl 25881237d026cebd96877a2ea2729db1ce512875cb2a10ca0cd1d6ddf4b51a3b crypto/aes/asm/aesni-x86_64.pl -6047359ad3967168812fbc8a95cb851b72c09f7846be2f03ec2ab93531a9c2bd crypto/aes/asm/aesni-xts-avx512.pl +00dd3a64df71ebd61fd35d2a6179d07cc86fc156cce1541ef176ecafb815f4bb crypto/aes/asm/aesni-xts-avx512.pl 0489a10fbb1a8ca3652848d5c1e14e519501e189bad3e5827a573c26df359691 crypto/aes/asm/aesp8-ppc.pl e397a5781893e97dd90a5a52049633be12a43f379ec5751bca2a6350c39444c8 crypto/aes/asm/aest4-sparcv9.pl 578142d03bc47353952fca2027eb63ec97ce9a1379c0f3c7ac0fdf110eb3378b crypto/aes/asm/aesv8-armx.pl @@ -39,7 +39,7 @@ c3541865cd02d81101cdbab4877ed82772e6980d2c677b9008b38fa1b26d36d4 crypto/aes/asm c6935d2ab7925022cb3d76446536ff01b1a1b8eb7eac619d034a29aad17ed45f crypto/aes/asm/vpaes-x86_64.pl 2bc67270155e2d6c7da87d9070e005ee79cea18311004907edfd6a078003532a crypto/alphacpuid.pl 269e52f8867c13ca75d2f88ec1f89b692cb8c6c3ee89abe2fd3c1821925191d8 crypto/arm64cpuid.pl -7a7c1d063be476f35442b0b056cfad0cf62190b603304abd283906ab40590167 crypto/armcap.c +b0242943b097f7640f1b3c33313934a98caf45d47d4403e9e53d826f6d2dc0c4 crypto/armcap.c d9f923daabe7537d1063b182f9f220655abd182ef4c55a0194a7ee8d6030b5bd crypto/armv4cpuid.pl e886d814c34492504cc9a2451c67fd8c0b4e83e8618f931632400cfe522b6e4d crypto/asn1_dsa.c 819c9fd2b0cae9aab81c3cbd1815c2e22949d75f132f649b5883812d0bbaa39a crypto/bn/asm/alpha-mont.pl @@ -58,14 +58,14 @@ b27ec5181e387e812925bb26823b830f49d7a6e4971b6d11ea583f5632a1504b crypto/bn/asm/ 59cd27e1e10c4984b7fb684b27f491e7634473b1bcff197a07e0ca653124aa9a crypto/bn/asm/ppc.pl 0b3350f56d423a4df918a08e90c7c66227c4449a9f9c44096eacc254ebc65f9f crypto/bn/asm/ppc64-mont-fixed.pl a25be64867ab837d93855af232e2bfa71b85b2c6f00e35e620fdc5618187fb6f crypto/bn/asm/ppc64-mont.pl -b3aad31ab658eceaa9c5e734e19f39c33991f4839ab55b0cec8018020b1a305e crypto/bn/asm/rsaz-2k-avx512.pl -03f6cc678f377c5cd953e8da135c5d76dc1cd011565118c99e25bff91e7271df crypto/bn/asm/rsaz-2k-avxifma.pl -e914311420ae4486ab6000cc6ab424f04d8a042bda40ab8f288348dc9f0eb595 crypto/bn/asm/rsaz-3k-avx512.pl -95b11e0b04c38bde06d152dfde5ab970dab27cccdfeac998e1bc293e01520474 crypto/bn/asm/rsaz-3k-avxifma.pl -e13bd2df8c591052ddf16a839072f43353841f9f35e0ac95f836511838dbc771 crypto/bn/asm/rsaz-4k-avx512.pl -cf92b66c4032703b7ce03ff6aa36887d14e31a8861e7aa21c46a466ea4802851 crypto/bn/asm/rsaz-4k-avxifma.pl -6e47bf041e51d8086c4933c2a5da3ce6d1b136592984754461d59aa81e4995a6 crypto/bn/asm/rsaz-avx2.pl -b42f6cf0fbf9eae58343df9629e7a9e5b8814195ea0c9882d7b143a0841cc018 crypto/bn/asm/rsaz-x86_64.pl +d48aded8547aa44a4af0d76d4675320628c66ba54e6fda865804953eefa8e853 crypto/bn/asm/rsaz-2k-avx512.pl +ae2e714dc003867c31136f939f8d47eb35eac3de36dbeea8f028a48d03b964ec crypto/bn/asm/rsaz-2k-avxifma.pl +6b5f35bf328f19b3add87a9715736ca92a8165920264311e20d3477a41a90a82 crypto/bn/asm/rsaz-3k-avx512.pl +b0ef4c3bb3a835066e9f7cafab22efc9d668b6debf5b9b9ec312cabae9412631 crypto/bn/asm/rsaz-3k-avxifma.pl +ca2d4486ee67f2015a8580664f3bbc28c23201205a2422d3a972cdf6ba59147a crypto/bn/asm/rsaz-4k-avx512.pl +80b0e7aca0ebee78fb3c651723e7f0eaac43a5b6a2bcf87b98a454a248abb945 crypto/bn/asm/rsaz-4k-avxifma.pl +7d686b484ea2bb65091c6ed3e74d5f4063ed4a8ecc09b7bef8d3a3aa57c4121e crypto/bn/asm/rsaz-avx2.pl +bec7e89c5a33652bbff20c95a6fe82bd96f7f2f61a3544c122f3af6f4f162110 crypto/bn/asm/rsaz-x86_64.pl 30fedf48dfc5fec1c2044b6c226dd9fc42a92522cc589797a23a79d452bdd2cf crypto/bn/asm/s390x-gf2m.pl 590388d69d7ac3a0e9af4014792f4f0fdb9552719e8fb48ebc7e5dfca2a491d4 crypto/bn/asm/s390x-mont.pl aa02597f3dc09cfbc190aedb75711859ba0f3efff87067ebfba1ec78ebee40d7 crypto/bn/asm/s390x.S @@ -81,9 +81,9 @@ d24f3e97239c8eed5efc721521b025b7256c15e67a54ea6b5c4cf8f7cd0f89ea crypto/bn/asm/ 90d4ae234c08267adce9ed38d56e0edc223f7480cb9605f5d7399d0b3914c6be crypto/bn/asm/x86-mont.pl 0e3e572cd864bcb9222cdad7ca4e8dae4250f6f76c2b66e1f0e46df1cc0cf371 crypto/bn/asm/x86_64-gcc.c 709ddee92e9222ee0ed27bfb90db556e85e2d302e4a9131afa25fdc14c4d858f crypto/bn/asm/x86_64-gf2m.pl -da7f7780d27eed164797e5334cd45b35d9c113e86afaca051463aef9a8fd787c crypto/bn/asm/x86_64-mont.pl -efe70ef06b5d92539f8a239c98c0261d93a15b3e418ca87d97ec569da9e6e9d3 crypto/bn/asm/x86_64-mont5.pl -0ea8185a037a2951bb3d1e590bbbdeac305176d5e618f3e43a04c09733a9de34 crypto/bn/bn_add.c +4ad5e97a7ed376d2cc079a3eabfbdc0cce3fe6e61751324ef18b72d24f7851d6 crypto/bn/asm/x86_64-mont.pl +11eebbeb8ae59158e780d74300b333de9705aefdde73cff280286c053c8743da crypto/bn/asm/x86_64-mont5.pl +7c81cd72fbf6f2dd85cbcbf40027301c98c1701928d3199edb2b8fdf04a5ca5e crypto/bn/bn_add.c 529933a6592cf82abde515dae10db17833a16ec29cb89ec577c0a184838fe27b crypto/bn/bn_asm.c feef3a84a40034291286882d483ac23ab55631c3c93f40ba0ea98944916ff3ec crypto/bn/bn_blind.c 1b8f89064c287669a834fe032ef823796f7355ed7e6da08d6c56c0a4cd0bba01 crypto/bn/bn_const.c @@ -91,13 +91,13 @@ eee3d2710144b0e860c57e84f5adc6b2bf64fc27cbd202a8ca2630aefed3b84c crypto/bn/bn_c 282f06fbdeb991d90337787c6407020e940b6d5e187a06866f1a7787c10a0c1b crypto/bn/bn_ctx.c b1b1c5fb8a45fde5755dfd5da62b68100b94f8c492c950719c108c384ea7f3c4 crypto/bn/bn_dh.c 4824f271f0ddc487b5991fbd92f7f7695aeeac234e076078f37da027999cdd88 crypto/bn/bn_div.c -d36b2be05469f144f52173616e413a7bdd836607fccf94cf543cc7f5a343b962 crypto/bn/bn_exp.c +f1e98f178356791a3d54f586c19d1639d8e89b2cf6e6a4de783327ceada296a2 crypto/bn/bn_exp.c ce5219203bf869561297978d6d416357a441864cd801865503dfd455c481960c crypto/bn/bn_exp2.c 18ac3f6fe64225f72243689199839ea2ce2aa61d80b084bc4cd9efe1c7cc9d89 crypto/bn/bn_gcd.c b643fdcd91ad7dfcfa97a0bb235221b024b8a77faa7890f0bcb9681ea2c64c49 crypto/bn/bn_gf2m.c 73ee247467879d4ec984c9900dfe7761233c5b889b8762be37c7e8fdd6d1d210 crypto/bn/bn_intern.c ff147e5e032cc7c772b73a91fc6e24d8d9516e642d29354445d1f82d64b1d924 crypto/bn/bn_kron.c -df9aebbdcca87fc5715dde430687fb516d8de0dac70c8910409fb73d6dd2305b crypto/bn/bn_lib.c +c4bae573e4e7132106b1151e8983cb63200dd9e49dc464e805f0fc50d55374d0 crypto/bn/bn_lib.c cd7bade0f2e223fe34f6e2f8cc87098ac8f0af96ec62ada5e67f6a2344d48ef0 crypto/bn/bn_local.h b494fd85387afa7816422922e52987e0faefc3c890c972e7d4fe04f620dfc59a crypto/bn/bn_mod.c 39a8fe0bb625b4c11b74998ce6fd99b7655228aaa7d7ad3076f61741937ae14d crypto/bn/bn_mont.c @@ -126,7 +126,7 @@ ab29529cca1308302d852999f2790c404a4dc0ef8cd6653260739f70b2f22758 crypto/core_fe 0e3519aec0d93b0700d1175616b8bfca9c045989fad515d2202dd7dff9caa5ac crypto/core_namemap.c a62f653b8a6ee765be704980425617e04e1d242f9735efaf35fc6e00815ff2a7 crypto/cpuid.c a73118d14eeb232ff250ae908204ddd7cf33deba5f3ca68a2dbb51b020946b0e crypto/cryptlib.c -66dbfc58916709d5a6913777346083247942a8d9458ee9b2bf443f0ea4988d64 crypto/ctype.c +0145299d43dbb60e85ef6b97cf7496dec55cc37b75433e1403c11adfa3e90c5f crypto/ctype.c b9fabcf8480b8c9c7847a0c9af0fcc13b6c4b4a4558d5e445e6409221e6f8113 crypto/der_writer.c 135ef65f7602432f8c87ad18fdd90b867f1c46b1c631522d56181fbed2106b05 crypto/des/des_enc.c 7c2cea4c850398158b4aff172b242de0cc436b66f62fc701ccca3fe5489925a5 crypto/des/des_local.h @@ -136,7 +136,7 @@ c1e015556147b40c854bf0ab275c54235f99001d04c6d49f158fba6865eb5439 crypto/des/fcr dc2e7899593032fdf0fcab18f5549c52f12bad2225aac9a08c4622ffee34b193 crypto/des/set_key.c 41b7fc5e67814311b878684e3f29cff60e228f1516f670d81bf43130f2668ae8 crypto/des/spr.h b842e39f34996d74cdc9b9be5fc93c27fc91ef6141fae83163e09f6b0eff1e09 crypto/dh/dh_backend.c -091ec05b6316cce34305ae8f8014043c7c9b72098aa1abe9c35dcbcdb4b77cd0 crypto/dh/dh_check.c +380d55ea09a50ba3ece173e64db90782efae08ca56ac51cb4d31b9a303b429ea crypto/dh/dh_check.c c117ac4fd24369c7813ac9dc9685640700a82bb32b0f7e038e85afd6c8db75c7 crypto/dh/dh_gen.c 1149e214ed664540434912e284730a3c87385172e4c6d1c944ea56659e2dd762 crypto/dh/dh_group_params.c a539a8930035fee3b723d74a1d13e931ff69a2b523c83d4a2d0d9db6c78ba902 crypto/dh/dh_kdf.c @@ -146,7 +146,7 @@ a9166c3cc60f4281e9d471c64145e0a78fc9dc43b8bc9e5de96d91eb7d277da3 crypto/dh/dh_l 40065939139ac28aa52838aa54d257da82fce73504557f7a9ad34d13824e0cb9 crypto/dsa/dsa_backend.c 786d6c65ced7ee4e25f5dd7c3150259ec95b6aa321a7590d905757b8139f8230 crypto/dsa/dsa_check.c ae727bf6319eb57e682de35d75ea357921987953b3688365c710e7fba51c7c58 crypto/dsa/dsa_gen.c -dee83cb278b3f712a62bd3477bdecf7b83e6df38ada2f3e1ca043d37327e2da4 crypto/dsa/dsa_key.c +43f8fba4f50fbc94b1532a7667c9cfdc91b357e8658fd5fe0dcd302ea93ae9a0 crypto/dsa/dsa_key.c 7d44106570c0ff9a44de874ea2daeaa87ea4c814fef6af0a26f655120a54f529 crypto/dsa/dsa_lib.c 98ce52d325d2409d7851f1e1226755136f115c884d227d2ae3e4f9b61fc323b8 crypto/dsa/dsa_local.h 3428bc7602f344f8b8d4a5807b0a7e982cbead1ec28be73ad77b5f849b034993 crypto/dsa/dsa_ossl.c @@ -159,9 +159,9 @@ d9722ad8c6b6e209865a921f3cda831d09bf54a55cacd1edd9802edb6559190a crypto/ec/asm/ 3715ddd921425f3018741037f01455ed26a840ace08691a800708170a66cf4d2 crypto/ec/asm/ecp_nistz256-ppc64.pl cfe7e75a2fddc87a7251684469a8808b9da82b2f5725eafad5806920f89932bd crypto/ec/asm/ecp_nistz256-sparcv9.pl 922725c4761cfa567af6ed9ecab04f2c7729ae2595f2fc0fa46dc67879dc87b0 crypto/ec/asm/ecp_nistz256-x86.pl -afa4497cfbf9ef7805e42ae6a61c7d983e8a789b270d498a07785570ab85a9fa crypto/ec/asm/ecp_nistz256-x86_64.pl +f5c4f8c74a44c8723293e3bb64c0c2cf75dc354466ac9f93ebfdab1df34b64c4 crypto/ec/asm/ecp_nistz256-x86_64.pl cc727533130f5f1a29229929b3d4e8454585d647be25d6344f3c6a0240998368 crypto/ec/asm/x25519-ppc64.pl -ee897e230964511baa0d1bf95fb938312407a40a88ebe01476879c2763e5f732 crypto/ec/asm/x25519-x86_64.pl +ee576a748991bb2cf0a37437e46a23dd55dfd35d989e087d122c7cf0f332eb2a crypto/ec/asm/x25519-x86_64.pl 2e7b5d2a3eff0b8a90c1de3f28a7bf59b1057e7694c0e36909e774343cef609f crypto/ec/curve25519.c 784c03c3f81fd0c363cd0500fbd95f3e49c65f47a249f7ba25fad42a41d3eea2 crypto/ec/curve448/arch_32/f_impl32.c 8e75602d4d492316d318bac147eaa09d87b0eeda0d450e18683d935673ab61b0 crypto/ec/curve448/arch_64/arch_intrinsics.h @@ -185,7 +185,7 @@ dfbccf591879eecbd9ed75da1fbe6c7b1672d07648fd43b37755dfe248253bb2 crypto/ec/ec_b 3a3c4f4767513b4fbbabdea2918d7c7d105eb573334a7fd893b866989463c4d2 crypto/ec/ec_check.c f3991bfc65a7371b84afd0cc328e3cbd4736edf7267e4b731dd82677bfab047a crypto/ec/ec_curve.c 8cfd0dcfb5acbf6105691a2d5e2826dba1ff3906707bc9dd6ff9bffcc306468f crypto/ec/ec_cvt.c -add58bcaf43a28e66b3a6ec1f70ed9b0b4a4a0d40230e903a26a1ff1129649e0 crypto/ec/ec_key.c +b94eb087740dde2bf697cfbc5e8a17efd80e84c5072c9c72f8ed2f9155976d37 crypto/ec/ec_key.c 35515133fb3c33c5736a9f744e835b9fc0775193357ab2492f11d0f63503c65e crypto/ec/ec_kmeth.c 652a1544120bf0fecde46a8e18cc28fffcb7cd864be2e2b84c99d571ba320e64 crypto/ec/ec_lib.c 0d113ac5dbdb420ba3d1c060f4fa3300fc0a81b571a919c2b176022fdca89878 crypto/ec/ec_local.h @@ -214,7 +214,7 @@ ed0217e7c2049b44a454b40e7e18385eadb34bce1bcf54337f420cbf988775da crypto/evp/asy e997e921669076c51e230ccb2e36b1c6755fe408c61b1177d2aa67529cab15f3 crypto/evp/evp_local.h 8963ef06e4d228f7067917434f60f0502dc4bbdf3b271649498b734f4074bfb0 crypto/evp/evp_rand.c 0bdae4714221662282dccd5b1f2485370d24e463c11bdbb71a310f34616954fe crypto/evp/evp_utils.c -8f4194bcc2e0de69236925aa7515bc31f36ed113dcd3cee5d71167ac770cdfdd crypto/evp/exchange.c +1d78745866dde8224eec50c8553a15b51aa14bc3313969479806b3c3024c7282 crypto/evp/exchange.c 294284ad040fe4b74845f91b1903c961c757e1ef3fcc2ffa35f43f37f1655e64 crypto/evp/kdf_lib.c 532f0ff4ab32068f160016f39cd520fadfbd09b81b3b3b562bf543acafb38889 crypto/evp/kdf_meth.c d911878128b90b98f3a4a1fb844ef3a20d35eafda3f80773dac8ce93c55bc352 crypto/evp/kem.c @@ -239,7 +239,7 @@ bb208ef3a2c7ebdc518bd38f2f07a17cff356040f1c5d68eea13bd9275897a52 crypto/ffc/ffc e9a500ddbe96cb5b302fd2db74fac0924a6ac45732df5ee1c09e82b19d06ccfd crypto/ffc/ffc_params_validate.c f172c8c2112ee82716a7bc3a3e05d5cc26188c66b9d768ac1ff906845063d2cc crypto/hashtable/hashfunc.c ed523d9793ff9db947857bca354067d17b8de5a4b28604dbf902320e62d93e33 crypto/hashtable/hashtable.c -7a9af0b14f1463b36de0689bc434a318adcb7990bb23862bf1d2a0adf510583a crypto/hmac/hmac.c +9a63ec43c8b9a55e0b135394a659026c1d1236978ebbb5df0e3c4c5c58b62ef4 crypto/hmac/hmac.c 907dd44e0bf873eebefcb4d82975b72ecec9e0f3c348c79314450fdaa78d4073 crypto/hmac/hmac_local.h 0e2d6129504d15ffaf5baa63158ccec0e4b6193a8275333956d8f868ef35127e crypto/ia64cpuid.S 29c020cf599c24ef9969a42e00e690a7b463c20dd90356b0a4117ca31b13db6f crypto/initthread.c @@ -248,28 +248,28 @@ ed523d9793ff9db947857bca354067d17b8de5a4b28604dbf902320e62d93e33 crypto/hashtab 899ba6a9049a61d5b175637907f747f58863cd8950409cefac8fbc8f574f970c crypto/loongarch64cpuid.pl 460a7af09cde89a820b091522ada1310cfcec99c60aee505f94c48c35e9a29e8 crypto/loongarchcap.c f866aafae928db1b439ac950dc90744a2397dfe222672fe68b3798396190c8b0 crypto/mem_clr.c -23ff635daa1a3149e14de6c2a41b82a7587801581bdf39b8a82e9c624da95471 crypto/ml_dsa/ml_dsa_encoders.c +1812ee360303b9fdcebe6dd0690944646bd9605ee67e3554c691cf5993293c46 crypto/ml_dsa/ml_dsa_encoders.c 825105b0a2c4844b2b4229001650ff7e61e1348e52f1072210f70b97cd4adb71 crypto/ml_dsa/ml_dsa_hash.h -2fbef0188a8606c56f2ffffecfbbbd13ccd454c2af949d6e37fb7c929974f1d4 crypto/ml_dsa/ml_dsa_key.c +2bebd01093de6f77dabb8b6e5ac3deaad9104904956691e22d80f105a3e526c2 crypto/ml_dsa/ml_dsa_key.c 579c1a12a5c5f014476a6bf695dc271f63074fb187e23ffc3f9ccb5b7ea044f1 crypto/ml_dsa/ml_dsa_key.h 3f98eb0467033d0a40867ef1c1036dcfea5d231eeac2321196f7d7c7243edace crypto/ml_dsa/ml_dsa_key_compress.c 170292bfc8761e39b688ccfb21b3660af6e1a875aa38ff7448cc22f71f5874c5 crypto/ml_dsa/ml_dsa_local.h -0490a89372b79d98c2fdc294f836fddd7a54a148202ffbd50c2d4371816a94d8 crypto/ml_dsa/ml_dsa_matrix.c +6ac18f9ef27efc7fddc38ad5edec94fcf76a972ca9fcb6bdc5472673d885d238 crypto/ml_dsa/ml_dsa_matrix.c ff65c82c56e341f47df03d0c74de7fb537de0e68a4fa23fa07a9fdb51c511f1c crypto/ml_dsa/ml_dsa_matrix.h c2652262227348b8bb053a239e8491b26f08d6fadc47ba3471302f5797ae1c62 crypto/ml_dsa/ml_dsa_ntt.c 3e0980e67842c4d8637fa449ac41e9d650c614c1074c29f1021605d229a4f73d crypto/ml_dsa/ml_dsa_params.c 10e37ab3ee09a45d99007665e073efb2b062c819f30af8694c6b0f411eb33822 crypto/ml_dsa/ml_dsa_poly.h -26be5266a9f1a33999a5a68c96cffc7932ba64521d9554dabe7397591611c852 crypto/ml_dsa/ml_dsa_sample.c -26ce39dd4cdac0a1c00cee24d53e156c16a1577c71a8a96bce3e2b4130afa6f5 crypto/ml_dsa/ml_dsa_sign.c +abb4f2263fb9b6d08911e1b8e2df2c2de636d6255f7cf3eee594f50dedcefc0c crypto/ml_dsa/ml_dsa_sample.c +f1cbf5ebe46fe456e338a496193bf028d48a28bb3d4804591094babe84d83b25 crypto/ml_dsa/ml_dsa_sign.c 5217ef237e21872205703b95577290c34898423466a465c7bd609b2eb4627964 crypto/ml_dsa/ml_dsa_sign.h -8311e08d9d0e2e073092d0cfaf64851fb8d0f0708dfc2707422f525f87f269d0 crypto/ml_dsa/ml_dsa_vector.h -0fbbb11e30b7e3f4e5366334e273dcc3f6440ed04a0758f0c99279c25b8c0baf crypto/ml_kem/ml_kem.c +afc44b2cdf6a03555cebcc0398179b44f5810098d0b17dcb2b0c0c62023d6964 crypto/ml_dsa/ml_dsa_vector.h +dd95a5261fd1624e1e93270b0dc9404c887506a402d55521a5074975db833fd6 crypto/ml_kem/ml_kem.c 36e24eae5d38cc9666ae40e4e8a2dc12328e1159fea68447cb19dab174d25adf crypto/modes/asm/aes-gcm-armv8-unroll8_64.pl 33357356cd739d4ae89d52f0804b6900e4b94d8829323819c6f64c8908e978df crypto/modes/asm/aes-gcm-armv8_64.pl -a91995f81b384b175ecf252690030bb068d6af64bfcdab2fe753484b2d07a184 crypto/modes/asm/aes-gcm-avx512.pl +573c286991352233cb068d0e218c5cb1e6fe5d07a924496dbccca95fa82e1d4d crypto/modes/asm/aes-gcm-avx512.pl 8fab6574aa99ee635d564dbe68b014562b61af37fa4f151210690837cdae6707 crypto/modes/asm/aes-gcm-ppc.pl dd0de5ca8913a941cfff781a42fba43227e133976a24d0fddebf63909f7e010a crypto/modes/asm/aes-gcm-riscv64-zvkb-zvkg-zvkned.pl -9dcd3be86cda832ebe0394f5a859a761f4b711f2010fb606457f754722c5fb84 crypto/modes/asm/aesni-gcm-x86_64.pl +a4fad5a5cb112929323632e4f3f5fce7d6f0ceb6ea2e3ed1a4a2165f05fbf0b5 crypto/modes/asm/aesni-gcm-x86_64.pl c2e874a8deb418b5d8c935b2e256370566a5150e040c9fa008cdb5b463c26904 crypto/modes/asm/ghash-alpha.pl 6bc7d63569c73d7020ede481f2de05221ac92403c7cc11e7263ada7644f6aa9b crypto/modes/asm/ghash-armv4.pl 097975df63370de7ebea012d17de14fc1f361fb83acf03b432a99ae7d5bceb24 crypto/modes/asm/ghash-c64xplus.pl @@ -281,7 +281,7 @@ e6d6ce559210aee1e97f098683e290c221cc90f6f4f8047b331e8071a8387559 crypto/modes/a 92071f9c046f312c4eb7df483f385bc71ade863392e1acf3e821912bcc5cfaa7 crypto/modes/asm/ghash-s390x.pl 6af1a05981e1d41e4dea51e58938360e3abc4a4f58e179908242466d032b1a8a crypto/modes/asm/ghash-sparcv9.pl 26f55a57e77f774d17dfba93d757f78edfa3a03f68a71ffa37ccf3bfc468b1e2 crypto/modes/asm/ghash-x86.pl -487e23973c9c782d375a956da6231e91f450182d8822d3f86fd4924e143fed70 crypto/modes/asm/ghash-x86_64.pl +3d746cc0cf6cca866e34cdbbd79f5660244033fa440ed82aaaa9dd16cebf821f crypto/modes/asm/ghash-x86_64.pl a4e9f2e496bd9362b17a1b5989aa4682647cefcff6117f0607122a9e11a9dfd9 crypto/modes/asm/ghashp8-ppc.pl 92f17ee53bd40123358ce5b37bcd6063bfa7d6860dd734d4ac585249c03a6b32 crypto/modes/asm/ghashv8-armx.pl ca4be187fc1805d498f2adb823509f0519e214644029c18d331b5b01a0891a9d crypto/modes/cbc128.c @@ -312,7 +312,7 @@ ed6956c34da5127fbf8f1a067654b617c261039743a12fd1d296a1dd01b05c26 crypto/params_ fcafd9ac56254e921f43dda47aa6d19ff42b3461ff3a72e0bff1840793f96701 crypto/provider_core.c aa58d7800d3ccf2989b0de3c2e2710dfac36c88dc51659129897b0dfd2162527 crypto/provider_local.h 5ba2e1c74ddcd0453d02e32612299d1eef18eff8493a7606c15d0dc3738ad1d9 crypto/provider_predefined.c -5f077b3d3c0127c9051907f91b7184d18ad045452e0cd891937932c8fb1f129f crypto/rand/rand_lib.c +1e919f7f3c860eb21bf2f6f868dae076c64c53f1ad794c6764f69329724c3fc2 crypto/rand/rand_lib.c 9e162caba63741e3df4d0f1c49a7555263ebc120cfb643546ea7e34d3f5eb862 crypto/rand/rand_local.h dce7413b4c4e588c9a099c6fd7c6c9a397e034f259a2027d4ea8bdfe149164fa crypto/rcu_internal.h 0c1d3e0e857e9e4f84752a8ef0b619d8af0d81427b52facbd0174e685dac9a47 crypto/riscv32cpuid.pl @@ -322,7 +322,7 @@ f0c8792a99132e0b9c027cfa7370f45594a115934cdc9e8f23bdd64abecaf7fd crypto/rsa/rsa b1584c4a1a5f83a1fd43d854ce72bb11735aa34945f2b2f983228f36f27fdad2 crypto/rsa/rsa_backend.c 38a102cd1da1f6ca5a46e6a22f018237964336274385f5c70cbedcaa6997647e crypto/rsa/rsa_chk.c e762c599b17d5c89f4b1c9eb7d0ca1f04a95d815c86a3e72c30b231ce57fb199 crypto/rsa/rsa_crpt.c -e666568eadfd01ff3e435364dee2575fca7ff3e6855b2c258fa1e4d04239d933 crypto/rsa/rsa_gen.c +157eec6c45b95ed974324055f594885c50e33616af3af06efb558d651a786c69 crypto/rsa/rsa_gen.c f22bc4e2c3acab83e67820c906c1caf048ec1f0d4fcb7472c1bec753c75f8e93 crypto/rsa/rsa_lib.c 969a13b951b8a77337fef84437b1aeec49ab1c73ecbceeb4b0df2174ae16a9a2 crypto/rsa/rsa_local.h cf0b75cd54b61b9b9a290ef18d0ddce9fb26a029a54eb3f720d9b25188440f00 crypto/rsa/rsa_mp_names.c @@ -350,13 +350,13 @@ be1e7dd9998e3f31cfa6e1b17bc198aeec584a8b76820e38f71d51b05f8a9f2a crypto/sha/asm 79dec13ccbee4a6758a22d92bfd5694565416219e48b6894dfb63c6b0029ae28 crypto/sha/asm/keccak1600-s390x.pl 3fb93b9440f5c3008b5c876a8106acc5f8d38f1afedd79381f0befec7dd7d72b crypto/sha/asm/keccak1600-x86_64.pl 831b8b02ab25d78ba6300ce960d96c13439bfba5844e13061e19c4e25cbacc3d crypto/sha/asm/keccak1600p8-ppc.pl -75d832db9bf0e98e7a5c522169060a6dd276c5118cfb297fc3f1111f55cd4007 crypto/sha/asm/sha1-586.pl +131d338bc716d9b5d4c1d3e8de213aa621f7581f91ec0ee7e2e56a9a94f1822b crypto/sha/asm/sha1-586.pl c96e87d4f5311cd73bbdf499acc03418588be12426d878e157dd67e0099e0219 crypto/sha/asm/sha1-alpha.pl 695ef6f8041f37f4b39cb7099e9c7c3a29d6f823823df7333530d375f5f5e01b crypto/sha/asm/sha1-armv4-large.pl cb32284af92d99d7046b99dd5bbd894d53531f7b99d351235a939c542680193b crypto/sha/asm/sha1-armv8.pl 11d332b4e058e9fa418d6633316d2e9f9bf520a08b2d933e877bdf38b2edefcf crypto/sha/asm/sha1-c64xplus.pl 32ff0e701a7b8f25bcfe8477b20795de54f536527bd87d3ce694fd9aaae356d4 crypto/sha/asm/sha1-ia64.pl -de6c7e8c1e27779a8cf1ce2a04f487a3d4dc510d5ba240cd06128ecc8574e424 crypto/sha/asm/sha1-mb-x86_64.pl +9fdde42e62c5a5c0457316ac35e6f6f940061634ab1e44a1ef5cdbacb656d738 crypto/sha/asm/sha1-mb-x86_64.pl 0f5c63cf09e950d1b488935ab3b5562e3e9d5cd1a563fb88a41e3dae90a35e6d crypto/sha/asm/sha1-mips.pl b5ffd7b6dbb04c05de7efa2945adb67ea845e7e61a3bf163a532f7b6acdf4267 crypto/sha/asm/sha1-parisc.pl 482cd23ca6ec38d6f62b90c68f9f20643579c50f2c0fbb0dab1c10a0e35efe77 crypto/sha/asm/sha1-ppc.pl @@ -364,11 +364,11 @@ b5ffd7b6dbb04c05de7efa2945adb67ea845e7e61a3bf163a532f7b6acdf4267 crypto/sha/asm 7fd355b412ddfa1c510e0ba3284f75b1c0d621b6db2ecb1d2a935d5cdb706628 crypto/sha/asm/sha1-sparcv9.pl 24554e68b0e7b7db7b635ff149549015f623ca0bcd9ae90439586a2076f6ae80 crypto/sha/asm/sha1-sparcv9a.pl 74d197cdd72400cabbff7e173f72c8976723081508b095dc995e8cd1abf3daa6 crypto/sha/asm/sha1-thumb.pl -dc363497de4fa3bc88b16e834ddf4967aecabdba5ea3ddd6113cf00da7e278bd crypto/sha/asm/sha1-x86_64.pl -c099059ef107f548ea2c2bab64a4eb8c277070ce6d74c4d32bb9808dc19c5fa3 crypto/sha/asm/sha256-586.pl +a579c0ab82151f8879bac23ef1ffb198dfbf9b02d2015c500a232baafc6a3722 crypto/sha/asm/sha1-x86_64.pl +494390ee974a00a0bfdb0ee46116efa45379b5e63988c0a3be9ff6183be2359d crypto/sha/asm/sha256-586.pl 0f01f7b5b0699f1e8ca260439d009febfa5b85b9e7b0933d236467e383aaaa2e crypto/sha/asm/sha256-armv4.pl 93ddc97651ee3e779144a3c6b3e46a1bc4aa81e75cd7b9df068a2aef8743d25f crypto/sha/asm/sha256-c64xplus.pl -9a68b6642b20e3cdccd636c4a934a6e0114160506784583f684ad65aefac2872 crypto/sha/asm/sha256-mb-x86_64.pl +478035fb599566f468f68ae9a3c5311b1e9c6257de6c47a7a32082c8aee41c8d crypto/sha/asm/sha256-mb-x86_64.pl b14670492f24cd0d2fedf8780e981b7da123203395c085334d4571b619b0a610 crypto/sha/asm/sha256-riscv64-zvkb-zvknha_or_zvknhb.pl dd82e1311703abb019975fc7b61fb87d67e1ed916dddd065aced051e851114b9 crypto/sha/asm/sha512-586.pl 16e68ac669860c5bf8e4db81cd3d64fc2c22168e129c2597e94b0f56fafcdfa8 crypto/sha/asm/sha512-armv4.pl @@ -381,7 +381,7 @@ fb06844e7c3b014a58dccc8ec6020c71843cfdc5be08288bc7d204f0a840c474 crypto/sha/asm 07804b96dda856cffaef291641c4ae7f59288ed1e65e38823cfdcb74f8ac5295 crypto/sha/asm/sha512-riscv64-zvkb-zvknhb.pl 38e0455fd6a2b93a7a5385379ca92bc6526585ca1eb4af365fac4c78f7285c72 crypto/sha/asm/sha512-s390x.pl 0611845c52091b0208dd41f22ddef9dd1e68d3d92fa4c4360738b840a6314de6 crypto/sha/asm/sha512-sparcv9.pl -473874a27b031e3d6c3dd0388c7231aa299e07c5832fa7499a081488e6f5680a crypto/sha/asm/sha512-x86_64.pl +14b563ed790d9bd76b0f45e27b75b5fa46d393d7bea8704d2894004adc3f4ac6 crypto/sha/asm/sha512-x86_64.pl 8725cabb8d695c576619f19283b034074a3fa0f1c0be952a9dbe9793be15b907 crypto/sha/asm/sha512p8-ppc.pl 93858e3b530333a129127b8df8cd3326cf55b770238b4fff2474c4e6e3def1dd crypto/sha/keccak1600.c 306cacd3f86e5cacaca74c58ef862516515e5c0cafaff48636d537fd84f1c2fb crypto/sha/sha1dgst.c @@ -391,19 +391,19 @@ a7e074a2f2cea0c33e7875eacc8adb465b5802e4c1d100cda79ac3dd52cdb453 crypto/sha/sha 61ab6d7d7da9e65120ec59cfa9f5ede785502ae371696c3e4e04e039743ca111 crypto/sha/sha_local.h dfd99e02830973ab349409ac6ba0ee901ba7736216030965bd7e5a54356abd7c crypto/slh_dsa/slh_adrs.c c9b270de1259d9fa71a4d352786357bcf1dd3d22075edab84501e2f8e550b271 crypto/slh_dsa/slh_adrs.h -95d42ca839ff34a050a7006734a06c157ad259512c1a10b978e9f899efe69f12 crypto/slh_dsa/slh_dsa.c -ab7b580b1cba302c5675918b457794a3b3d00aac42297312d9447bc6f6a40b09 crypto/slh_dsa/slh_dsa_hash_ctx.c -892a5ed5213c0898882bfc42f72be2864b363cd62d08a3b337c20b4fa557bef0 crypto/slh_dsa/slh_dsa_key.c +26566d0e641456101bd17338dbbb16f59dfacd34f76cff5882133a0ab7323130 crypto/slh_dsa/slh_dsa.c +6b88a8ca514dd2ead7808bf08ea7c7e89125cdcfae8f0db4f3518069382fdfa0 crypto/slh_dsa/slh_dsa_hash_ctx.c +924e686178fdc5984d1a09b02d91e04d4b9c4eb818ee384107ca64357c237e39 crypto/slh_dsa/slh_dsa_key.c 4c7981f7db69025f52495c549fb3b3a76be62b9e13072c3f3b7f1dedeaf8cc91 crypto/slh_dsa/slh_dsa_key.h -5dcb631891eb6afcd27a6b19d2de4d493c71dab159e53620d86d9b96642e97e8 crypto/slh_dsa/slh_dsa_local.h -adb3f4dea52396935b8442df7b36ed99324d3f3e8ce3fdf714d6dfd683e1f9f0 crypto/slh_dsa/slh_fors.c -5d3855cb2927efa4b28fec4357694bf863ac8dc6556009bdfa800ba16cb80b4d crypto/slh_dsa/slh_hash.c +f8007c0f93908810f138f872809cd49013e22192907f4c38d290b6c4566230f5 crypto/slh_dsa/slh_dsa_local.h +6d3f3c0be706c1dd871db863f2344f709a2b7fbb60a0d91298aeb2222f767a87 crypto/slh_dsa/slh_fors.c +f6f5286c6ce9f37cbb527144ec09fd86ae796ac3e71f0bdbb45b5a08a0692122 crypto/slh_dsa/slh_hash.c 3af167addbfd97f831f2a1981133bf4e2b62b95dc9477767797f7e4a653556db crypto/slh_dsa/slh_hash.h -6402664fbb259808a6f7b5a5d6be2b4a3cc8a905399d97b160cdb3e4a97c02c4 crypto/slh_dsa/slh_hypertree.c +1eebf59ebd0859be5a8deddd2f664f99158060904234532af608a44dd6d92d19 crypto/slh_dsa/slh_hypertree.c 1ce9b4f4f90a6f82005c9cdc0ea1f6b6876556c76f8bfd95f4c003a1c195a266 crypto/slh_dsa/slh_params.c 86b16a2c36d708cb880ba49648bb3051c2997188c8ea6aec9292534b97232c7f crypto/slh_dsa/slh_params.h -1aa9dc1c6fe59d024485df9a6b782ac4d0656a31b12faee749fe098911799eaf crypto/slh_dsa/slh_wots.c -59db81a3342c0c89b030756168b9a7f09c938b2cd3498335108e0a32c041b6e7 crypto/slh_dsa/slh_xmss.c +668a2431034f8c604970ed531e32b7b20b6b710e258d1db0a8eb06a13d900f0e crypto/slh_dsa/slh_wots.c +37fff5f88dd8bcd0ad8cdbab130c5a9a018422fe59b141bdb11bcee8fd1b046f crypto/slh_dsa/slh_xmss.c 9ef5a01caccc2eb15f72e367d0424737040ac8018479bbbbce3d216c655765c2 crypto/sparccpuid.S b462d1efe0acd798e1ec5f37fd1c824a587e1773e6a6f984d5a332581573ecbc crypto/sparcv9cap.c 9e16e8641ac5ec2cb2fcc8e4796af5b698d6fa4ce85e374bd8f5b4edb51e6428 crypto/sparse_array.c @@ -417,7 +417,7 @@ f06b08138d73b834471abc4a3ba43b2be838f7196c937c3e933694d6cd69f74d crypto/thread/ 2e5955d706b96c487e4875ffbe208fac15bdca06b33cee916d5343978c14efa1 crypto/threads_lib.c b3743dfd1c13fe70dc57a5a0b2ec540ab3afa748699eb6ef36f56f4d36d06ef3 crypto/threads_none.c 7b97b0f57f6b7cac89c1b8bd03bee34fb39d33cfae1632e75571ba106a5b9442 crypto/threads_pthread.c -9dac146cda57fb53d9b9eb30ff1fc81090f5e62dbe05d4cd97ed11cf501fc78c crypto/threads_win.c +a4692ad34bd148e06344672e08a3ba928719ca5af4d11ba54d97926759dcda0b crypto/threads_win.c 93f8fe09f96492a6be6772ddbf0cc37912fc2a90acb7faea378da1735fe20f6f crypto/time.c 88c5f9f4d2611223d283ebd2ae10ae5ecbb9972d00f747d93fcb74b62641e3f9 crypto/x86_64cpuid.pl 085d9fe93adf232f1ff838be9235046c2c2abe2daeb0e6342921d8f2e955dc18 crypto/x86cpuid.pl @@ -468,7 +468,7 @@ b41a5d9a7bdf60df169e327b41f16489830b82393dd663d1f89f81da4483eaa7 include/intern 9bafa62442fdeda25b97fdbe8e8bf8ea62a5b5167adb2ac7ebbb13db271673f9 include/internal/ffc.h 0a82ff0abab6ab815f9cb523b9643854346b47ff276f8868d1cbe48efc1b20ee include/internal/fips.h 923d4fb14a08f9b251b9bf9727bc50930d0279e8b63243faf85374bdcbbfc4e0 include/internal/hashfunc.h -a37a58d887ae4331a19179900b8d077afa1174c5152d53dc1533c37a65f319d6 include/internal/hashtable.h +d76c942d91e97f8954852ec7ae5a790a591b44762bba31930af585ed5f861fe0 include/internal/hashtable.h f6f30785e3eced1ccdd4b149286ff2b8bbb860eb7e070cbe54c997aa022854da include/internal/namemap.h c367e6120d26a2b629f4db7e179973e33fb095e1102d5c7a69c744b88ebe4469 include/internal/nelem.h eef3ec603b9877bd24a8fa1dbcd7752618fa74943b045515720bb0ca61394ae5 include/internal/numbers.h @@ -568,7 +568,7 @@ a481e8762c694b3dac0e74aac8626fe60fa94962a14914f1f6969ea1214c40b1 include/openss 9e04a3e9ca5352adffbdd75a5ea5237e8ff96a8c0a842368cc3a29de006b2ee7 include/openssl/types.h 62e0cddeedfc217ac02bf37f3669ccea8d0822a88a74a8ec82b844a85b2700aa include/openssl/x509.h.in 869959c3d557d2ace84f38b7a8d0f23b3b0854de7f952f46310e828af04554dd include/openssl/x509_vfy.h.in -5dbee881fe4e1f08a773e8bd34eeda7639be7c474a3d4d6e7c8d779e19c7eb2a include/openssl/x509err.h +53a45ca5d00026ef0a256f7ff27f5708d5af0a44177a0fc4b209ec054d44e18c include/openssl/x509err.h c0a9551efccf43f3dd748d4fd8ec897ddaabbc629c00ec1ad76ce983e1195a13 providers/common/bio_prov.c 6d25e1b61731cc558c2f801350d0cd874d3c19a3b0a03f52394c11fcaf2d51a5 providers/common/capabilities.c f94b7435d4ec888ec30df1c611afa8b9eedbb59e905a2c7cb17cfc8c4b9b85b8 providers/common/der/der_digests_gen.c.in @@ -611,7 +611,7 @@ b10730f4d302344579c09f43d5f9c5538bb6b4acd60de7430c24269fc522d5a5 providers/comm e2f8f00519d81aa16f1c30e8cbf9a0d8e898a1cb5c8b38bb01dd9ab513e34c9e providers/common/securitycheck_fips.c abd5997bc33b681a4ab275978b92aebca0806a4a3f0c2f41dacf11b3b6f4e101 providers/fips/fips_entry.c d8cb05784ae8533a7d9569d4fbaaea4175b63a7c9f4fb0f254215224069dea6b providers/fips/fipsindicator.c -0c473190a4b6809caed57997e44ee9ec949bcf01c542633e2881d07c809d3a51 providers/fips/fipsprov.c +f0f1486219ddb5817b5105c36f384cb9ef095ddceec50966fe178f4b4177028c providers/fips/fipsprov.c 8f52eead96febbce9e7f2bf5aaea557efe8f94ce078044959e80e5ae78432539 providers/fips/include/fips/fipsindicator.h ef204adc49776214dbb299265bc4f2c40b48848cbea4c25b8029f2b46a5c9797 providers/fips/include/fips_indicator_params.inc f2581d7b4e105f2bb6d30908f3c2d9959313be08cec6dbeb49030c125a7676d3 providers/fips/include/fips_selftest_params.inc @@ -639,7 +639,7 @@ be18c20e0197f25fe7b9e0268657a2271a69d216b89cb100f082fa5fcaad1e07 providers/impl 60c4f604cf9b5457be48f31cc24ca21729660381081b2dbf99f362a013a09684 providers/implementations/ciphers/cipher_aes_gcm_hw_vaes_avx512.inc e2886780637db72b12c9bc488d81647ed55a7f5c850efd4bdbf88ef7127e1913 providers/implementations/ciphers/cipher_aes_hw.c 89de794c090192459d99d95bc4a422e7782e62192cd0fdb3bdef4128cfedee68 providers/implementations/ciphers/cipher_aes_hw_aesni.inc -eac58fff6aa9918d657228c2707f1b3f0ef8f1210c97575f3c264db78bfd996f providers/implementations/ciphers/cipher_aes_ocb.c +b88e88831695dfc165ce83e64802ffb8240f1f696d9c67f350b9ff1b2e913212 providers/implementations/ciphers/cipher_aes_ocb.c 88138a1aff9705e608c0557653be92eb4de65b152555a2b79ec8b2a8fae73e8f providers/implementations/ciphers/cipher_aes_ocb.h 6c3a89771719b36d6917d23464be5441836378393731af96ba165fd788df1a41 providers/implementations/ciphers/cipher_aes_ocb_hw.c c7aac28a9dca1ad46e5bce4de93e07dffec1f89fab82394c3ff7cf1bda8b483f providers/implementations/ciphers/cipher_aes_wrp.c @@ -655,7 +655,7 @@ dc4626becaabc3990549483d9ef5f05c7dd9a9c2cf9be96ade3ba6a6e203f7f5 providers/impl cca34f1c7baf3a98964f7ce19a59e06d1eaf2ada121a0d4a438f4078a072b325 providers/implementations/ciphers/cipher_tdes_hw.c d2f418806c7ed45f118683bc13329573804592684e522efced0fd0921f4548fd providers/implementations/ciphers/ciphercommon.c ab9a2edb23aa61cf31da6addd8674a6028f93399eceeeee35a56ee770338fd6c providers/implementations/ciphers/ciphercommon_block.c -6b6090c233ddf29d819f2559361aeeae03505de7626a127628d5f0f6d3bce295 providers/implementations/ciphers/ciphercommon_ccm.c +fafb07c3fd77a89cff1d2efbb6edc0767132fc30c57f9e282080da04e6762499 providers/implementations/ciphers/ciphercommon_ccm.c 6632a555d5bcd5af67d0355ce46c2906bb3a0dcdf1651595b29189c40a5ca675 providers/implementations/ciphers/ciphercommon_ccm_hw.c ab51261da6aea5a3cca74a7561e4b89e6ce83f2ac497a5c766ecd3c3bff95152 providers/implementations/ciphers/ciphercommon_gcm.c bb67eaa7a98494ca938726f9218213870fc97dd87b56bda950626cc794baf20b providers/implementations/ciphers/ciphercommon_gcm_hw.c @@ -692,39 +692,39 @@ abe2b0f3711eaa34846e155cffc9242e4051c45de896f747afd5ac9d87f637dc providers/impl a9a5a3ba575b1a372f5a09135667ac1b0e303f8b19b0707804390aba9e266eca providers/implementations/kdfs/sskdf.c f01cbd7c5351d4aa9ae667627503b2cfef6fc0695e7a42296b7bf015c9a418b3 providers/implementations/kdfs/tls1_prf.c 39207243a84beb670cb0e64b6d0fe7bfc6a3dd84000617b647a3ecf52a1da3c2 providers/implementations/kdfs/x942kdf.c -748af266d06006da10524f3a621c65b8c3eeddf8b1ccd06ecdc6b689564d220c providers/implementations/kem/ml_kem_kem.c -35549cec7031452bb5b46aa8a86028abc7a3a2b39f9f6564fa4bd402451bc647 providers/implementations/kem/mlx_kem.c -e89b894af920504160abfc11860b89b505d116d978162a02213f72500180903b providers/implementations/kem/rsa_kem.c -aa13d72bc69a374db72b6d44e2f2c2ddd5f7bddbe16b950e3c4666d876c63735 providers/implementations/keymgmt/dh_kmgmt.c +b1431361b8a3448b73f4a46c48b3a4f9fd378c2abba67563f4407b1c7f007fca providers/implementations/kem/ml_kem_kem.c +926e08e60171cc867220e0f106533ed155132a034690bddea1e7793a879ebf73 providers/implementations/kem/mlx_kem.c +ff22e920552b82db3dab51b09f9dd2fd038ef0d57fb76cea5578e703653d28c9 providers/implementations/kem/rsa_kem.c +6599ad60eef3554741e049c3ff1bd9cc6064d4f3d1835e1ea5dec3a0c14c80bb providers/implementations/keymgmt/dh_kmgmt.c c0446d1b2101ddd977063516b87d23f424cdca33473f293db4c3974b674169b0 providers/implementations/keymgmt/dsa_kmgmt.c -2b98ba2124a86eae2adc7b88bfa26e47b548e9628b99180cc2cd841eed5ed8da providers/implementations/keymgmt/ec_kmgmt.c +45480796e6ea50cbe9529c17f9fa04228a9126dc7e7e32971519eeb6d6ac267c providers/implementations/keymgmt/ec_kmgmt.c 258ae17bb2dd87ed1511a8eb3fe99eed9b77f5c2f757215ff6b3d0e8791fc251 providers/implementations/keymgmt/ec_kmgmt_imexport.inc -167cd7df056bf46f3481cf6101fb6cfca55dea592f896c2b29649df1939885c4 providers/implementations/keymgmt/ecx_kmgmt.c +c559f1f265388e7b1c8195188fcc71ac8af09b3398530ec8ed7a9afd7b41281e providers/implementations/keymgmt/ecx_kmgmt.c daf35a7ab961ef70aefca981d80407935904c5da39dca6692432d6e6bc98759d providers/implementations/keymgmt/kdf_legacy_kmgmt.c 69b509e9c7fe9692622d1059917c3adb991c0047e11bc116f0a393a3a0539445 providers/implementations/keymgmt/mac_legacy_kmgmt.c -3c63e65bd1a6a2e853828205c015a50c38a82f2fee9bf6787dce6dab7331bb91 providers/implementations/keymgmt/ml_dsa_kmgmt.c -5c95eb8192483b2d81435e52aef6b2c96180bb22a67f717c29661a13b5861b02 providers/implementations/keymgmt/ml_kem_kmgmt.c -f37c8b7bb59d4b199889044992cb1b18ad39f2eafc87029f5348c55a95195e8c providers/implementations/keymgmt/mlx_kmgmt.c +7d197679dc4ae59f0e697749c56cb76399fc5eed88e94585dfd5ebdb23466e53 providers/implementations/keymgmt/ml_dsa_kmgmt.c +2df9ca1a68a9b6e1d1b108148b54ccf5454da3afa34e510beb2f4516e473e4c6 providers/implementations/keymgmt/ml_kem_kmgmt.c +4cec24edda3df01c08bef98a0a177ccdd1f8ba84e37c399dc568e010d7c0b29f providers/implementations/keymgmt/mlx_kmgmt.c cd4b8129eaccbd77f9b6c725d3cb57b71109c4649115ec786b6495100afaddf2 providers/implementations/keymgmt/rsa_kmgmt.c -d640cff1c46911b69866eb83f48beba42a1741bb1d3f1db6e7201077a57761fc providers/implementations/keymgmt/slh_dsa_kmgmt.c -9d02d481b9c7c0c9e0932267d1a3e1fef00830aaa03093f000b88aa042972b9f providers/implementations/macs/cmac_prov.c +92621573e975489b821884151d2de751e462fcf91efa83cb3bf8f4fd40cd241b providers/implementations/keymgmt/slh_dsa_kmgmt.c +2a66bc54579cb1fcd72674a1e60a7a1f798c13ab964a45e5603bed699268354f providers/implementations/macs/cmac_prov.c a3bb4d7914f45cf82f86cd92135e20a712274ca153d9ed5ad24db7f33710726c providers/implementations/macs/gmac_prov.c 2d6b8c42c67e3e43d8d0035463cbff590dabb7da815f9e437a3a72d4b6596319 providers/implementations/macs/hmac_prov.c 40686337be4261685f176bb10042d903d46ab10c90e10ac42d3842e9b5ddd960 providers/implementations/macs/kmac_prov.c 0ebc5a48655a697231918644397308e64914c32421e9b8ee7afd7779b6a2fdb8 providers/implementations/rands/drbg.c -d9e41abc1780bb253bdca6c58cc32af7d0a774e52c91fc5d64577f71defc52c2 providers/implementations/rands/drbg_ctr.c -cf98646defb0b385d6ce4bedcd51559c9a03424491f4576ea7eb41e3db8a18b3 providers/implementations/rands/drbg_hash.c -57561d4bd3a79e6a250310a989958409437dfa68b2818d5f0dbb8a5e7ef04bb7 providers/implementations/rands/drbg_hmac.c +d2805527aa28c27dc0d10f3e35b64e18626691b3c864806dd644b7dd1640ec49 providers/implementations/rands/drbg_ctr.c +e624059b1c9f878655d6a21a4c295c43d147ea913f638a2d007a1a68379180f8 providers/implementations/rands/drbg_hash.c +3aa1dd31f0db1ab0a7a5a3037f722e284587c244126810268622fae65bef77d7 providers/implementations/rands/drbg_hmac.c 841617c81d6d5eae5ea59064e8b45947d436d3e53b49283329d17016866d8f34 providers/implementations/rands/drbg_local.h 355bd437dde9ecd1da89f42691147f2b5cf9a012ff5f55062bf83b6bead1e181 providers/implementations/rands/fips_crng_test.c -4913fec58a2648fcec0e5a94dba9decab0505a6d725bed6eb861ce854db81df8 providers/implementations/rands/test_rng.c +90ea602ec88f7c0a78f3e7c801cdd3574a221f04497121a9ea7dcb05b7ee6765 providers/implementations/rands/test_rng.c c6c709dfd8b1be036e2a5232d3b21dc25f0150f2aae24cc7db6b09cd790a04ee providers/implementations/signature/dsa_sig.c d10d611713a6d9aa5cdbe636f1ba90404043431fd1df01fc1a1ce8499bf96ad0 providers/implementations/signature/ecdsa_sig.c a837f69cb1aa5d0327372e26a63a8492b6ffb1156325f66e880c202011d07cbe providers/implementations/signature/eddsa_sig.c e0e67e402ff19b0d2eb5228d7ebd70b9477c12595ac34d6f201373d7c8a516f4 providers/implementations/signature/mac_legacy_sig.c 51251a1ca4c0b6faea059de5d5268167fe47565163317177d09db39978134f78 providers/implementations/signature/ml_dsa_sig.c -94725f9e466c60c710900ca9878196f359e8421f46d5fb62fda91f5f845caff3 providers/implementations/signature/rsa_sig.c -539d3f55b8fd28826c786cb4e5c0e735173dc0faf268527ea007052be623cd37 providers/implementations/signature/slh_dsa_sig.c +6b293ca81102cd2f234d60f52f839e5bd7a746a42df3fe8a4489e6c214108f50 providers/implementations/signature/rsa_sig.c +ec630d49078bdd901132e7651eaf3478ff3b04e5558c435ffd7c77dcb62e46b3 providers/implementations/signature/slh_dsa_sig.c 21f537f9083f0341d9d1b0ace090a8d8f0b2b9e9cf76771c359b6ea00667a469 providers/implementations/skeymgmt/aes_skmgmt.c 2dbf9b8e738fad556c3248fb554ff4cc269ade3c86fa3d2786ba9b6d6016bf22 providers/implementations/skeymgmt/generic.c 9ba8db9b0e18847ef79ecb77fbc383d8762694be29dfb7d269df6f02dc977222 providers/implementations/skeymgmt/skeymgmt_lcl.h diff --git a/providers/fips.checksum b/providers/fips.checksum index 7d8252550bd4c..f236b8ff81a48 100644 --- a/providers/fips.checksum +++ b/providers/fips.checksum @@ -1 +1 @@ -f24213807982cf5d2859d5d1b78caa54c249ec28725645d1af28f092d543962d providers/fips-sources.checksums +ee77588030ee4df89ad9ff70a12118a9b89ebc4fde306fd25e9c01ef719d0b26 providers/fips-sources.checksums From f4dc4d58b48d346a8270183f89acf826d459b0ca Mon Sep 17 00:00:00 2001 From: openssl-machine Date: Tue, 25 Aug 2026 11:56:39 +0000 Subject: [PATCH 176/189] Prepare for release of 3.5.8 Reviewed-by: Neil Horman Reviewed-by: Milan Broz MergeDate: Tue Aug 25 11:56:40 2026 Release: yes --- CHANGES.md | 2 +- NEWS.md | 2 +- VERSION.dat | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a02d74d447cf1..b440f013313f6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,7 +28,7 @@ OpenSSL Releases OpenSSL 3.5 ----------- -### Changes between 3.5.7 and 3.5.8 [xx XXX xxxx] +### Changes between 3.5.7 and 3.5.8 [25 Aug 2026] * Fixed QUIC server being able to trigger double free when processing `INITIAL` packet. diff --git a/NEWS.md b/NEWS.md index bf9631179595b..329b1772c3483 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,7 +23,7 @@ OpenSSL Releases OpenSSL 3.5 ----------- -### Major changes between OpenSSL 3.5.7 and OpenSSL 3.5.8 [under development] +### Major changes between OpenSSL 3.5.7 and OpenSSL 3.5.8 [25 Aug 2026] OpenSSL 3.5.8 is a security patch release. The most severe CVE fixed in this release is Moderate. diff --git a/VERSION.dat b/VERSION.dat index c675e8bc3b8e4..bf654c1a77130 100644 --- a/VERSION.dat +++ b/VERSION.dat @@ -1,7 +1,7 @@ MAJOR=3 MINOR=5 PATCH=8 -PRE_RELEASE_TAG=dev +PRE_RELEASE_TAG= BUILD_METADATA= -RELEASE_DATE="" +RELEASE_DATE="25 Aug 2026" SHLIB_VERSION=3 From ee6976702de0e34bffd01ddc2ba67d4a07a71318 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Fri, 6 Sep 2024 17:46:57 +0000 Subject: [PATCH 177/189] Remove submodules (cherry picked from commit ae2e0753685696f30915675d7f76a91bee56c339) --- .gitmodules | 37 ------------------------------------- cloudflare-quiche | 1 - fuzz/corpora | 1 - gost-engine | 1 - krb5 | 1 - oqs-provider | 1 - pyca-cryptography | 1 - python-ecdsa | 1 - tlsfuzzer | 1 - tlslite-ng | 1 - wycheproof | 1 - 11 files changed, 47 deletions(-) delete mode 160000 cloudflare-quiche delete mode 160000 fuzz/corpora delete mode 160000 gost-engine delete mode 160000 krb5 delete mode 160000 oqs-provider delete mode 160000 pyca-cryptography delete mode 160000 python-ecdsa delete mode 160000 tlsfuzzer delete mode 160000 tlslite-ng delete mode 160000 wycheproof diff --git a/.gitmodules b/.gitmodules index b4c756a67b179..e69de29bb2d1d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,37 +0,0 @@ -[submodule "pyca.cryptography"] - path = pyca-cryptography - url = https://github.com/pyca/cryptography.git - -[submodule "krb5"] - path = krb5 - url = https://github.com/krb5/krb5 - -[submodule "gost-engine"] - path = gost-engine - url = https://github.com/gost-engine/engine - update = rebase -[submodule "wycheproof"] - path = wycheproof - url = https://github.com/google/wycheproof -[submodule "tlsfuzzer"] - path = tlsfuzzer - url = https://github.com/tlsfuzzer/tlsfuzzer -[submodule "python-ecdsa"] - path = python-ecdsa - url = https://github.com/tlsfuzzer/python-ecdsa -[submodule "tlslite-ng"] - path = tlslite-ng - url = https://github.com/tlsfuzzer/tlslite-ng -[submodule "oqs-provider"] - path = oqs-provider - url = https://github.com/open-quantum-safe/oqs-provider.git -[submodule "cloudflare-quiche"] - path = cloudflare-quiche - url = https://github.com/cloudflare/quiche -[submodule "fuzz/corpora"] - path = fuzz/corpora - url = https://github.com/openssl/fuzz-corpora - branch = main -[submodule "pkcs11-provider"] - path = pkcs11-provider - url = https://github.com/latchset/pkcs11-provider.git diff --git a/cloudflare-quiche b/cloudflare-quiche deleted file mode 160000 index 7ab6a55cfe471..0000000000000 --- a/cloudflare-quiche +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7ab6a55cfe471267d61e4d28ba43d41defcd87e0 diff --git a/fuzz/corpora b/fuzz/corpora deleted file mode 160000 index ce771805c094d..0000000000000 --- a/fuzz/corpora +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ce771805c094d098c25a218bc8e9f7344eccbc5a diff --git a/gost-engine b/gost-engine deleted file mode 160000 index 74b1f4fddbc2d..0000000000000 --- a/gost-engine +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 74b1f4fddbc2d6de969815b1992ddc1ae7c643fe diff --git a/krb5 b/krb5 deleted file mode 160000 index 784c38f50e70a..0000000000000 --- a/krb5 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 784c38f50e70a739400cdd3f2620bac2e2788e6c diff --git a/oqs-provider b/oqs-provider deleted file mode 160000 index 7bc597c04b534..0000000000000 --- a/oqs-provider +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7bc597c04b534ddea9b6654481deb31ded8e1bbc diff --git a/pyca-cryptography b/pyca-cryptography deleted file mode 160000 index 7e33b0e7739d6..0000000000000 --- a/pyca-cryptography +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7e33b0e7739d633c77b8c478620167f693ed13f4 diff --git a/python-ecdsa b/python-ecdsa deleted file mode 160000 index 4096fa0171592..0000000000000 --- a/python-ecdsa +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4096fa01715929e08b97e73f3173aee9d57f2a3f diff --git a/tlsfuzzer b/tlsfuzzer deleted file mode 160000 index 61f45d9701294..0000000000000 --- a/tlsfuzzer +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 61f45d9701294fd87ef92d2a7e3dfb076653a562 diff --git a/tlslite-ng b/tlslite-ng deleted file mode 160000 index 77ef321dde1a9..0000000000000 --- a/tlslite-ng +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 77ef321dde1a9e6bcf94d73c80f8789a770d8031 diff --git a/wycheproof b/wycheproof deleted file mode 160000 index 2196000605e45..0000000000000 --- a/wycheproof +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2196000605e45d91097147c9c71f26b72af58003 From 93c999bb97bb2f1c057d85f3d7a07e7fbef89e93 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Fri, 26 Jan 2024 16:34:22 +0000 Subject: [PATCH 178/189] Msan fixes (cherry picked from commit 35f2869954dd2671ee2f02c808ec0ee34d74eee3) --- crypto/bn/bn_intern.c | 10 ++++++++++ crypto/cpuid.c | 9 +++++++++ providers/implementations/rands/drbg_ctr.c | 12 ++++++++++++ 3 files changed, 31 insertions(+) diff --git a/crypto/bn/bn_intern.c b/crypto/bn/bn_intern.c index bd299cd1442d7..6fa404afce2cd 100644 --- a/crypto/bn/bn_intern.c +++ b/crypto/bn/bn_intern.c @@ -10,6 +10,11 @@ #include "internal/cryptlib.h" #include "bn_local.h" +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# endif +#endif /* * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. * This is an array r[] of values that are either zero or odd with an @@ -188,6 +193,11 @@ int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words) return 0; } +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(words, sizeof(BN_ULONG) * num_words); +# endif +#endif memcpy(a->d, words, sizeof(BN_ULONG) * num_words); a->top = num_words; bn_correct_top(a); diff --git a/crypto/cpuid.c b/crypto/cpuid.c index d659135919d1f..18c648148a30c 100644 --- a/crypto/cpuid.c +++ b/crypto/cpuid.c @@ -102,7 +102,16 @@ void OPENSSL_cpuid_setup(void) if (trigger) return; + /// This function is called from .init section before memory sanitizer mmaps shadow memory. + /// Program will crash with segmentation fault when trying access `trigger`, + /// because its address was replaced with some not mapped address. + /// Also see https://github.com/ClickHouse/openssl/pull/5 + /// Unfortunately, __msan_init() is no longer part of msan's public header and there seems to be no replacement. +#if defined(__has_feature) +# if !__has_feature(memory_sanitizer) trigger = 1; +# endif +#endif if ((env = ossl_getenv("OPENSSL_ia32cap")) != NULL) { int off = (env[0] == '~') ? 1 : 0; diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c index 57da1cfdf33df..fa4a7400ffbd2 100644 --- a/providers/implementations/rands/drbg_ctr.c +++ b/providers/implementations/rands/drbg_ctr.c @@ -25,6 +25,12 @@ #include "internal/provider.h" #include "internal/common.h" +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# endif +#endif + static OSSL_FUNC_rand_newctx_fn drbg_ctr_new_wrapper; static OSSL_FUNC_rand_freectx_fn drbg_ctr_free; static OSSL_FUNC_rand_instantiate_fn drbg_ctr_instantiate_wrapper; @@ -72,6 +78,12 @@ static void inc_128(PROV_DRBG_CTR *ctr) p[n] = (u8)c; c >>= 8; } while (n); + +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(p, 16); +# endif +#endif } static void ctr_XOR(PROV_DRBG_CTR *ctr, const unsigned char *in, size_t inlen) From 1e6fca4789dd0183f9112e63b8779e9d9461fd8b Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Thu, 25 Jan 2024 11:03:50 +0000 Subject: [PATCH 179/189] Remove dependency on "getrandom" function (cherry picked from commit a6387b8f1883fc074cd92c83a20fa5930accaba6) --- providers/implementations/rands/seeding/rand_unix.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 0b8a9ec341d92..ed82495e693fc 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -351,8 +351,13 @@ static ssize_t syscall_random(void *buf, size_t buflen) * Note: Sometimes getentropy() can be provided but not implemented * internally. So we need to check errno for ENOSYS */ -#if !defined(__DragonFly__) && !defined(__NetBSD__) && !defined(__FreeBSD__) -#if defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__) && !defined(__hpux) +# if !defined(__DragonFly__) && !defined(__NetBSD__) && !defined(__FreeBSD__) + + /// Disable the usage of "getentropy" function from libc (on static link time) to avoid dependency on too new libc version. + /// Otherwise, if we build ClickHouse on a system with new libc and run the built binary on a system with old libc, it will fail. + /// + /// Note that there is a fallback below to (1) runtime symbol lookup and (2) direct syscall, that are equivalent. +# if 0 && defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) extern int getentropy(void *buffer, size_t length) __attribute__((weak)); if (getentropy != NULL) { From 55227af3b0a69383e1e68312e8538b4d5a4bb281 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Mon, 11 Mar 2024 14:03:58 +0000 Subject: [PATCH 180/189] Remove dependency on glibc 2.14 sendmmsg/recvmmsg (cherry picked from commit a5c57bbdeca0042282b6427ee72c2abcbba4ec23) --- crypto/bio/bss_dgram.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 968104a062086..8d802bb020a45 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -49,7 +49,9 @@ #define M_METHOD_WSARECVMSG 4 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) -#if !(__GLIBC_PREREQ(2, 14)) +/// ClickHouse-specific patch: Pretend to use a stone age glibc because we use a stone age glibc. +/// Otherwise, system calls sendmmsg and recvmmsg are used which work only with too-new glibc 2.14. +/// #if !(__GLIBC_PREREQ(2, 14)) #undef NO_RECVMMSG /* * Some old glibc versions may have recvmmsg and MSG_WAITFORONE flag, but @@ -57,7 +59,7 @@ * versions */ #define NO_RECVMMSG -#endif +/// #endif #endif #if defined(__GNU__) /* GNU/Hurd does not have IP_PKTINFO yet */ From 1c5cd7aac614552cfd5294cac46520c1be742c95 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Wed, 20 Mar 2024 12:22:40 +0000 Subject: [PATCH 181/189] Suppress tsan failures: use locks instead of atomics ----- E Exception: Sanitizer assert found for instance ================== E WARNING: ThreadSanitizer: data race (pid=1) E Write of size 8 at 0x7b2800025d30 by thread T2 (mutexes: write M0, write M1): E #0 free (clickhouse+0x709a3e5) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #1 CRYPTO_free build_docker/./contrib/openssl/crypto/mem.c:282:5 (clickhouse+0x2015f8ea) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #2 EVP_PKEY_free build_docker/./contrib/openssl/crypto/evp/p_lib.c:1809:5 (clickhouse+0x2012a751) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #3 Poco::Crypto::EVPPKey::~EVPPKey() build_docker/./base/poco/Crypto/src/EVPPKey.cpp:121:17 (clickhouse+0x1d00ffa9) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #4 DB::CertificateReloader::Data::~Data() build_docker/./src/Server/CertificateReloader.h:71:12 (clickhouse+0x194fb42d) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #5 std::__1::default_delete::operator()[abi:v15000](DB::CertificateReloader::Data const*) const build_docker/./contrib/llvm-project/libcxx/include/__memory/unique_ptr.h:48:5 (clickhouse+0x194fb42d) E #6 std::__1::__shared_ptr_pointer, std::__1::allocator>::__on_zero_shared() build_docker/./contrib/llvm-project/libcxx/include/__memory/shared_ptr.h:263:5 (clickhouse+0x194fb42d) E #7 std::__1::__shared_count::__release_shared[abi:v15000]() build_docker/./contrib/llvm-project/libcxx/include/__memory/shared_ptr.h:174:9 (clickhouse+0x194fade0) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #8 std::__1::__shared_weak_count::__release_shared[abi:v15000]() build_docker/./contrib/llvm-project/libcxx/include/__memory/shared_ptr.h:215:27 (clickhouse+0x194fade0) E #9 std::__1::shared_ptr::~shared_ptr[abi:v15000]() build_docker/./contrib/llvm-project/libcxx/include/__memory/shared_ptr.h:702:23 (clickhouse+0x194fade0) E #10 std::__1::shared_ptr::operator=[abi:v15000](std::__1::shared_ptr&&) build_docker/./contrib/llvm-project/libcxx/include/__memory/shared_ptr.h:723:9 (clickhouse+0x194fade0) E #11 MultiVersion::set(std::__1::unique_ptr>&&) build_docker/./src/Common/MultiVersion.h:76:25 (clickhouse+0x194fade0) E #12 DB::CertificateReloader::tryLoad(Poco::Util::AbstractConfiguration const&) build_docker/./src/Server/CertificateReloader.cpp:83:18 (clickhouse+0x194f94ca) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #13 DB::Server::main(std::__1::vector, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6::operator()(Poco::AutoPtr, bool) const build_docker/./programs/server/Server.cpp:1546:45 (clickhouse+0xf384df7) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #14 decltype(std::declval, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6&>()(std::declval>(), std::declval())) std::__1::__invoke[abi:v15000], std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6&, Poco::AutoPtr, bool>(DB::Server::main(std::__1::vector, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6&, Poco::AutoPtr&&, bool&&) build_docker/./contrib/llvm-project/libcxx/include/__functional/invoke.h:394:23 (clickhouse+0xf3827a9) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #15 void std::__1::__invoke_void_return_wrapper::__call, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6&, Poco::AutoPtr, bool>(DB::Server::main(std::__1::vector, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6&, Poco::AutoPtr&&, bool&&) build_docker/./contrib/llvm-project/libcxx/include/__functional/invoke.h:479:9 (clickhouse+0xf3827a9) E #16 std::__1::__function::__default_alloc_func, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6, void (Poco::AutoPtr, bool)>::operator()[abi:v15000](Poco::AutoPtr&&, bool&&) build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:235:12 (clickhouse+0xf3827a9) E #17 void std::__1::__function::__policy_invoker, bool)>::__call_impl, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_6, void (Poco::AutoPtr, bool)>>(std::__1::__function::__policy_storage const*, Poco::AutoPtr&&, bool) build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:716:16 (clickhouse+0xf3827a9) E #18 std::__1::__function::__policy_func, bool)>::operator()[abi:v15000](Poco::AutoPtr&&, bool&&) const build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:848:16 (clickhouse+0x19fd2cbe) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #19 std::__1::function, bool)>::operator()(Poco::AutoPtr, bool) const build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:1187:12 (clickhouse+0x19fd2cbe) E #20 DB::ConfigReloader::reloadIfNewer(bool, bool, bool, bool) build_docker/./src/Common/Config/ConfigReloader.cpp:150:13 (clickhouse+0x19fd2cbe) E #21 DB::ConfigReloader::reload() build_docker/./src/Common/Config/ConfigReloader.h:51:21 (clickhouse+0xf38767c) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #22 DB::Server::main(std::__1::vector, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13::operator()() const build_docker/./programs/server/Server.cpp:1731:31 (clickhouse+0xf38767c) E #23 decltype(std::declval, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13&>()()) std::__1::__invoke[abi:v15000], std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13&>(DB::Server::main(std::__1::vector, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13&) build_docker/./contrib/llvm-project/libcxx/include/__functional/invoke.h:394:23 (clickhouse+0xf38767c) E #24 void std::__1::__invoke_void_return_wrapper::__call, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13&>(DB::Server::main(std::__1::vector, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13&) build_docker/./contrib/llvm-project/libcxx/include/__functional/invoke.h:479:9 (clickhouse+0xf38767c) E #25 std::__1::__function::__default_alloc_func, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13, void ()>::operator()[abi:v15000]() build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:235:12 (clickhouse+0xf38767c) E #26 void std::__1::__function::__policy_invoker::__call_impl, std::__1::allocator>, std::__1::allocator, std::__1::allocator>>> const&)::$_13, void ()>>(std::__1::__function::__policy_storage const*) build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:716:16 (clickhouse+0xf38767c) E #27 std::__1::__function::__policy_func::operator()[abi:v15000]() const build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:848:16 (clickhouse+0x16907aa0) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #28 std::__1::function::operator()() const build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:1187:12 (clickhouse+0x16907aa0) E #29 DB::Context::reloadConfig() const build_docker/./src/Interpreters/Context.cpp:4357:5 (clickhouse+0x16907aa0) E #30 DB::InterpreterSystemQuery::execute() build_docker/./src/Interpreters/InterpreterSystemQuery.cpp:577:29 (clickhouse+0x17e78c19) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #31 DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr, DB::QueryFlags, DB::QueryProcessingStage::Enum, DB::ReadBuffer*) build_docker/./src/Interpreters/executeQuery.cpp:1195:40 (clickhouse+0x17e3e462) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #32 DB::executeQuery(std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr, DB::QueryFlags, DB::QueryProcessingStage::Enum) build_docker/./src/Interpreters/executeQuery.cpp:1374:26 (clickhouse+0x17e39837) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #33 DB::TCPHandler::runImpl() build_docker/./src/Server/TCPHandler.cpp:518:54 (clickhouse+0x195cc651) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #34 DB::TCPHandler::run() build_docker/./src/Server/TCPHandler.cpp:2329:9 (clickhouse+0x195e8707) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #35 Poco::Net::TCPServerConnection::start() build_docker/./base/poco/Net/src/TCPServerConnection.cpp:43:3 (clickhouse+0x1d00d942) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #36 Poco::Net::TCPServerDispatcher::run() build_docker/./base/poco/Net/src/TCPServerDispatcher.cpp:115:20 (clickhouse+0x1d00e1b1) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #37 Poco::PooledThread::run() build_docker/./base/poco/Foundation/src/ThreadPool.cpp:188:14 (clickhouse+0x1d20f2e6) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #38 Poco::(anonymous namespace)::RunnableHolder::run() build_docker/./base/poco/Foundation/src/Thread.cpp:45:11 (clickhouse+0x1d20d5af) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #39 Poco::ThreadImpl::runnableEntry(void*) build_docker/./base/poco/Foundation/src/Thread_POSIX.cpp:335:27 (clickhouse+0x1d20ba69) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E E Previous atomic write of size 4 at 0x7b2800025d30 by thread T3 (mutexes: write M2): E #0 CRYPTO_DOWN_REF build_docker/./contrib/openssl/include/internal/refcount.h:51:12 (clickhouse+0x2012a6e6) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #1 EVP_PKEY_free build_docker/./contrib/openssl/crypto/evp/p_lib.c:1795:5 (clickhouse+0x2012a6e6) E #2 ssl_cert_clear_certs build_docker/./contrib/openssl/ssl/ssl_cert.c:246:9 (clickhouse+0x1ffafd37) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #3 ssl_cert_free build_docker/./contrib/openssl/ssl/ssl_cert.c:277:5 (clickhouse+0x1ffafd37) E #4 ossl_ssl_connection_free build_docker/./contrib/openssl/ssl/ssl_lib.c:1458:5 (clickhouse+0x1ffba6af) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #5 SSL_free build_docker/./contrib/openssl/ssl/ssl_lib.c:1417:9 (clickhouse+0x1ffb920e) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #6 Poco::Net::SecureSocketImpl::reset() build_docker/./base/poco/NetSSL_OpenSSL/src/SecureSocketImpl.cpp:583:3 (clickhouse+0x1cfaac60) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #7 Poco::Net::SecureSocketImpl::~SecureSocketImpl() build_docker/./base/poco/NetSSL_OpenSSL/src/SecureSocketImpl.cpp:80:3 (clickhouse+0x1cfaac60) E #8 Poco::Net::SecureStreamSocketImpl::~SecureStreamSocketImpl() build_docker/./base/poco/NetSSL_OpenSSL/src/SecureStreamSocketImpl.cpp:52:1 (clickhouse+0x1cfb15dd) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #9 Poco::Net::SecureStreamSocketImpl::~SecureStreamSocketImpl() build_docker/./base/poco/NetSSL_OpenSSL/src/SecureStreamSocketImpl.cpp:43:1 (clickhouse+0x1cfb15dd) E #10 Poco::RefCountedObject::release() const build_docker/./base/poco/Foundation/include/Poco/RefCountedObject.h:86:13 (clickhouse+0x1cffc81e) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #11 Poco::Net::Socket::~Socket() build_docker/./base/poco/Net/src/Socket.cpp:68:10 (clickhouse+0x1cffc81e) E #12 Poco::Net::StreamSocket::~StreamSocket() build_docker/./base/poco/Net/src/StreamSocket.cpp:63:1 (clickhouse+0x1d009c39) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #13 Poco::Net::TCPConnectionNotification::~TCPConnectionNotification() build_docker/./base/poco/Net/src/TCPServerDispatcher.cpp:43:2 (clickhouse+0x1d00ef50) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #14 Poco::Net::TCPConnectionNotification::~TCPConnectionNotification() build_docker/./base/poco/Net/src/TCPServerDispatcher.cpp:42:2 (clickhouse+0x1d00ef50) E #15 Poco::RefCountedObject::release() const build_docker/./base/poco/Foundation/include/Poco/RefCountedObject.h:86:13 (clickhouse+0x1d00e203) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #16 Poco::AutoPtr::~AutoPtr() build_docker/./base/poco/Foundation/include/Poco/AutoPtr.h:91:19 (clickhouse+0x1d00e203) E #17 Poco::Net::TCPServerDispatcher::run() build_docker/./base/poco/Net/src/TCPServerDispatcher.cpp:122:3 (clickhouse+0x1d00e203) E #18 Poco::PooledThread::run() build_docker/./base/poco/Foundation/src/ThreadPool.cpp:188:14 (clickhouse+0x1d20f2e6) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #19 Poco::(anonymous namespace)::RunnableHolder::run() build_docker/./base/poco/Foundation/src/Thread.cpp:45:11 (clickhouse+0x1d20d5af) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) E #20 Poco::ThreadImpl::runnableEntry(void*) build_docker/./base/poco/Foundation/src/Thread_POSIX.cpp:335:27 (clickhouse+0x1d20ba69) (BuildId: 706d92b17db171493f293d517643f726ee1b7b1e) (cherry picked from commit 5b50434b7180034ff7b427cf76838098673e9232) --- include/internal/refcount.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/internal/refcount.h b/include/internal/refcount.h index 61eb78ae41205..5c11c80fc15fa 100644 --- a/include/internal/refcount.h +++ b/include/internal/refcount.h @@ -21,8 +21,9 @@ #define HAVE_C11_ATOMICS #endif -#if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \ - && ATOMIC_INT_LOCK_FREE > 0 +# if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \ + && ATOMIC_INT_LOCK_FREE > 0 \ + && 0 /// ClickHouse-specific patch: if we use atomics, tsan complains :( #define HAVE_ATOMICS 1 @@ -74,7 +75,8 @@ static inline int CRYPTO_GET_REF(CRYPTO_REF_COUNT *refcnt, int *ret) return 1; } -#elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0 +# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0 \ + && 0 /// ClickHouse-specific patch: if we use atomics, tsan complains :( #define HAVE_ATOMICS 1 From c78e1b44da4ae04c1a6152a51350ed97cb443089 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Tue, 11 Jun 2024 19:25:32 +0000 Subject: [PATCH 182/189] Suppress leaky memory warning During my testing (*), I got below stack about leaked memory. - at database startup, Azure is registered as an object storage (--> registerAzureObjectStorage) - this calls into Azure, then into curl, and then into OpenSSL - curl asks OpenSSL for a bunch of random numbers (--> function 'ossl_random' in curl's OpenSSL wrapper) - OpenSSL initializes the random number generator and stores it in some random number generator context object (--> *RAND_get0_public) - this object is registered via pthread_key_create and pthread_setspecific registered in TLS - if registerAzureObjectStorage was the only place which initializes the RNG, we could argue that the leaked memory does not matter anyways as it is released after shutdown - RAND_get0_public also registers a free handler (rand_delete_thread_state) that runs in TLS, so the memory is released also if registration is called from arbitrary other threads. In sum: this is a false positive. (*) https://github.com/ClickHouse/clickhouse-private/issues/10107#issuecomment-2161282313 ``` ================================================================= ==2757181==ERROR: LeakSanitizer: detected memory leaks Direct leak of 48 byte(s) in 1 object(s) allocated from: #0 0x5672f4a48083 in malloc (/data/ch4/build_asan/programs/clickhouse+0xa2b7083) (BuildId: 4d868624feaa8b5598d9d0b327749c877bfb6cfd) #1 0x567321d05c7e in CRYPTO_malloc build_asan/./contrib/openssl/crypto/mem.c:202:11 #2 0x567321d05c7e in CRYPTO_zalloc build_asan/./contrib/openssl/crypto/mem.c:222:11 #3 0x567321d5f9cf in EVP_RAND_CTX_new build_asan/./contrib/openssl/crypto/evp/evp_rand.c:353:11 #4 0x567321d627db in rand_new_drbg build_asan/./contrib/openssl/crypto/rand/rand_lib.c:658:11 #5 0x567321d61e7b in RAND_get0_public build_asan/./contrib/openssl/crypto/rand/rand_lib.c:777:16 #6 0x567321d61d4f in RAND_bytes_ex build_asan/./contrib/openssl/crypto/rand/rand_lib.c:378:12 #7 0x56731cfe9267 in ossl_random openssl.c #8 0x56731cf534ae in Curl_rand (/data/ch4/build_asan/programs/clickhouse+0x327c24ae) (BuildId: 4d868624feaa8b5598d9d0b327749c877bfb6cfd) #9 0x56731cf757dc in Curl_socketpair (/data/ch4/build_asan/programs/clickhouse+0x327e47dc) (BuildId: 4d868624feaa8b5598d9d0b327749c877bfb6cfd) #10 0x56731cf40bfe in Curl_multi_handle (/data/ch4/build_asan/programs/clickhouse+0x327afbfe) (BuildId: 4d868624feaa8b5598d9d0b327749c877bfb6cfd) #11 0x56731cecb260 in curl_easy_perform (/data/ch4/build_asan/programs/clickhouse+0x3273a260) (BuildId: 4d868624feaa8b5598d9d0b327749c877bfb6cfd) #12 0x56731cd4a351 in Azure::Core::Http::CurlConnection::CurlConnection(Azure::Core::Http::Request&, Azure::Core::Http::CurlTransportOptions const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::basic_string, std::__1::allocator> const&) build_asan/./contrib/azure/sdk/core/azure-core/src/http/curl/curl.cpp:2441:24 #13 0x56731cd3176b in std::__1::__unique_if::__unique_single std::__1::make_unique[abi:v15000], std::__1::allocator> const&, std::__1::basic_string, std::__1::allocator> const&>(Azure::Core::Http::Request&, Azure::Core::H ttp::CurlTransportOptions const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::basic_string, std::__1::allocator> const&) build_asan/./contrib/llvm-project/libcxx/include/__memory/unique_ptr.h:714:32 #14 0x56731cd3176b in Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(Azure::Core::Http::Request&, Azure::Core::Http::CurlTransportOptions const&, bool) build_asan/./contrib/azure/sdk/core/azure-core/src/http/curl/curl.cpp:2126:10 #15 0x56731cd2f891 in Azure::Core::Http::CurlTransport::Send(Azure::Core::Http::Request&, Azure::Core::Context const&) build_asan/./contrib/azure/sdk/core/azure-core/src/http/curl/curl.cpp:351:48 #16 0x56731cdd66db in Azure::Core::Http::Policies::_internal::TransportPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/core/azure-core/src/http/transport_policy.cpp:121:40 #17 0x56731cd7c75b in Azure::Core::Http::Policies::_internal::LogPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/core/azure-core/src/http/log_policy.cpp:114:23 #18 0x56731cdd0218 in Azure::Core::Http::Policies::_internal::RequestActivityPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/core/azure-core/src/http/request_activity_policy.cpp:110:23 #19 0x56731cec5f18 in Azure::Storage::_internal::StoragePerRetryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/storage/azure-storage-common/src/storage_per_retry_policy.cpp:57:23 #20 0x56731cec6d0b in Azure::Storage::_internal::StorageSwitchToSecondaryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/storage/azure-storage-common/src/storage_switch_to_secondary_policy.cpp:36:32 #21 0x56731cdcd019 in Azure::Core::Http::Policies::_internal::RetryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/core/azure-core/src/http/retry_policy.cpp:146:34 #22 0x56731cdd6e17 in Azure::Core::Http::Policies::_internal::TelemetryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/core/azure-core/src/http/telemetry_policy.cpp:23:21 #23 0x56731cdb0ef5 in Azure::Core::Http::Policies::_internal::RequestIdPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/core/azure-core/inc/azure/core/http/policies/policy.hpp:453:27 #24 0x56731cdfc53e in Azure::Storage::_internal::StorageServiceVersionPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/storage/azure-storage-common/inc/azure/storage/common/internal/storage_service_version_policy.hpp:34:25 #25 0x56731ce4bff1 in Azure::Core::Http::_internal::HttpPipeline::Send(Azure::Core::Http::Request&, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/core/azure-core/inc/azure/core/internal/http/pipeline.hpp:230:29 #26 0x56731ce4bff1 in Azure::Storage::Blobs::_detail::BlobContainerClient::Create(Azure::Core::Http::_internal::HttpPipeline&, Azure::Core::Url const&, Azure::Storage::Blobs::_detail::BlobContainerClient::CreateBlobContainerOptions const&, Azure::Core::Context const&) build_asan/./contrib/azure/sdk/storage/azure-storage-blobs/src/rest_client.cpp:1415:36 #27 0x56731ce0bdd8 in Azure::Storage::Blobs::BlobContainerClient::Create(Azure::Storage::Blobs::CreateBlobContainerOptions const&, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/storage/azure-storage-blobs/src/blob_container_client.cpp:258:12 #28 0x56731ce396dc in Azure::Storage::Blobs::BlobServiceClient::CreateBlobContainer(std::__1::basic_string, std::__1::allocator> const&, Azure::Storage::Blobs::CreateBlobContainerOptions const&, Azure::Core::Context const&) const build_asan/./contrib/azure/sdk/storage/azure-storage-blobs/src/blob_service_client.cpp:264:41 #29 0x56731018fcff in DB::getAzureBlobContainerClient(Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&) build_asan/./src/Disks/ObjectStorages/AzureBlobStorage/AzureBlobStorageAuth.cpp:236:75 #30 0x5673115a7352 in DB::registerAzureObjectStorage(DB::ObjectStorageFactory&)::$_0::operator()(std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool) const build_asan/./src/Disks/ObjectStorages/ObjectStorageFactory.cpp:315:13 #31 0x5673115a7352 in decltype(std::declval()(std::declval, std::__1::allocator> const&>(), std::declval(), std::declval, std::__1::allocator> const&>(), std::declval const&>(), std::declval() )) std::__1::__invoke[abi:v15000], std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool>(DB::registerAzureObjectStorage(DB::ObjectStorageFactory&)::$_0&, std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool&&) build_asan/./contrib/llvm-project/libcxx/include/__functional/invoke.h:394:23 #32 0x5673115a7352 in std::__1::shared_ptr std::__1::__invoke_void_return_wrapper, false>::__call, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_pt r const&, bool>(DB::registerAzureObjectStorage(DB::ObjectStorageFactory&)::$_0&, std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool&&) build_asan/./contrib/llvm-project/libcxx/include/__functional/invoke.h:470:16 #33 0x5673115a7352 in std::__1::__function::__default_alloc_func (std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool)>::operator()[abi:v 15000](std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool&&) build_asan/./contrib/llvm-project/libcxx/include/__functional/function.h:235:12 #34 0x5673115a7352 in std::__1::shared_ptr std::__1::__function::__policy_invoker (std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool)>::__call_impl (std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool)>>(std::__1::__function::__policy_storage const*, std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool) build_asan/./contrib/llvm-project/libcxx/include/__functional/function.h:716:16 #35 0x5673115a0780 in std::__1::__function::__policy_func (std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool)>::operator()[abi:v15000](std::__1::basic_string, std::_ _1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool&&) const build_asan/./contrib/llvm-project/libcxx/include/__functional/function.h:848:16 #36 0x5673115a0780 in std::__1::function (std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool)>::operator()(std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool) const build_asan/./contrib/llvm-project/libcxx/include/__functional/function.h:1187:12 #37 0x5673115a0780 in DB::ObjectStorageFactory::create(std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr const&, bool) const build_asan/./src/Disks/ObjectStorages/ObjectStorageFactory.cpp:135:12 #38 0x56731159ef45 in DB::registerDiskObjectStorage(DB::DiskFactory&, bool)::$_0::operator()(std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr, std::__1::map, std::__1::allocator>, std::__1: :shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&, bool, bool) const build_asan/./src/Disks/ObjectStorages/RegisterDiskObjectStorage.cpp:27:64 #39 0x56731159ef45 in decltype(std::declval()(std::declval, std::__1::allocator> const&>(), std::declval(), std::declval, std::__1::allocator> const&>(), std::declval>(), std::declval, std::__1::allocator>, std::__1::shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&>(), std::declval(), std::declval())) std::__1::__invoke[abi:v15000], std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr, std::__1::map, std::__1::allocator>, std::__1::shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&, bool, bool>(DB::registerDiskObjectStorage(DB::DiskFactory&, bool)::$_0&, std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_ string, std::__1::allocator> const&, std::__1::shared_ptr&&, std::__1::map, std::__1::allocator>, std::__1::shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&, bool&&, bool&&) build_asan/./contrib/llvm-project/libcxx/include/__functional/invoke.h:394:23 #40 0x56731159ef45 in std::__1::shared_ptr std::__1::__invoke_void_return_wrapper, false>::__call, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr, std::__1::map, std::__1::allocator>, std::__1::shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&, bool, bool>(DB::registerDiskObjectStorage(DB::DiskFactory&, bool)::$_0 &, std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr&&, std::__1::map, std::__1::allocator>, std::__1::shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&, bool&&, bool&&) build_asan/./contrib/llvm-project/libcxx/include/__functional/invoke.h:470:16 #41 0x56731159ef45 in std::__1::__function::__default_alloc_func (std::__1::basic_string, std::__1::allocator> const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr, std::__1::map, std::__1::allocator>, std::__1::shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&, bool, bool)>::operator()[abi:v15000](std::__1::basic_string, std::__1::allocator > const&, Poco::Util::AbstractConfiguration const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::shared_ptr&&, std::__1::map, std::__1::allocator>, std::__1::shared_ptr, std::__1::less, std::__1::allocator>>, std::__1::allocator, std::__1::allocator> const, std::__1::shared_ptr>>> const&, bool&&, bool&&) build_asan/./contrib/llvm-project/libcxx/include/__functional/function.h:235:12 ``` (cherry picked from commit 8eaedf35d2f9077f1ead2d89478812ba437d860b) --- crypto/rand/rand_lib.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index df70d1c2b1dad..5ea967dda21c8 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -103,6 +103,13 @@ static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx) return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX); } + +#if defined(__has_feature) +# if __has_feature(address_sanitizer) +#include +# endif +#endif + #ifndef FIPS_MODULE #include #include @@ -857,13 +864,22 @@ static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) if (CRYPTO_THREAD_get_local(&dgbl->private) == NULL && !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state)) return NULL; - rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL, - SECONDARY_RESEED_TIME_INTERVAL); +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_disable(); +# endif +#endif + rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL, + SECONDARY_RESEED_TIME_INTERVAL); if (!CRYPTO_THREAD_set_local(&dgbl->public, rand)) { EVP_RAND_CTX_free(rand); rand = NULL; } - } +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_enable(); +# endif +#endif return rand; } From fc1f070bc195b52ef984bb27b35816525297bfd6 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Tue, 11 Jun 2024 20:59:59 +0000 Subject: [PATCH 183/189] Suppress leaky memory warning in OpenSSL's error handling The leak was reported in https://github.com/ClickHouse/ClickHouse/issues/63792 - a SSL session is established - somewhere down in OpenSSL, the per-thread error queue is clear'ed - when no error queue exists (e.g. because the thread was just spawned), a new error queue is allocated - the error queue is stored in TLS, and a free handler is registered which deletes it when the thread ends - Leak sanitizer does not understand ^^ (false positive) ``` Direct leak of 9944 byte(s) in 11 object(s) allocated from: #0 0x5571bf7e04cf in malloc (/usr/bin/clickhouse+0xa39a4cf) (BuildId: 06c4931100f632dde9d0ecd3cf6a67776742e29b) #1 0x5571ecbc06be in CRYPTO_malloc build_docker/./contrib/openssl/crypto/mem.c:202:11 #2 0x5571ecbc06be in CRYPTO_zalloc build_docker/./contrib/openssl/crypto/mem.c:222:11 #3 0x5571ecb03c6a in ossl_err_get_state_int build_docker/./contrib/openssl/crypto/err/err.c:691:17 #4 0x5571ecb037b5 in ERR_clear_error build_docker/./contrib/openssl/crypto/err/err.c:339:10 #5 0x5571ec9cf0d0 in state_machine build_docker/./contrib/openssl/ssl/statem/statem.c:366:5 #6 0x5571ec90c7d4 in SSL_do_handshake build_docker/./contrib/openssl/ssl/ssl_lib.c:4746:19 #7 0x5571e70cc501 in Poco::Net::SecureSocketImpl::connectSSL(bool) build_docker/./base/poco/NetSSL_OpenSSL/src/SecureSocketImpl.cpp:206:11 #8 0x5571e70cce6b in Poco::Net::SecureSocketImpl::connect(Poco::Net::SocketAddress const&, Poco::Timespan const&, bool) build_docker/./base/poco/NetSSL_OpenSSL/src/SecureSocketImpl.cpp:149:2 #9 0x5571e70d81f7 in Poco::Net::SecureStreamSocketImpl::connect(Poco::Net::SocketAddress const&, Poco::Timespan const&) build_docker/./base/poco/NetSSL_OpenSSL/src/SecureStreamSocketImpl.cpp:87:8 #10 0x5571e0ca708a in DB::Connection::connect(DB::ConnectionTimeouts const&) build_docker/./src/Client/Connection.cpp:158:29 ``` (cherry picked from commit 9e7862cea9fde8af56859f38714bba979a1de75d) --- crypto/err/err.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crypto/err/err.c b/crypto/err/err.c index a995c4e2422de..2a0af875b44d2 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -26,6 +26,12 @@ #include "internal/e_os.h" #include "err_local.h" +#if defined(__has_feature) +# if __has_feature(address_sanitizer) +#include +# endif +#endif + /* Forward declaration in case it's not published because of configuration */ ERR_STATE *ERR_get_state(void); @@ -689,7 +695,17 @@ ERR_STATE *ossl_err_get_state_int(void) if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE *)-1)) return NULL; +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_disable(); +# endif +#endif state = OSSL_ERR_STATE_new(); +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_enable(); +# endif +#endif if (state == NULL) { CRYPTO_THREAD_set_local(&err_thread_local, NULL); return NULL; From 4312e627e29b205c1a6f6c092171ecf14dee4485 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Tue, 18 Jun 2024 19:59:52 +0000 Subject: [PATCH 184/189] Suppress leaksan false positive (cherry picked from commit b50f55132d05d51e92a9bcd1e0f7698c831703f0) --- crypto/engine/eng_lib.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crypto/engine/eng_lib.c b/crypto/engine/eng_lib.c index 04a2602ed2d8c..bc643a1b4e67f 100644 --- a/crypto/engine/eng_lib.c +++ b/crypto/engine/eng_lib.c @@ -12,6 +12,12 @@ #include #include "internal/refcount.h" +#if defined(__has_feature) +# if __has_feature(address_sanitizer) +#include +# endif +#endif + CRYPTO_RWLOCK *global_engine_lock; CRYPTO_ONCE engine_lock_init = CRYPTO_ONCE_STATIC_INIT; @@ -33,8 +39,18 @@ ENGINE *ENGINE_new(void) ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); return 0; } +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_disable(); +# endif +#endif if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_enable(); +# endif +#endif if (!CRYPTO_NEW_REF(&ret->struct_ref, 1)) { OPENSSL_free(ret); return NULL; From 4439909b2dd057d1405138528c733070e87a257c Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Sun, 30 Jun 2024 14:35:04 +0000 Subject: [PATCH 185/189] Suppress leaky memory warning, pt. II ClickHouse issue https://github.com/ClickHouse/clickhouse-private/issues/10107#issuecomment-2189755698 reports this memory leak: (note how it is very similar to https://github.com/ClickHouse/clickhouse-private/issues/10107#issue-2314912657) ``` Direct leak of 528 byte(s) in 11 object(s) allocated from: #0 0x561369af24cf in malloc (/usr/bin/clickhouse+0xa6cf4cf) (BuildId: 22880fad595a96b17eb9add20e7a01f8ded54c49) #1 0x561397b86a7e in CRYPTO_malloc build_docker/./contrib/openssl/crypto/mem.c:202:11 #2 0x561397b86a7e in CRYPTO_zalloc build_docker/./contrib/openssl/crypto/mem.c:222:11 #3 0x561397be07cf in EVP_RAND_CTX_new build_docker/./contrib/openssl/crypto/evp/evp_rand.c:353:11 #4 0x561397be35fb in rand_new_drbg build_docker/./contrib/openssl/crypto/rand/rand_lib.c:665:11 #5 0x561397be2a9b in RAND_get0_private build_docker/./contrib/openssl/crypto/rand/rand_lib.c:827:16 #6 0x561397be296f in RAND_priv_bytes_ex build_docker/./contrib/openssl/crypto/rand/rand_lib.c:356:12 #7 0x5613978d7cd8 in SSL_CTX_new_ex build_docker/./contrib/openssl/ssl/ssl_lib.c:4016:13 #8 0x561392d1eabd in ossl_connect_common openssl.c #9 0x561392d11e23 in ssl_cf_connect vtls.c #10 0x561392c13a1f in cf_setup_connect connect.c #11 0x561392c1b0e5 in cf_hc_connect cf-https-connect.c #12 0x561392c0a332 in Curl_conn_connect (/usr/bin/clickhouse+0x337e7332) (BuildId: 22880fad595a96b17eb9add20e7a01f8ded54c49) #13 0x561392c7a28a in multi_runsingle multi.c #14 0x561392c78f6d in curl_multi_perform (/usr/bin/clickhouse+0x33855f6d) (BuildId: 22880fad595a96b17eb9add20e7a01f8ded54c49) #15 0x561392bfd53e in curl_easy_perform (/usr/bin/clickhouse+0x337da53e) (BuildId: 22880fad595a96b17eb9add20e7a01f8ded54c49) #16 0x561392a7c411 in Azure::Core::Http::CurlConnection::CurlConnection(Azure::Core::Http::Request&, Azure::Core::Http::CurlTransportOptions const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::basic_string, std::__1::allocator> const&) build_docker/./contrib/azure/sdk/core/azure-core/src/http/curl/curl.cpp:2441:24 #17 0x561392a6382b in std::__1::__unique_if::__unique_single std::__1::make_unique[abi:v15000], std::__1::allocator> const&, std::__1::basic_string, std::__1::allocator> const&>(Azure::Core::Http::Request&, Azure::Core::Http::CurlTransportOptions const&, std::__1::basic_string, std::__1::allocator> const&, std::__1::basic_string, std::__1::allocator> const&) build_docker/./contrib/llvm-project/libcxx/include/__memory/unique_ptr.h:714:32 #18 0x561392a6382b in Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(Azure::Core::Http::Request&, Azure::Core::Http::CurlTransportOptions const&, bool) build_docker/./contrib/azure/sdk/core/azure-core/src/http/curl/curl.cpp:2126:10 #19 0x561392a61951 in Azure::Core::Http::CurlTransport::Send(Azure::Core::Http::Request&, Azure::Core::Context const&) build_docker/./contrib/azure/sdk/core/azure-core/src/http/curl/curl.cpp:351:48 #20 0x561392b0879b in Azure::Core::Http::Policies::_internal::TransportPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/core/azure-core/src/http/transport_policy.cpp:121:40 #21 0x561392aae81b in Azure::Core::Http::Policies::_internal::LogPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/core/azure-core/src/http/log_policy.cpp:114:23 #22 0x561392b022d8 in Azure::Core::Http::Policies::_internal::RequestActivityPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/core/azure-core/src/http/request_activity_policy.cpp:110:23 #23 0x561392b2e02a in Azure::Storage::_internal::SharedKeyPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/storage/azure-storage-common/inc/azure/storage/common/internal/shared_key_policy.hpp:36:25 #24 0x561392bf7fd8 in Azure::Storage::_internal::StoragePerRetryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/storage/azure-storage-common/src/storage_per_retry_policy.cpp:57:23 #25 0x561392bf8dcb in Azure::Storage::_internal::StorageSwitchToSecondaryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/storage/azure-storage-common/src/storage_switch_to_secondary_policy.cpp:36:32 #26 0x561392aff0d9 in Azure::Core::Http::Policies::_internal::RetryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/core/azure-core/src/http/retry_policy.cpp:146:34 #27 0x561392b08ed7 in Azure::Core::Http::Policies::_internal::TelemetryPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/core/azure-core/src/http/telemetry_policy.cpp:23:21 #28 0x561392ae2fb5 in Azure::Core::Http::Policies::_internal::RequestIdPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/core/azure-core/inc/azure/core/http/policies/policy.hpp:453:27 #29 0x561392b2e5fe in Azure::Storage::_internal::StorageServiceVersionPolicy::Send(Azure::Core::Http::Request&, Azure::Core::Http::Policies::NextHttpPolicy, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/storage/azure-storage-common/inc/azure/storage/common/internal/storage_service_version_policy.hpp:34:25 #30 0x561392b7e0b1 in Azure::Core::Http::_internal::HttpPipeline::Send(Azure::Core::Http::Request&, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/core/azure-core/inc/azure/core/internal/http/pipeline.hpp:230:29 #31 0x561392b7e0b1 in Azure::Storage::Blobs::_detail::BlobContainerClient::Create(Azure::Core::Http::_internal::HttpPipeline&, Azure::Core::Url const&, Azure::Storage::Blobs::_detail::BlobContainerClient::CreateBlobContainerOptions const&, Azure::Core::Context const&) build_docker/./contrib/azure/sdk/storage/azure-storage-blobs/src/rest_client.cpp:1415:36 #32 0x561392b3de98 in Azure::Storage::Blobs::BlobContainerClient::Create(Azure::Storage::Blobs::CreateBlobContainerOptions const&, Azure::Core::Context const&) const build_docker/./contrib/azure/sdk/storage/azure-storage-blobs/src/blob_container_client.cpp:258:12 ``` - at database startup, Azure is registered as an object storage (--> registerAzureObjectStorage) - this calls into Azure, then into curl, and then into OpenSSL - curl asks OpenSSL for a bunch of random numbers (--> function 'ossl_random' in curl's OpenSSL wrapper) - OpenSSL initializes the random number generator and stores it in some random number generator context object (--> *RAND_get0_private) - this object is registered via pthread_key_create and pthread_setspecific registered in TLS - if registerAzureObjectStorage was the only place which initializes the RNG, we could argue that the leaked memory does not matter anyways as it is released after shutdown - RAND_get0_public also registers a free handler (rand_delete_thread_state) that runs in TLS, so the memory is released also if registration is called from arbitrary other threads. In sum: this is a false positive. As a result, the fix is similar to earlier fix https://github.com/ClickHouse/openssl/commit/5c4b034785bf04f80380138cf49bf9743400f144 (cherry picked from commit 499f1ee900142f6b714dee99280d31df7b2eb4c0) --- crypto/rand/rand_lib.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 5ea967dda21c8..616e70792c9bb 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -869,7 +869,7 @@ static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) __lsan_disable(); # endif #endif - rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL, + rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL, SECONDARY_RESEED_TIME_INTERVAL); if (!CRYPTO_THREAD_set_local(&dgbl->public, rand)) { EVP_RAND_CTX_free(rand); @@ -880,9 +880,9 @@ static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) __lsan_enable(); # endif #endif + } return rand; } - /* * Get the public random generator. * Returns pointer to its EVP_RAND_CTX on success, NULL on failure. @@ -915,12 +915,22 @@ static EVP_RAND_CTX *rand_get0_private(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) if (CRYPTO_THREAD_get_local(&dgbl->public) == NULL && !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state)) return NULL; +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_disable(); +# endif +#endif rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL, - SECONDARY_RESEED_TIME_INTERVAL); + SECONDARY_RESEED_TIME_INTERVAL); if (!CRYPTO_THREAD_set_local(&dgbl->private, rand)) { EVP_RAND_CTX_free(rand); rand = NULL; } +#if defined(__has_feature) +# if __has_feature(address_sanitizer) + __lsan_enable(); +# endif +#endif } return rand; } From d59146714a3f027ddb0075f0695fb10e6bdf147b Mon Sep 17 00:00:00 2001 From: Konstantin Bogdanov Date: Mon, 30 Jun 2025 08:27:07 +0200 Subject: [PATCH 186/189] Remove submodules (cherry picked from commit 6e1c68f6d03d3607c2ff468f2a59e3200dbabccd) --- pkcs11-provider | 1 - 1 file changed, 1 deletion(-) delete mode 160000 pkcs11-provider diff --git a/pkcs11-provider b/pkcs11-provider deleted file mode 160000 index 64fc325ac0f91..0000000000000 --- a/pkcs11-provider +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 64fc325ac0f91d03d76b3546df2998d3a38c525b From b0fe9d5cd49a482cf451464e1e41d950fe8a1266 Mon Sep 17 00:00:00 2001 From: Konstantin Bogdanov Date: Mon, 27 Oct 2025 10:16:08 +0100 Subject: [PATCH 187/189] Add msan_unpoison around SHA3 assembly calls Related MSan error log: ==2046343==WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x556f1dce43f2 in sample_scalar /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/ml_kem/ml_kem.c:449:47 #1 0x556f1dce43f2 in matrix_expand /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/ml_kem/ml_kem.c:999:21 #2 0x556f1dcdec79 in genkey /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/ml_kem/ml_kem.c:1391:10 #3 0x556f1dcde895 in ossl_ml_kem_genkey /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/ml_kem/ml_kem.c:1879:15 #4 0x556f1dd71e1b in ml_kem_gen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/providers/implementations/keymgmt/ml_kem_kmgmt.c:771:13 #5 0x556f1da6add2 in evp_keymgmt_gen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/keymgmt_meth.c:464:11 #6 0x556f1da68160 in evp_keymgmt_util_gen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/keymgmt_lib.c:518:20 #7 0x556f1da8f2f4 in EVP_PKEY_generate /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/pmeth_gn.c:189:13 #8 0x556f1da570d4 in evp_pkey_keygen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/evp_lib.c:1216:15 #9 0x556f1da570d4 in EVP_PKEY_Q_keygen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/evp_lib.c:1242:11 #10 0x556f1dd763f8 in mlx_kem_gen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/providers/implementations/keymgmt/mlx_kmgmt.c:707:17 #11 0x556f1da6add2 in evp_keymgmt_gen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/keymgmt_meth.c:464:11 #12 0x556f1da68160 in evp_keymgmt_util_gen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/keymgmt_lib.c:518:20 #13 0x556f1da8f2f4 in EVP_PKEY_generate /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/pmeth_gn.c:189:13 #14 0x556f1da8f972 in EVP_PKEY_keygen /home/thevar1able/nvmemount/clickhouse/contrib/openssl/crypto/evp/pmeth_gn.c:274:12 #15 0x556f1d8355b3 in ssl_generate_pkey_group /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/s3_lib.c:4935:9 #16 0x556f1d884598 in add_key_share /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/statem/extensions_clnt.c:661:25 #17 0x556f1d88417f in tls_construct_ctos_key_share /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/statem/extensions_clnt.c:766:18 #18 0x556f1d87cdec in tls_construct_extensions /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/statem/extensions.c:910:15 #19 0x556f1d8a777c in tls_construct_client_hello /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/statem/statem_clnt.c:1357:10 #20 0x556f1d8a2465 in write_state_machine /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/statem/statem.c:902:26 #21 0x556f1d8a2465 in state_machine /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/statem/statem.c:492:21 #22 0x556f1d8a1536 in ossl_statem_connect /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/statem/statem.c:301:12 #23 0x556f1d858378 in SSL_do_handshake /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/ssl_lib.c:5007:19 #24 0x556f1d858680 in SSL_connect /home/thevar1able/nvmemount/clickhouse/contrib/openssl/ssl/ssl_lib.c:2243:12 #25 0x556f1ab7f511 in Poco::Net::SecureSocketImpl::connectSSL(bool) /home/thevar1able/nvmemount/clickhouse/base/poco/NetSSL_OpenSSL/src/SecureS ocketImpl.cpp:205:11 #26 0x556f1ab80143 in Poco::Net::SecureSocketImpl::connect(Poco::Net::SocketAddress const&, Poco::Timespan const&, bool) /home/thevar1able/nvme mount/clickhouse/base/poco/NetSSL_OpenSSL/src/SecureSocketImpl.cpp:148:2 #27 0x556f1ab8dd4a in Poco::Net::SecureStreamSocketImpl::connect(Poco::Net::SocketAddress const&, Poco::Timespan const&) /home/thevar1able/nvme mount/clickhouse/base/poco/NetSSL_OpenSSL/src/SecureStreamSocketImpl.cpp:99:8 #28 0x556f1ab3d96d in Poco::Net::StreamSocket::connect(Poco::Net::SocketAddress const&, Poco::Timespan const&) /home/thevar1able/nvmemount/clic khouse/base/poco/Net/src/StreamSocket.cpp:89:10 #29 0x556f1aabfaa7 in Poco::Net::HTTPSession::connect(Poco::Net::SocketAddress const&) /home/thevar1able/nvmemount/clickhouse/base/poco/Net/src /HTTPSession.cpp:239:10 #30 0x556f1ab55f54 in Poco::Net::HTTPSClientSession::connect(Poco::Net::SocketAddress const&) /home/thevar1able/nvmemount/clickhouse/base/poco/ NetSSL_OpenSSL/src/HTTPSClientSession.cpp:182:16 #31 0x556f1aa86972 in Poco::Net::HTTPClientSession::reconnect(unsigned long*) /home/thevar1able/nvmemount/clickhouse/base/poco/Net/src/HTTPClie ntSession.cpp:471:13 #32 0x556ee2448df8 in DB::EndpointConnectionPool::PooledConnection::doConnect(unsigned long*) /home/thevar1able/ nvmemount/clickhouse/src/Common/HTTPConnectionPool.cpp:515:22 #33 0x556ee2448df8 in DB::EndpointConnectionPool::prepareNewConnection(DB::ConnectionTimeouts const&, unsigned l ong*) /home/thevar1able/nvmemount/clickhouse/src/Common/HTTPConnectionPool.cpp:690:25 #34 0x556ee2445eed in DB::EndpointConnectionPool::getConnection(DB::ConnectionTimeouts const&, unsigned long*) / home/thevar1able/nvmemount/clickhouse/src/Common/HTTPConnectionPool.cpp:603:16 #35 0x556ee248e8c9 in DB::makeHTTPSession(DB::HTTPConnectionGroupType, Poco::URI const&, DB::ConnectionTimeouts const&, DB::ProxyConfiguration const&, unsigned long*) /home/thevar1able/nvmemount/clickhouse/src/IO/HTTPCommon.cpp:63:29 #36 0x556ee91f3da5 in DB::ReadWriteBufferFromHTTP::callImpl(Poco::Net::HTTPResponse&, std::__1::basic_string, std::__1::allocator> const&, std::__1::optional const&, bool) const /home/thevar1able/nvmemount/clic khouse/src/IO/ReadWriteBufferFromHTTP.cpp:272:20 #37 0x556ee91f44b9 in DB::ReadWriteBufferFromHTTP::callWithRedirects(Poco::Net::HTTPResponse&, std::__1::basic_string, std::__1::allocator> const&, std::__1::optional const&) /home/thevar1able/nvmemount/clickho use/src/IO/ReadWriteBufferFromHTTP.cpp:290:19 #38 0x556ee91f6182 in DB::ReadWriteBufferFromHTTP::initialize() /home/thevar1able/nvmemount/clickhouse/src/IO/ReadWriteBufferFromHTTP.cpp:413:1 9 (cherry picked from commit 2720d8c08f0853b6388988fc600ca4b6370e4ed9) --- crypto/sha/sha3.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crypto/sha/sha3.c b/crypto/sha/sha3.c index 21e1070beed27..1cdc8e983e8e8 100644 --- a/crypto/sha/sha3.c +++ b/crypto/sha/sha3.c @@ -13,6 +13,12 @@ #endif #include "internal/sha3.h" +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# endif +#endif + void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, int next); void ossl_sha3_reset(KECCAK1600_CTX *ctx) @@ -122,8 +128,21 @@ int ossl_sha3_final(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen) (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz); +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(ctx->buf, bsz); +# endif +#endif + ctx->xof_state = XOF_STATE_FINAL; SHA3_squeeze(ctx->A, out, outlen, bsz, 0); + +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(out, outlen); +# endif +#endif + return 1; } @@ -191,6 +210,13 @@ int ossl_sha3_squeeze(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen) if (outlen >= bsz) { len = bsz * (outlen / bsz); SHA3_squeeze(ctx->A, out, len, bsz, next); + +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(out, len); +# endif +#endif + next = 1; out += len; outlen -= len; @@ -198,6 +224,13 @@ int ossl_sha3_squeeze(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen) if (outlen > 0) { /* Step 3. Squeeze one more block into a buffer */ SHA3_squeeze(ctx->A, ctx->buf, bsz, bsz, next); + +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(ctx->buf, bsz); +# endif +#endif + memcpy(out, ctx->buf, outlen); /* Step 4. Remember the leftover part of the squeezed block */ ctx->bufsz = bsz - outlen; From e485f2f872417be02dd334a4a87579bcbd2d8286 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sun, 15 Feb 2026 17:32:11 +0100 Subject: [PATCH 188/189] Add __msan_unpoison for X25519 assembly output buffers x25519_scalar_mult and related functions may use assembly implementations (x25519-x86_64.s) that MSan cannot instrument. Add __msan_unpoison annotations after assembly writes, following the same pattern used in sha3.c, bn_intern.c, and eng_rdrand.c. (cherry picked from commit f3b2f0273ed59cef874db0d6943f8d7d1804bd31) --- crypto/ec/curve25519.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c index c6886763aba7e..5661d33485832 100644 --- a/crypto/ec/curve25519.c +++ b/crypto/ec/curve25519.c @@ -21,6 +21,12 @@ #include "internal/numbers.h" +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# endif +#endif + #if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) #define BASE_2_64_IMPLEMENTED @@ -5846,6 +5852,12 @@ int ossl_x25519(uint8_t out_shared_key[32], const uint8_t private_key[32], { static const uint8_t kZeros[32] = { 0 }; x25519_scalar_mult(out_shared_key, private_key, peer_public_value); +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + /* x25519_scalar_mult may use assembly that MSan cannot instrument. */ + __msan_unpoison(out_shared_key, 32); +# endif +#endif /* The all-zero output results when the input is a point of small order. */ return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0; } @@ -5875,5 +5887,11 @@ void ossl_x25519_public_from_private(uint8_t out_public_value[32], fe_mul(zplusy, zplusy, zminusy_inv); fe_tobytes(out_public_value, zplusy); +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(out_public_value, 32); +# endif +#endif + OPENSSL_cleanse(e, sizeof(e)); } From d5430eb696419b7c401ee84647c7a1bafc8a26c8 Mon Sep 17 00:00:00 2001 From: Konstantin Bogdanov Date: Sat, 4 Jul 2026 10:38:24 +0200 Subject: [PATCH 189/189] Use getauxval for ARM CPU feature detection on musl OSSL_IMPLEMENT_GETAUXVAL is only enabled for glibc >= 2.16, Android, FreeBSD and OpenBSD, so on musl OPENSSL_cpuid_setup fell back to the brute-force SIGILL-based probing: install a SIGILL handler, execute each optional instruction, and siglongjmp out of the handler when it traps. That scheme breaks under ThreadSanitizer with static libc interception: the sigaction/sigsetjmp/siglongjmp round-trip through TSan's interceptors during a library constructor leads to a null pointer call inside the probe, an unrecoverable startup failure in every TSan aarch64 musl binary (OPENSSL_cpuid_setup runs as an __attribute__((constructor)) before main). musl has always provided an unversioned getauxval, so take the same HWCAP-based path as glibc. This also removes the last SIGILL-probing user in the binary and keeps CPU detection free of signal-handler tricks. The __MUSL__ macro is defined globally by the ClickHouse musl toolchain files. (cherry picked from commit 26868a38972e80dd15f56212c3677d77363f5c74) --- crypto/armcap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crypto/armcap.c b/crypto/armcap.c index 3005d295cfd0b..415c55cb46fc9 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -77,6 +77,10 @@ void OPENSSL_cpuid_setup(void) __attribute__((constructor)); #include #define OSSL_IMPLEMENT_GETAUXVAL #endif +#elif defined(__MUSL__) +/* musl has always provided getauxval(), unversioned. */ +#include +#define OSSL_IMPLEMENT_GETAUXVAL #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) #include