]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Implement provider-side keymgmt_dup function
authorTomas Mraz <tomas@openssl.org>
Wed, 7 Apr 2021 17:35:13 +0000 (19:35 +0200)
committerTomas Mraz <tomas@openssl.org>
Thu, 15 Apr 2021 07:19:39 +0000 (09:19 +0200)
To avoid mutating key data add OSSL_FUNC_KEYMGMT_DUP function
to the provider API and implement it for all asym-key key
managements.

Use it when copying everything to an empty EVP_PKEY
which is the case with EVP_PKEY_dup().

Fixes #14658

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/14793)

27 files changed:
crypto/dh/dh_ameth.c
crypto/dh/dh_backend.c
crypto/dh/dh_lib.c
crypto/dsa/dsa_ameth.c
crypto/dsa/dsa_backend.c
crypto/dsa/dsa_lib.c
crypto/ec/ecx_backend.c
crypto/ec/ecx_key.c
crypto/ec/ecx_meth.c
crypto/evp/evp_local.h
crypto/evp/keymgmt_lib.c
crypto/evp/keymgmt_meth.c
crypto/evp/p_lib.c
crypto/rsa/rsa_ameth.c
crypto/rsa/rsa_backend.c
doc/man7/provider-keymgmt.pod
include/crypto/dh.h
include/crypto/dsa.h
include/crypto/ecx.h
include/crypto/evp.h
include/crypto/rsa.h
include/openssl/core_dispatch.h
providers/implementations/keymgmt/dh_kmgmt.c
providers/implementations/keymgmt/dsa_kmgmt.c
providers/implementations/keymgmt/ec_kmgmt.c
providers/implementations/keymgmt/ecx_kmgmt.c
providers/implementations/keymgmt/rsa_kmgmt.c

index 907a867ecac2174c89c28ed1fd9cbceab855a22b..1e72561d253f2a20ed98b358f5f06f32d50688f9 100644 (file)
@@ -536,46 +536,6 @@ static int dhx_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
     return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DHX);
 }
 
-static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f)
-{
-    if (f != NULL && (*out = BN_dup(f)) == NULL)
-        return 0;
-    return 1;
-}
-
-static DH *dh_dup(const DH *dh)
-{
-    DH *dupkey = NULL;
-
-    /* Do not try to duplicate foreign DH keys */
-    if (ossl_dh_get_method(dh) != DH_OpenSSL())
-        return NULL;
-
-    if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL)
-        return NULL;
-
-    dupkey->length = DH_get_length(dh);
-    if (!ossl_ffc_params_copy(&dupkey->params, &dh->params))
-        goto err;
-
-    dupkey->flags = dh->flags;
-
-    if (!dh_bn_dup_check(&dupkey->pub_key, dh->pub_key))
-        goto err;
-    if (!dh_bn_dup_check(&dupkey->priv_key, dh->priv_key))
-        goto err;
-
-    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH,
-                            &dupkey->ex_data, &dh->ex_data))
-        goto err;
-
-    return dupkey;
-
- err:
-    DH_free(dupkey);
-    return NULL;
-}
-
 static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
 {
     DH *dh = from->pkey.dh;
@@ -583,7 +543,7 @@ static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
     int ret;
 
     if (dh != NULL) {
-        dupkey = dh_dup(dh);
+        dupkey = ossl_dh_dup(dh);
         if (dupkey == NULL)
             return 0;
     }
index 97f5271a5ad2f47fe7699827e555e8296bdd0200..aebb38d1c9d9478f8c3fbe51c0bbce523d2bb82b 100644 (file)
@@ -17,6 +17,7 @@
 #include <openssl/core_names.h>
 #include "internal/param_build_set.h"
 #include "crypto/dh.h"
+#include "dh_local.h"
 
 /*
  * The intention with the "backend" source file is to offer backend functions
@@ -117,6 +118,49 @@ int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
     return 1;
 }
 
+static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f)
+{
+    if (f != NULL && (*out = BN_dup(f)) == NULL)
+        return 0;
+    return 1;
+}
+
+DH *ossl_dh_dup(const DH *dh)
+{
+    DH *dupkey = NULL;
+
+#ifndef FIPS_MODULE
+    /* Do not try to duplicate foreign DH keys */
+    if (ossl_dh_get_method(dh) != DH_OpenSSL())
+        return NULL;
+#endif
+
+    if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL)
+        return NULL;
+
+    dupkey->length = DH_get_length(dh);
+    if (!ossl_ffc_params_copy(&dupkey->params, &dh->params))
+        goto err;
+
+    dupkey->flags = dh->flags;
+
+    if (!dh_bn_dup_check(&dupkey->pub_key, dh->pub_key))
+        goto err;
+    if (!dh_bn_dup_check(&dupkey->priv_key, dh->priv_key))
+        goto err;
+
+#ifndef FIPS_MODULE
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH,
+                            &dupkey->ex_data, &dh->ex_data))
+        goto err;
+#endif
+
+    return dupkey;
+
+ err:
+    DH_free(dupkey);
+    return NULL;
+}
 #ifndef FIPS_MODULE
 DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
                            OSSL_LIB_CTX *libctx, const char *propq)
