From: slontis Date: Wed, 9 Apr 2025 00:05:09 +0000 (+1000) Subject: Fix EVP_PKEY_CTX_dup() so that it copies the keymanager. X-Git-Tag: openssl-3.0.17~67 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0533e0bcba55a201e437d7b9833a9ef96bd2fba9;p=thirdparty%2Fopenssl.git Fix EVP_PKEY_CTX_dup() so that it copies the keymanager. A call to EVP_PKEY_CTX_new() creates a keymgmt pointer internally, but EVP_PKEY_CTX_dup() does not copy this field. Calling EVP_PKEY_derive_set_peer_ex() after EVP_PKEY_CTX_dup() resulted in a segfault because it tried to access this pointer. EVP_PKEY_CTX_dup() has been updated to copy the keymanager (and upref it). Reported by Eamon ODea (Oracle). Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/27304) (cherry picked from commit 3c22da73465f5dd211299e64f0de8786dcaf86c3) --- diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 245ca2d41d7..b7253f11505 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -501,6 +501,12 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) } rctx->legacy_keytype = pctx->legacy_keytype; + if (pctx->keymgmt != NULL) { + if (!EVP_KEYMGMT_up_ref(pctx->keymgmt)) + goto err; + rctx->keymgmt = pctx->keymgmt; + } + if (EVP_PKEY_CTX_IS_DERIVE_OP(pctx)) { if (pctx->op.kex.exchange != NULL) { rctx->op.kex.exchange = pctx->op.kex.exchange; diff --git a/test/ectest.c b/test/ectest.c index 946973c2f4d..0318bc9eae7 100644 --- a/test/ectest.c +++ b/test/ectest.c @@ -2707,7 +2707,7 @@ static int custom_params_test(int id) int is_prime = 0; EC_KEY *eckey1 = NULL, *eckey2 = NULL; EVP_PKEY *pkey1 = NULL, *pkey2 = NULL; - EVP_PKEY_CTX *pctx1 = NULL, *pctx2 = NULL; + EVP_PKEY_CTX *pctx1 = NULL, *pctx2 = NULL, *dctx = NULL; size_t sslen, t; unsigned char *pub1 = NULL , *pub2 = NULL; OSSL_PARAM_BLD *param_bld = NULL; @@ -2930,11 +2930,12 @@ static int custom_params_test(int id) EVP_PKEY_CTX_free(pctx1); if (!TEST_ptr(pctx1 = EVP_PKEY_CTX_new(pkey1, NULL)) || !TEST_int_eq(EVP_PKEY_derive_init(pctx1), 1) - || !TEST_int_eq(EVP_PKEY_derive_set_peer(pctx1, pkey2), 1) - || !TEST_int_eq(EVP_PKEY_derive(pctx1, NULL, &t), 1) + || !TEST_ptr(dctx = EVP_PKEY_CTX_dup(pctx1)) + || !TEST_int_eq(EVP_PKEY_derive_set_peer_ex(dctx, pkey2, 1), 1) + || !TEST_int_eq(EVP_PKEY_derive(dctx, NULL, &t), 1) || !TEST_int_gt(bsize, t) || !TEST_int_le(sslen, t) - || !TEST_int_eq(EVP_PKEY_derive(pctx1, buf1, &t), 1) + || !TEST_int_eq(EVP_PKEY_derive(dctx, buf1, &t), 1) /* compare with previous result */ || !TEST_mem_eq(buf1, t, buf2, sslen)) goto err; @@ -2962,6 +2963,7 @@ static int custom_params_test(int id) EVP_PKEY_free(pkey2); EVP_PKEY_CTX_free(pctx1); EVP_PKEY_CTX_free(pctx2); + EVP_PKEY_CTX_free(dctx); return ret; }