Commit 8c141a2cff for openssl.org
commit 8c141a2cffb58f9780615d259da35e8228656c0c
Author: huanghuihui0904 <625173@qq.com>
Date: Thu Mar 12 19:16:12 2026 +0800
crypto/evp/exchange.c: fix memory leak in EVP_PKEY_derive_SKEY()
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)
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index 5bc34d12cf..a5eea9af1d 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -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;
}