index f5e0f893c18b33c48ebf7323049103edf2c8337b..92767a94c222a3575c65c1fca00d2507f0cc919b 100644 (file)
@@ -325,3 +325,5 @@ int ossl_dh_get0_nid(const DH *dh)
 {
     return dh->params.nid;
 }
+
+
index 69964c053cb4d185ff29dedfd77b327af78021d4..0844e9be09755f1318ae1c67dba403a59019c523 100644 (file)
@@ -500,45 +500,6 @@ static int dsa_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
     return 1;
 }
 
-static ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
-{
-    if (f != NULL && (*out = BN_dup(f)) == NULL)
-        return 0;
-    return 1;
-}
-
-static DSA *dsa_dup(const DSA *dsa)
-{
-    DSA *dupkey = NULL;
-
-    /* Do not try to duplicate foreign DSA keys */
-    if (DSA_get_method((DSA *)dsa) != DSA_OpenSSL())
-        return NULL;
-
-    if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL)
-        return NULL;
-
-    if (!ossl_ffc_params_copy(&dupkey->params, &dsa->params))
-        goto err;
-
-    dupkey->flags = dsa->flags;
-
-    if (!dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key))
-        goto err;
-    if (!dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key))
-        goto err;
-
-    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA,
-                            &dupkey->ex_data, &dsa->ex_data))
-        goto err;
-
-    return dupkey;
-
- err:
-    DSA_free(dupkey);
-    return NULL;
-}
-
 static int dsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
 {
     DSA *dsa = from->pkey.dsa;
@@ -546,7 +507,7 @@ static int dsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
     int ret;
 
     if (dsa != NULL) {
-        dupkey = dsa_dup(dsa);
+        dupkey = ossl_dsa_dup(dsa);
         if (dupkey == NULL)
             return 0;
     }
index f3e54aeb131b0d922419bf6cc58c5c5ebcdc957e..856203a200255aa403623e978d71524ab2be1cb2 100644 (file)
@@ -16,6 +16,7 @@
 #include <openssl/core_names.h>
 #include <openssl/err.h>
 #include "crypto/dsa.h"
+#include "dsa_local.h"
 
 /*
  * The intention with the "backend" source file is to offer backend support
@@ -56,6 +57,49 @@ int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[])
     return 0;
 }
 
+static ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
+{
+    if (f != NULL && (*out = BN_dup(f)) == NULL)
+        return 0;
+    return 1;
+}
+
+DSA *ossl_dsa_dup(const DSA *dsa)
+{
+    DSA *dupkey = NULL;
+
+#ifndef FIPS_MODULE
+    /* Do not try to duplicate foreign DSA keys */
+    if (DSA_get_method((DSA *)dsa) != DSA_OpenSSL())
+        return NULL;
+#endif
+
+    if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL)
+        return NULL;
+
+    if (!ossl_ffc_params_copy(&dupkey->params, &dsa->params))
+        goto err;
+
+    dupkey->flags = dsa->flags;
+
+    if (!dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key))
+        goto err;
+    if (!dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key))
+        goto err;
+
+#ifndef FIPS_MODULE
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA,
+                            &dupkey->ex_data, &dsa->ex_data))
+        goto err;
+#endif
+
+    return dupkey;
+
+ err:
+    DSA_free(dupkey);
+    return NULL;
+}
+
 #ifndef FIPS_MODULE
 DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
                              OSSL_LIB_CTX *libctx, const char *propq)
index 5512b99ef100799defc97238670dfa7227ec1154..f39c2aa21a893a3b57321e475569c3c7ca949fb6 100644 (file)
@@ -358,3 +358,4 @@ int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[])
         dsa->dirty_cnt++;
     return ret;
 }
