From a4105f7882bc366e693cc9bb5773d6ccc8fd3726 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 6 Feb 2026 15:06:51 +0000 Subject: [PATCH] Pass low level DH objects to the default provider As we did for RSA objects we do the same for DH objects. Fixes #29942 Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz MergeDate: Fri Feb 13 07:58:25 2026 (Merged from https://github.com/openssl/openssl/pull/29960) --- crypto/dh/dh_lib.c | 5 ++ include/crypto/dh.h | 1 + providers/implementations/keymgmt/dh_kmgmt.c | 55 ++++++++++++++++++-- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index f959c0dd88d..8b742e67ba9 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -150,6 +150,11 @@ int DH_up_ref(DH *r) return ((i > 1) ? 1 : 0); } +OSSL_LIB_CTX *ossl_dh_get0_libctx(const DH *dh) +{ + return dh->libctx; +} + void ossl_dh_set0_libctx(DH *d, OSSL_LIB_CTX *libctx) { d->libctx = libctx; diff --git a/include/crypto/dh.h b/include/crypto/dh.h index 66dab801b9c..93a918fae24 100644 --- a/include/crypto/dh.h +++ b/include/crypto/dh.h @@ -18,6 +18,7 @@ DH *ossl_dh_new_by_nid_ex(OSSL_LIB_CTX *libctx, int nid); DH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx); +OSSL_LIB_CTX *ossl_dh_get0_libctx(const DH *dh); void ossl_dh_set0_libctx(DH *d, OSSL_LIB_CTX *libctx); int ossl_dh_generate_ffc_parameters(DH *dh, int type, int pbits, int qbits, BN_GENCB *cb); diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index de42ee85335..df42a7d1408 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -27,6 +27,8 @@ #include "crypto/dh.h" #include "internal/fips.h" #include "internal/sizes.h" +#include "internal/threads_common.h" +#include "internal/cryptlib.h" static OSSL_FUNC_keymgmt_new_fn dh_newdata; static OSSL_FUNC_keymgmt_free_fn dh_freedata; @@ -99,17 +101,51 @@ static int dh_gen_type_name2id_w_default(const char *name, int type) return ossl_dh_gen_type_name2id(name, type); } +/* + * If the application actually created a legacy DH object and assigned it to + * the EVP_PKEY, then we get hold of that object here. We return 0 if we hit + * a fatal error or 1 otherwise. We may return 1 but with *dh set to NULL. + */ +static int get_legacy_dh_object(OSSL_LIB_CTX *libctx, DH **dh) +{ +#ifndef FIPS_MODULE + /* + * This only works because we are in the default provider. We are not + * normally allowed to pass complex objects across the provider boundary + * like this. + */ + *dh = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_LOW_LEVEL_OBJECT, libctx); + if (*dh != NULL) { + if (ossl_lib_ctx_get_concrete(ossl_dh_get0_libctx(*dh)) != ossl_lib_ctx_get_concrete(libctx)) { + *dh = NULL; + return 1; + } + if (!DH_up_ref(*dh)) + return 0; + } +#endif + + return 1; +} + static void *dh_newdata(void *provctx) { DH *dh = NULL; - if (ossl_prov_is_running()) { + if (!ossl_prov_is_running()) + return NULL; + + if (!get_legacy_dh_object(PROV_LIBCTX_OF(provctx), &dh)) + return NULL; + + if (dh == NULL) { dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx)); if (dh != NULL) { DH_clear_flags(dh, DH_FLAG_TYPE_MASK); DH_set_flags(dh, DH_FLAG_TYPE_DH); } } + return dh; } @@ -117,11 +153,20 @@ static void *dhx_newdata(void *provctx) { DH *dh = NULL; - dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx)); - if (dh != NULL) { - DH_clear_flags(dh, DH_FLAG_TYPE_MASK); - DH_set_flags(dh, DH_FLAG_TYPE_DHX); + if (!ossl_prov_is_running()) + return NULL; + + if (!get_legacy_dh_object(PROV_LIBCTX_OF(provctx), &dh)) + return NULL; + + if (dh == NULL) { + dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx)); + if (dh != NULL) { + DH_clear_flags(dh, DH_FLAG_TYPE_MASK); + DH_set_flags(dh, DH_FLAG_TYPE_DHX); + } } + return dh; } -- 2.47.3