]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix ECDSA sig CTX dup "sig" aliasing, error paths
authorViktor Dukhovni <openssl-users@dukhovni.org>
Mon, 16 Mar 2026 00:51:45 +0000 (11:51 +1100)
committerEugene Syromiatnikov <esyr@openssl.org>
Fri, 20 Mar 2026 18:15:22 +0000 (19:15 +0100)
- 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)

providers/implementations/signature/ecdsa_sig.c

index 8a399a6b29d83be208bf13d0c4d8678c93db3c77..3b9773be3168724eb97407f22644cdd530edbfeb 100644 (file)
@@ -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;