diff options
author | Tomas Mraz <tomas@openssl.org> | 2021-04-07 19:35:13 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2021-04-15 09:19:39 +0200 |
commit | 4a9fe33c8e12f4fefae0471c0834f8e674dc7e4e (patch) | |
tree | 479171af7347523257b843893173927cbbc6e572 /crypto | |
parent | b9cd82f95bf99eab4e1b0420918e7139db091c4b (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.c | 42 | ||||
-rw-r--r-- | crypto/dh/dh_backend.c | 44 | ||||
-rw-r--r-- | crypto/dh/dh_lib.c | 2 | ||||
-rw-r--r-- | crypto/dsa/dsa_ameth.c | 41 | ||||
-rw-r--r-- | crypto/dsa/dsa_backend.c | 44 | ||||
-rw-r--r-- | crypto/dsa/dsa_lib.c | 1 | ||||
-rw-r--r-- | crypto/ec/ecx_backend.c | 43 | ||||
-rw-r--r-- | crypto/ec/ecx_key.c | 3 | ||||
-rw-r--r-- | crypto/ec/ecx_meth.c | 14 | ||||
-rw-r--r-- | crypto/evp/evp_local.h | 1 | ||||
-rw-r--r-- | crypto/evp/keymgmt_lib.c | 6 | ||||
-rw-r--r-- | crypto/evp/keymgmt_meth.c | 12 | ||||
-rw-r--r-- | crypto/evp/p_lib.c | 2 | ||||
-rw-r--r-- | crypto/rsa/rsa_ameth.c | 94 | ||||
-rw-r--r-- | crypto/rsa/rsa_backend.c | 95 |
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) { |