+
index 8f8fdc7705b8ff16bc94d4fce96528cc87436967..d3ffb13916ced8f07ae44227a699a7d78421277e 100644 (file)
@@ -92,6 +92,49 @@ int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
     return 1;
 }
 
+ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key)
+{
+    ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
+
+    if (ret == NULL) {
+        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    ret->lock = CRYPTO_THREAD_lock_new();
+    if (ret->lock == NULL) {
+        OPENSSL_free(ret);
+        return NULL;
+    }
+
+    ret->libctx = key->libctx;
+    ret->haspubkey = key->haspubkey;
+    ret->keylen = key->keylen;
+    ret->type = key->type;
+    ret->references = 1;
+
+    if (key->propq != NULL) {
+        ret->propq = OPENSSL_strdup(key->propq);
+        if (ret->propq == NULL)
+            goto err;
+    }
+
+    memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey));
+
+    if (key->privkey != NULL) {
+        if (ossl_ecx_key_allocate_privkey(ret) == NULL)
+            goto err;
+        memcpy(ret->privkey, key->privkey, ret->keylen);
+    }
+
+    return ret;
+
+err:
+    ossl_ecx_key_free(ret);
+    ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+    return NULL;
+}
+
 #ifndef FIPS_MODULE
 ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg,
                          const unsigned char *p, int plen,
index 60d9f3cc9fd4c8763b7cbdcdec1bd5cfb94a194d..90253372cecfa714c287d5b16c3417a02f08b482 100644 (file)
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <string.h>
 #include <openssl/err.h>
 #include "crypto/ecx.h"
 
@@ -39,7 +40,6 @@ ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey
 
     if (propq != NULL) {
         ret->propq = OPENSSL_strdup(propq);
-        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
         if (ret->propq == NULL)
             goto err;
     }
@@ -96,3 +96,4 @@ unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key)
 
     return key->privkey;
 }
+
index 609d8609ea27f0d208e38070f55a3d1df1817a99..df4b620829976d73ecc4f08e9914540a9037d2ea 100644 (file)
@@ -406,16 +406,18 @@ static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
 
 static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
 {
-    ECX_KEY *ecx = from->pkey.ecx;
+    ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
     int ret;
 
-    /* We can do just up-ref as ECX keys are immutable */
-    if (ecx != NULL && !ossl_ecx_key_up_ref(ecx))
-        return 0;
+    if (ecx != NULL) {
+        dupkey = ossl_ecx_key_dup(ecx);
+        if (dupkey == NULL)
+            return 0;
+    }
 
-    ret = EVP_PKEY_assign(to, from->type, ecx);
+    ret = EVP_PKEY_assign(to, from->type, dupkey);
     if (!ret)
-        ossl_ecx_key_free(ecx);
+        ossl_ecx_key_free(dupkey);
     return ret;
 }
 
index 72caf86aafb53b3d519a3e9b57eae3a56f515846..1b92668a20dd87373267f8d2d6d301fc1352a79b 100644 (file)
@@ -113,6 +113,7 @@ struct evp_keymgmt_st {
     OSSL_FUNC_keymgmt_export_fn *export;
     OSSL_FUNC_keymgmt_export_types_fn *export_types;
     OSSL_FUNC_keymgmt_copy_fn *copy;
+    OSSL_FUNC_keymgmt_dup_fn *dup;
 } /* EVP_KEYMGMT */ ;
 
 struct evp_keyexch_st {
index 872a63ae4743fe85f55138676256d7f4353f0a64..ed9fb0db036a9e70fa58c97f11768430ff6f5202 100644 (file)
@@ -459,6 +459,12 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection)
             evp_keymgmt_freedata(to_keymgmt, alloc_keydata);
             return 0;
         }
