]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Pass low level DH objects to the default provider
authorMatt Caswell <matt@openssl.org>
Fri, 6 Feb 2026 15:06:51 +0000 (15:06 +0000)
committerTomas Mraz <tomas@openssl.org>
Fri, 13 Feb 2026 07:57:58 +0000 (08:57 +0100)
As we did for RSA objects we do the same for DH objects.

Fixes #29942

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
MergeDate: Fri Feb 13 07:58:25 2026
(Merged from https://github.com/openssl/openssl/pull/29960)

crypto/dh/dh_lib.c
include/crypto/dh.h
providers/implementations/keymgmt/dh_kmgmt.c

index f959c0dd88d4218e0d4337d7e6944f712de5d386..8b742e67ba9786701a82597fd12f82f4e64707e3 100644 (file)
@@ -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;
index 66dab801b9c88a308b28771cd6724c8a74b88b61..93a918fae24abdef2f97b94d6a6b142d87386b6c 100644 (file)
@@ -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);
index de42ee853358571f56f5910ef9f8b8e665e198f2..df42a7d1408ef52878b1a950e050a27841ac16f2 100644 (file)
@@ -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;
 }