From: Viktor Dukhovni Date: Mon, 16 Mar 2026 00:51:45 +0000 (+1100) Subject: Fix ECDSA sig CTX dup "sig" aliasing, error paths X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cdcfd710600343f99fecf96677c415f37a17e1a;p=thirdparty%2Fopenssl.git Fix ECDSA sig CTX dup "sig" aliasing, error paths - The context "sig" field ended up shared by both contexts after a dup, leading to a later double-free. Reported by Stanislav Fort and Pavel Kohout of Aisle Research. - Rare error paths could lead to a memory leak or to use-after-free and/or double-free. Reported by Kenaz Wang. Fixes: edd3b7a309f8 "Add ECDSA to providers" Fixes: f68ba38e1890 "Refactor OpenSSL 'ECDSA' EVP_SIGNATURE to also include ECDSA+hash composites" Reviewed-by: Tomas Mraz Reviewed-by: Shane Lontis Reviewed-by: Eugene Syromiatnikov MergeDate: Fri Mar 20 18:15:48 2026 (Merged from https://github.com/openssl/openssl/pull/30479) --- diff --git a/providers/implementations/signature/ecdsa_sig.c b/providers/implementations/signature/ecdsa_sig.c index 8a399a6b29d..3b9773be316 100644 --- a/providers/implementations/signature/ecdsa_sig.c +++ b/providers/implementations/signature/ecdsa_sig.c @@ -657,40 +657,37 @@ static void *ecdsa_dupctx(void *vctx) PROV_ECDSA_CTX *srcctx = (PROV_ECDSA_CTX *)vctx; PROV_ECDSA_CTX *dstctx; - if (!ossl_prov_is_running()) - return NULL; - - dstctx = OPENSSL_zalloc(sizeof(*srcctx)); - if (dstctx == NULL) + /* Test KATS should not need to be supported */ + if (!ossl_prov_is_running() + || srcctx->kinv != NULL + || srcctx->r != NULL + || (dstctx = OPENSSL_memdup(srcctx, sizeof(*srcctx))) == NULL) return NULL; - *dstctx = *srcctx; dstctx->ec = NULL; dstctx->propq = NULL; + dstctx->md = NULL; + dstctx->mdctx = NULL; + dstctx->sig = NULL; if (srcctx->ec != NULL && !EC_KEY_up_ref(srcctx->ec)) goto err; - /* Test KATS should not need to be supported */ - if (srcctx->kinv != NULL || srcctx->r != NULL) - goto err; dstctx->ec = srcctx->ec; if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md)) goto err; dstctx->md = srcctx->md; - if (srcctx->mdctx != NULL) { - dstctx->mdctx = EVP_MD_CTX_new(); - if (dstctx->mdctx == NULL - || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx)) - goto err; - } - - if (srcctx->propq != NULL) { - dstctx->propq = OPENSSL_strdup(srcctx->propq); - if (dstctx->propq == NULL) - goto err; - } + if (srcctx->mdctx != NULL + && ((dstctx->mdctx = EVP_MD_CTX_new()) == NULL + || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))) + goto err; + if (srcctx->propq != NULL + && (dstctx->propq = OPENSSL_strdup(srcctx->propq)) == NULL) + goto err; + if (srcctx->sig != NULL + && (dstctx->sig = OPENSSL_memdup(srcctx->sig, srcctx->siglen)) == NULL) + goto err; return dstctx; err: @@ -971,6 +968,12 @@ static int ecdsa_sigalg_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (!OSSL_PARAM_get_octet_string(p.sig, (void **)&ctx->sig, 0, &ctx->siglen)) return 0; + /* The signature must not be empty */ + if (ctx->siglen == 0) { + OPENSSL_free(ctx->sig); + ctx->sig = NULL; + return 0; + } } } return 1;