+    } else if (to_keymgmt == from->keymgmt && to_keymgmt->dup != NULL
+               && to_keydata == NULL
+               && selection == OSSL_KEYMGMT_SELECT_ALL) {
+        to_keydata = alloc_keydata = evp_keymgmt_dup(to_keymgmt, from->keydata);
+        if (to_keydata == NULL)
+            return 0;
     } else if (match_type(to_keymgmt, from->keymgmt)) {
         struct evp_keymgmt_util_try_import_data_st import_data;
 
index cdd7c70ed910063edf3921f4372bf8505378b789..a1629bc37fd1506f2e37b0fb2428892eeaece372 100644 (file)
@@ -133,6 +133,10 @@ static void *keymgmt_from_algorithm(int name_id,
             if (keymgmt->copy == NULL)
                 keymgmt->copy = OSSL_FUNC_keymgmt_copy(fns);
             break;
+        case OSSL_FUNC_KEYMGMT_DUP:
+            if (keymgmt->dup == NULL)
+                keymgmt->dup = OSSL_FUNC_keymgmt_dup(fns);
+            break;
         case OSSL_FUNC_KEYMGMT_VALIDATE:
             if (keymgmt->validate == NULL)
                 keymgmt->validate = OSSL_FUNC_keymgmt_validate(fns);
@@ -472,3 +476,11 @@ int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt,
         return 0;
     return keymgmt->copy(keydata_to, keydata_from, selection);
 }
+
+void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from)
+{
+    /* We assume no dup if the implementation doesn't have a function */
+    if (keymgmt->dup == NULL)
+        return NULL;
+    return keymgmt->dup(keydata_from);
+}
index 0fc3af494f44d40e6333777fedd18d0083506059..04d9c80bd3a62bc9721686457884194b15d1f57e 100644 (file)
@@ -1857,7 +1857,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
 
         /* Synchronize the dirty count */
         pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
-    
+
         CRYPTO_THREAD_unlock(pk->lock);
         goto end;
     }
index e633fa5c9347a85a76c7e068f593d28702c60a4a..45e0000117fb7ba035d0efaaf3a79de93b580c1b 100644 (file)
@@ -884,98 +884,6 @@ static int rsa_pss_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
     return rsa_int_import_from(params, vpctx, RSA_FLAG_TYPE_RSASSAPSS);
 }
 
-static ossl_inline int rsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
-{
-    if (f != NULL && (*out = BN_dup(f)) == NULL)
-        return 0;
-    return 1;
-}
-
-static RSA *rsa_dup(const RSA *rsa)
-{
-    RSA *dupkey = NULL;
-    int pnum, i;
-
-    /* Do not try to duplicate foreign RSA keys */
-    if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL())
-        return NULL;
-
-    if ((dupkey = ossl_rsa_new_with_ctx(rsa->libctx)) == NULL)
-        return NULL;
-
-    /* private and public key */
-    if (!rsa_bn_dup_check(&dupkey->n, rsa->n))
-        goto err;
-    if (!rsa_bn_dup_check(&dupkey->e, rsa->e))
-        goto err;
-    if (!rsa_bn_dup_check(&dupkey->d, rsa->d))
-        goto err;
-
-    /* factors and crt params */
-    if (!rsa_bn_dup_check(&dupkey->p, rsa->p))
-        goto err;
-    if (!rsa_bn_dup_check(&dupkey->q, rsa->q))
-        goto err;
-    if (!rsa_bn_dup_check(&dupkey->dmp1, rsa->dmp1))
-        goto err;
-    if (!rsa_bn_dup_check(&dupkey->dmq1, rsa->dmq1))
-        goto err;
-    if (!rsa_bn_dup_check(&dupkey->iqmp, rsa->iqmp))
-        goto err;
-
-    /* multiprime */
-    pnum = sk_RSA_PRIME_INFO_num(rsa->prime_infos);
-    if (pnum > 0) {
-        dupkey->prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
-        for (i = 0; i < pnum; i++) {
-            const RSA_PRIME_INFO *pinfo = NULL;
-            RSA_PRIME_INFO *duppinfo = NULL;
-
-            if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) {
-                ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
-                goto err;
-            }
-            /* push first so cleanup in error case works */
-            (void)sk_RSA_PRIME_INFO_push(dupkey->prime_infos, duppinfo);
-
-            pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
-            if (!rsa_bn_dup_check(&duppinfo->r, pinfo->r))
-                goto err;
-            if (!rsa_bn_dup_check(&duppinfo->d, pinfo->d))
-                goto err;
-            if (!rsa_bn_dup_check(&duppinfo->t, pinfo->t))
-                goto err;
-        }
-        if (!ossl_rsa_multip_calc_product(dupkey))
-            goto err;
-    }
-
-    dupkey->version = rsa->version;
-    dupkey->flags = rsa->flags;
-
-    dupkey->pss_params = rsa->pss_params;
-
-    if (rsa->pss != NULL) {
-        dupkey->pss = RSA_PSS_PARAMS_dup(rsa->pss);
-        if (rsa->pss->maskGenAlgorithm != NULL
-            && dupkey->pss->maskGenAlgorithm == NULL) {
-            dupkey->pss->maskHash = ossl_x509_algor_mgf1_decode(rsa->pss->maskGenAlgorithm);
-            if (dupkey->pss->maskHash == NULL)
-                goto err;
-        }
-    }
-
-    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA,
-                            &dupkey->ex_data, &rsa->ex_data))
-        goto err;
-
-    return dupkey;
-
- err:
-    RSA_free(dupkey);
-    return NULL;
-}
-
 static int rsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
 {
     RSA *rsa = from->pkey.rsa;
@@ -983,7 +891,7 @@ static int rsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
     int ret;
 
     if (rsa != NULL) {
-        dupkey = rsa_dup(rsa);
+        dupkey = ossl_rsa_dup(rsa);
         if (dupkey == NULL)
             return 0;
     }
index 01ee87505891b3a2ff93fb2e8654e62ced76bab9..92be5f610ad3ee67ea00b21d6cab6f697dd84095 100644 (file)
@@ -22,6 +22,7 @@
 #include "internal/param_build_set.h"
 #include "crypto/asn1.h"
 #include "crypto/rsa.h"
+#include "rsa_local.h"
 
 #include "e_os.h"                /* strcasecmp for Windows() */
 
@@ -322,6 +323,100 @@ int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
     return ret;
 }
 
