summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2021-04-07 19:35:13 +0200
committerTomas Mraz <tomas@openssl.org>2021-04-15 09:19:39 +0200
commit4a9fe33c8e12f4fefae0471c0834f8e674dc7e4e (patch)
tree479171af7347523257b843893173927cbbc6e572 /crypto
parentb9cd82f95bf99eab4e1b0420918e7139db091c4b (diff)
Implement provider-side keymgmt_dup function
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)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/dh/dh_ameth.c42
-rw-r--r--crypto/dh/dh_backend.c44
-rw-r--r--crypto/dh/dh_lib.c2
-rw-r--r--crypto/dsa/dsa_ameth.c41
-rw-r--r--crypto/dsa/dsa_backend.c44
-rw-r--r--crypto/dsa/dsa_lib.c1
-rw-r--r--crypto/ec/ecx_backend.c43
-rw-r--r--crypto/ec/ecx_key.c3
-rw-r--r--crypto/ec/ecx_meth.c14
-rw-r--r--crypto/evp/evp_local.h1
-rw-r--r--crypto/evp/keymgmt_lib.c6
-rw-r--r--crypto/evp/keymgmt_meth.c12
-rw-r--r--crypto/evp/p_lib.c2
-rw-r--r--crypto/rsa/rsa_ameth.c94
-rw-r--r--crypto/rsa/rsa_backend.c95
15 files changed, 262 insertions, 182 deletions
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index 907a867eca..1e72561d25 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -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;
}
diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c
index 97f5271a5a..aebb38d1c9 100644
--- a/crypto/dh/dh_backend.c
+++ b/crypto/dh/dh_backend.c
@@ -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)
diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c
index f5e0f893c1..92767a94c2 100644
--- a/crypto/dh/dh_lib.c
+++ b/crypto/dh/dh_lib.c
@@ -325,3 +325,5 @@ int ossl_dh_get0_nid(const DH *dh)
{
return dh->params.nid;
}
+
+
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
index 69964c053c..0844e9be09 100644
--- a/crypto/dsa/dsa_ameth.c
+++ b/crypto/dsa/dsa_ameth.c
@@ -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;
}
diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c
index f3e54aeb13..856203a200 100644
--- a/crypto/dsa/dsa_backend.c
+++ b/crypto/dsa/dsa_backend.c
@@ -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)
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
index 5512b99ef1..f39c2aa21a 100644
--- a/crypto/dsa/dsa_lib.c
+++ b/crypto/dsa/dsa_lib.c
@@ -358,3 +358,4 @@ int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[])
dsa->dirty_cnt++;
return ret;
}
+
diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c
index 8f8fdc7705..d3ffb13916 100644
--- a/crypto/ec/ecx_backend.c
+++ b/crypto/ec/ecx_backend.c
@@ -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,
diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c
index 60d9f3cc9f..90253372ce 100644
--- a/crypto/ec/ecx_key.c
+++ b/crypto/ec/ecx_key.c
@@ -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;
}
+
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index 609d8609ea..df4b620829 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -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;
}
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 72caf86aaf..1b92668a20 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -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 {
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index 872a63ae47..ed9fb0db03 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -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;
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index cdd7c70ed9..a1629bc37f 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -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);
+}
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 0fc3af494f..04d9c80bd3 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -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;
}
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index e633fa5c93..45e0000117 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -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;
}
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c
index 01ee875058..92be5f610a 100644
--- a/crypto/rsa/rsa_backend.c
+++ b/crypto/rsa/rsa_backend.c
@@ -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)
{