Commit 6cdcfd7106 for openssl.org
commit 6cdcfd710600343f99fecf96677c415f37a17e1a
Author: Viktor Dukhovni <openssl-users@dukhovni.org>
Date: Mon Mar 16 11:51:45 2026 +1100
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 <tomas@openssl.foundation>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
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 8a399a6b29..3b9773be31 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;