+static ossl_inline int rsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
+{
+    if (f != NULL && (*out = BN_dup(f)) == NULL)
+        return 0;
+    return 1;
+}
+
+RSA *ossl_rsa_dup(const RSA *rsa)
+{
+    RSA *dupkey = NULL;
+#ifndef FIPS_MODULE
+    int pnum, i;
+
+    /* Do not try to duplicate foreign RSA keys */
+    if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL())
+        return NULL;
+#endif
+
+    if ((dupkey = ossl_rsa_new_with_ctx(rsa->libctx)) == NULL)
+        return NULL;
+
+    /* private and public key */
+    if (!rsa_bn_dup_check(&dupkey->n, rsa->n))
+        goto err;
+    if (!rsa_bn_dup_check(&dupkey->e, rsa->e))
+        goto err;
+    if (!rsa_bn_dup_check(&dupkey->d, rsa->d))
+        goto err;
+
+    /* factors and crt params */
+    if (!rsa_bn_dup_check(&dupkey->p, rsa->p))
+        goto err;
+    if (!rsa_bn_dup_check(&dupkey->q, rsa->q))
+        goto err;
+    if (!rsa_bn_dup_check(&dupkey->dmp1, rsa->dmp1))
+        goto err;
+    if (!rsa_bn_dup_check(&dupkey->dmq1, rsa->dmq1))
+        goto err;
+    if (!rsa_bn_dup_check(&dupkey->iqmp, rsa->iqmp))
+        goto err;
+
+    dupkey->version = rsa->version;
+    dupkey->flags = rsa->flags;
+    dupkey->pss_params = rsa->pss_params;
+
+#ifndef FIPS_MODULE
+    /* multiprime */
+    pnum = sk_RSA_PRIME_INFO_num(rsa->prime_infos);
+    if (pnum > 0) {
+        dupkey->prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
+        for (i = 0; i < pnum; i++) {
+            const RSA_PRIME_INFO *pinfo = NULL;
+            RSA_PRIME_INFO *duppinfo = NULL;
+
+            if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) {
+                ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            /* push first so cleanup in error case works */
+            (void)sk_RSA_PRIME_INFO_push(dupkey->prime_infos, duppinfo);
+
+            pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
+            if (!rsa_bn_dup_check(&duppinfo->r, pinfo->r))
+                goto err;
+            if (!rsa_bn_dup_check(&duppinfo->d, pinfo->d))
+                goto err;
+            if (!rsa_bn_dup_check(&duppinfo->t, pinfo->t))
+                goto err;
+        }
+        if (!ossl_rsa_multip_calc_product(dupkey))
+            goto err;
+    }
+
+    if (rsa->pss != NULL) {
+        dupkey->pss = RSA_PSS_PARAMS_dup(rsa->pss);
+        if (rsa->pss->maskGenAlgorithm != NULL
+            && dupkey->pss->maskGenAlgorithm == NULL) {
+            dupkey->pss->maskHash = ossl_x509_algor_mgf1_decode(rsa->pss->maskGenAlgorithm);
+            if (dupkey->pss->maskHash == NULL)
+                goto err;
+        }
+    }
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA,
+                            &dupkey->ex_data, &rsa->ex_data))
+        goto err;
+#endif
+
+    return dupkey;
+
+ err:
+    RSA_free(dupkey);
+    return NULL;
+}
+
 #ifndef FIPS_MODULE
 RSA_PSS_PARAMS *ossl_rsa_pss_decode(const X509_ALGOR *alg)
 {
index 9a11b316c2b3df9178d17a6cd92a99f47de856bc..2937d915b9cbabcd42358685072d47a1c952e936 100644 (file)
@@ -55,6 +55,9 @@ provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions
  /* Key object copy */
  int OSSL_FUNC_keymgmt_copy(void *keydata_to, const void *keydata_from, int selection);
 
+ /* Key object duplication, a constructor */
+ void *OSSL_FUNC_keymgmt_dup(const void *keydata_from);
+
  /* Key object validation */
  int OSSL_FUNC_keymgmt_validate(const void *keydata, int selection, int checktype);
 
@@ -119,6 +122,7 @@ macros in L<openssl-core_dispatch.h(7)>, as follows:
  OSSL_FUNC_keymgmt_export_types         OSSL_FUNC_KEYMGMT_EXPORT_TYPES
 
  OSSL_FUNC_keymgmt_copy                 OSSL_FUNC_KEYMGMT_COPY
+ OSSL_FUNC_keymgmt_dup                  OSSL_FUNC_KEYMGMT_DUP
 
 =head2 Key Objects
 
@@ -342,6 +346,9 @@ from I<keydata_from> to I<keydata_to>.  It is assumed that the caller
 has ensured that I<keydata_to> and I<keydata_from> are both owned by
 the implementation of this function.
 
+OSSL_FUNC_keymgmt_dup() should duplicate the key data I<keydata_from> and
+create a new provider side key object with the data.
+
 =head2 Common Information Parameters
 
 See L<OSSL_PARAM(3)> for further details on the parameters structure.
@@ -379,8 +386,8 @@ Bits of security is defined in SP800-57.
 
 =head1 RETURN VALUES
 
-OSSL_FUNC_keymgmt_new() should return a valid reference to the newly created provider
-side key object, or NULL on failure.
+OSSL_FUNC_keymgmt_new() and OSSL_FUNC_keymgmt_dup() should return a valid
+reference to the newly created provider side key object, or NULL on failure.
 
 OSSL_FUNC_keymgmt_import(), OSSL_FUNC_keymgmt_export(), OSSL_FUNC_keymgmt_get_params() and
 OSSL_FUNC_keymgmt_set_params() should return 1 for success or 0 on error.
index ab6115d9861be41edb291432b322e7c64f76285c..8d5908549b4b9d96c999da4ff0347f05e0355611 100644 (file)
@@ -56,5 +56,6 @@ int ossl_dh_kdf_X9_42_asn1(unsigned char *out, size_t outlen,
                            const unsigned char *ukm, size_t ukmlen,
                            const EVP_MD *md,
                            OSSL_LIB_CTX *libctx, const char *propq);
+DH *ossl_dh_dup(const DH *dh);
 
 #endif  /* OSSL_CRYPTO_DH_H */
index 38c49c3295f738ebd8609fd14421afe9e34786d4..4fad9ab73ed1c5e94d1bc9c968d6368dc39d90b1 100644 (file)
@@ -43,5 +43,6 @@ int ossl_dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key,
                                    int *ret);
 int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret);
 int ossl_dsa_check_pairwise(const DSA *dsa);
