]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
crypto/evp/exchange.c: fix memory leak in EVP_PKEY_derive_SKEY()
authorhuanghuihui0904 <625173@qq.com>
Thu, 12 Mar 2026 11:16:12 +0000 (19:16 +0800)
committerTodd Short <todd.short@me.com>
Fri, 13 Mar 2026 15:40:00 +0000 (11:40 -0400)
When mgmt == NULL, EVP_PKEY_derive_SKEY() fetches an EVP_SKEYMGMT into skeymgmt. Some early returns in the fallback derive path do not free this object, causing a leak. Route these paths through shared cleanup so skeymgmt is freed.

Resolves: https://github.com/openssl/openssl/issues/30378
Fixes #30378

Signed-off-by: huanghuihui0904 <625173@qq.com>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Todd Short <todd.short@me.com>
(Merged from https://github.com/openssl/openssl/pull/30389)

(cherry picked from commit 8c141a2cffb58f9780615d259da35e8228656c0c)

crypto/evp/exchange.c

index 5bc34d12cf08c02553ec4f9ad3f7985f9acb8bde..a5eea9af1d0768b33964052167b57f25b6df64c0 100644 (file)
@@ -518,25 +518,25 @@ EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt,
 
         if (ctx->op.kex.exchange->derive == NULL) {
             ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED);
-            return NULL;
+            goto cleanup;
         }
 
         key = OPENSSL_zalloc(keylen);
         if (key == NULL) {
             ERR_raise(ERR_R_EVP_LIB, ERR_R_CRYPTO_LIB);
-            return NULL;
+            goto cleanup;
         }
 
         if (!ctx->op.kex.exchange->derive(ctx->op.kex.algctx, key, &tmplen,
                 tmplen)) {
             OPENSSL_free(key);
-            return NULL;
+            goto cleanup;
         }
 
         if (keylen != tmplen) {
             OPENSSL_free(key);
             ERR_raise(ERR_R_EVP_LIB, ERR_R_INTERNAL_ERROR);
-            return NULL;
+            goto cleanup;
         }
         import_params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES,
             key, keylen);
@@ -544,30 +544,25 @@ EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt,
         ret = EVP_SKEY_import_SKEYMGMT(ctx->libctx, skeymgmt,
             OSSL_SKEYMGMT_SELECT_SECRET_KEY, import_params);
         OPENSSL_clear_free(key, keylen);
-        if (mgmt != skeymgmt)
-            EVP_SKEYMGMT_free(skeymgmt);
-        return ret;
+        goto cleanup;
     }
 
     ret = evp_skey_alloc(skeymgmt);
-    if (ret == NULL) {
-        if (mgmt != skeymgmt)
-            EVP_SKEYMGMT_free(skeymgmt);
-        return NULL;
-    }
+    if (ret == NULL)
+        goto cleanup;
 
     ret->keydata = ctx->op.kex.exchange->derive_skey(ctx->op.kex.algctx, key_type,
         ossl_provider_ctx(skeymgmt->prov),
         skeymgmt->import, keylen, params);
 
-    if (mgmt != skeymgmt)
-        EVP_SKEYMGMT_free(skeymgmt);
-
     if (ret->keydata == NULL) {
         EVP_SKEY_free(ret);
-        return NULL;
+        ret = NULL;
+        goto cleanup;
     }
-
+cleanup:
+    if (mgmt != skeymgmt)
+        EVP_SKEYMGMT_free(skeymgmt);
     return ret;
 }