diff options
Diffstat (limited to 'crypto/rsa/rsa_backend.c')
-rw-r--r-- | crypto/rsa/rsa_backend.c | 95 |
1 files changed, 95 insertions, 0 deletions
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) { |