+DSA *ossl_dsa_dup(const DSA *dsa);
 
 #endif
index 656ee94f0910574ab4015ed382958125439c89f0..fcb0bbde0fe5fdde6749d4347ab2e0974e54de85 100644 (file)
@@ -83,6 +83,7 @@ void ossl_ecx_key_set0_libctx(ECX_KEY *key, OSSL_LIB_CTX *libctx);
 unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key);
 void ossl_ecx_key_free(ECX_KEY *key);
 int ossl_ecx_key_up_ref(ECX_KEY *key);
+ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key);
 
 int ossl_x25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
                 const uint8_t peer_public_value[32]);
index 8ea5a2bf3583ad0aae6d09ca81186059db6d1d40..5f48d38f985023f0ddcdd66b4aaecc6f8739c805 100644 (file)
@@ -813,6 +813,8 @@ const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
 int evp_keymgmt_copy(const EVP_KEYMGMT *keymgmt,
                      void *keydata_to, const void *keydata_from,
                      int selection);
+void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt,
+                      const void *keydata_from);
 
 /* Pulling defines out of C source files */
 
index 73bf03f6158cb3716e91c72461361a742e1f2689..8c6ce49a7d67466df81049ebaccdd229b7fc23a0 100644 (file)
@@ -63,6 +63,7 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
 int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
                              STACK_OF(BIGNUM_const) *exps,
                              STACK_OF(BIGNUM_const) *coeffs);
+RSA *ossl_rsa_dup(const RSA *rsa);
 
 int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
 int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]);
index 1cc2ebcc57d125a419a3613ec741f5ccbb6d9dfa..46278b4af6c9b73d5e38493701d4bebf1494aa77 100644 (file)
@@ -598,8 +598,12 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_export_types,
 /* Copy function, only works for matching keymgmt */
 # define OSSL_FUNC_KEYMGMT_COPY                       44
 OSSL_CORE_MAKE_FUNC(int, keymgmt_copy,
-                    ( void *keydata_to, const void *keydata_from,
+                    (void *keydata_to, const void *keydata_from,
                      int selection))
+/* Dup function, constructor */
+# define OSSL_FUNC_KEYMGMT_DUP                        45
+OSSL_CORE_MAKE_FUNC(void *, keymgmt_dup,
+                    (const void *keydata_from))
 
 /* Key Exchange */
 
index ba56abe04a90b423265d41b6eea3f4b18344530a..f7b10a1d0015e363ec934082ffe7f96f99dde5b0 100644 (file)
@@ -45,6 +45,7 @@ static OSSL_FUNC_keymgmt_import_fn dh_import;
 static OSSL_FUNC_keymgmt_import_types_fn dh_import_types;
 static OSSL_FUNC_keymgmt_export_fn dh_export;
 static OSSL_FUNC_keymgmt_export_types_fn dh_export_types;
+static OSSL_FUNC_keymgmt_dup_fn dh_dup;
 
 #define DH_POSSIBLE_SELECTIONS                                                 \
     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
@@ -707,7 +708,7 @@ static void dh_gen_cleanup(void *genctx)
     OPENSSL_free(gctx);
 }
 
-void *dh_load(const void *reference, size_t reference_sz)
+static void *dh_load(const void *reference, size_t reference_sz)
 {
     DH *dh = NULL;
 
@@ -721,6 +722,13 @@ void *dh_load(const void *reference, size_t reference_sz)
     return NULL;
 }
 
+static void *dh_dup(const void *keydata_from)
+{
+    if (ossl_prov_is_running())
+        return ossl_dh_dup(keydata_from);
+    return NULL;
+}
+
 const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init },
@@ -743,6 +751,7 @@ const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
+    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },
     { 0, NULL }
 };
 
@@ -776,5 +785,6 @@ const OSSL_DISPATCH ossl_dhx_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
       (void (*)(void))dhx_query_operation_name },
+    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },
     { 0, NULL }
 };
index 15a40df26083f83da52d30999c719f0f493dbac3..0d3b6ae36c92abe9a705e54a650785763217c6f4 100644 (file)
@@ -44,6 +44,7 @@ static OSSL_FUNC_keymgmt_import_fn dsa_import;
 static OSSL_FUNC_keymgmt_import_types_fn dsa_import_types;
 static OSSL_FUNC_keymgmt_export_fn dsa_export;
 static OSSL_FUNC_keymgmt_export_types_fn dsa_export_types;
+static OSSL_FUNC_keymgmt_dup_fn dsa_dup;
 
 #define DSA_DEFAULT_MD "SHA256"
 #define DSA_POSSIBLE_SELECTIONS                                                \
@@ -597,7 +598,7 @@ static void dsa_gen_cleanup(void *genctx)
     OPENSSL_free(gctx);
 }
 
-void *dsa_load(const void *reference, size_t reference_sz)
+static void *dsa_load(const void *reference, size_t reference_sz)
 {
     DSA *dsa = NULL;
 
@@ -611,6 +612,13 @@ void *dsa_load(const void *reference, size_t reference_sz)
     return NULL;
 }
 
+static void *dsa_dup(const void *keydata_from)
+{
+    if (ossl_prov_is_running())
+        return ossl_dsa_dup(keydata_from);
+    return NULL;
+}
+
 const OSSL_DISPATCH ossl_dsa_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata },
     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dsa_gen_init },
@@ -631,5 +639,6 @@ const OSSL_DISPATCH ossl_dsa_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dsa_export_types },
+    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dsa_dup },
     { 0, NULL }
 };
index fe5bd7a28a0c673900c8b0b4538cc01d31707ea8..c525ffc81a0b698535e0ce314681f91bb338511f 100644 (file)
@@ -55,6 +55,7 @@ static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;
 static OSSL_FUNC_keymgmt_export_fn ec_export;
 static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
 static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
+static OSSL_FUNC_keymgmt_dup_fn ec_dup;
 #ifndef FIPS_MODULE
 # ifndef OPENSSL_NO_SM2
 static OSSL_FUNC_keymgmt_new_fn sm2_newdata;
@@ -1361,6 +1362,13 @@ static void *sm2_load(const void *reference, size_t reference_sz)
 # endif
 #endif
 
+static void *ec_dup(const void *keydata_from)
+{
+    if (ossl_prov_is_running())
+        return EC_KEY_dup(keydata_from);
+    return NULL;
+}
+
 const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
@@ -1386,6 +1394,7 @@ const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
       (void (*)(void))ec_query_operation_name },
+    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
     { 0, NULL }
 };
 
@@ -1416,6 +1425,7 @@ const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
       (void (*)(void))sm2_query_operation_name },
+    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
     { 0, NULL }
 };
 # endif
index a0284325cc3a2563d6a829ecc84e92a003e72b83..e072cdc851e53d74ef406a9e22410cc163955013 100644 (file)
@@ -71,6 +71,7 @@ static OSSL_FUNC_keymgmt_import_fn ecx_import;
 static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
 static OSSL_FUNC_keymgmt_export_fn ecx_export;
 static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
+static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
 
 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
 
@@ -691,6 +692,13 @@ void *ecx_load(const void *reference, size_t reference_sz)
     return NULL;
 }
 
+static void *ecx_dup(const void *keydata_from)
+{
+    if (ossl_prov_is_running())
+        return ossl_ecx_key_dup(keydata_from);
+    return NULL;
+}
+
 static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
 {
     uint8_t pub[64];
@@ -788,6 +796,7 @@ static int ed448_validate(const void *keydata, int selection, int checktype)
         { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
         { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
         { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
+        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
         { 0, NULL } \
     };
 
index fbd99e3dc8bc4fbe5bdaa3fc581462684201b32f..5760d7650f94f3298b347b17bad414bc4fb6a8c8 100644 (file)
@@ -49,6 +49,7 @@ static OSSL_FUNC_keymgmt_import_types_fn rsa_import_types;
 static OSSL_FUNC_keymgmt_export_fn rsa_export;
 static OSSL_FUNC_keymgmt_export_types_fn rsa_export_types;
 static OSSL_FUNC_keymgmt_query_operation_name_fn rsa_query_operation_name;
+static OSSL_FUNC_keymgmt_dup_fn rsa_dup;
 
 #define RSA_DEFAULT_MD "SHA256"
 #define RSA_PSS_DEFAULT_MD OSSL_DIGEST_NAME_SHA1
@@ -645,6 +646,13 @@ static void *rsapss_load(const void *reference, size_t reference_sz)
     return common_load(reference, reference_sz, RSA_FLAG_TYPE_RSASSAPSS);
 }
 
+static void *rsa_dup(const void *keydata_from)
+{
+    if (ossl_prov_is_running())
+        return ossl_rsa_dup(keydata_from);
+    return NULL;
+}
+
 /* For any RSA key, we use the "RSA" algorithms regardless of sub-type. */
 static const char *rsa_query_operation_name(int operation_id)
 {
@@ -671,6 +679,7 @@ const OSSL_DISPATCH ossl_rsa_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export },
     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types },
+    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup },
     { 0, NULL }
 };
 
@@ -695,5 +704,6 @@ const OSSL_DISPATCH ossl_rsapss_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types },
     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
       (void (*)(void))rsa_query_operation_name },
+    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup },
     { 0, NULL }
 };