diff options
Diffstat (limited to 'crypto/rsa/rsa_backend.c')
-rw-r--r-- | crypto/rsa/rsa_backend.c | 170 |
1 files changed, 152 insertions, 18 deletions
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index f9d1cb361d77..d6864dc237cd 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,7 +44,7 @@ static int collect_numbers(STACK_OF(BIGNUM) *numbers, if (numbers == NULL) return 0; - for (i = 0; names[i] != NULL; i++){ + for (i = 0; names[i] != NULL; i++) { p = OSSL_PARAM_locate_const(params, names[i]); if (p != NULL) { BIGNUM *tmp = NULL; @@ -64,22 +64,56 @@ static int collect_numbers(STACK_OF(BIGNUM) *numbers, int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private) { const OSSL_PARAM *param_n, *param_e, *param_d = NULL; - BIGNUM *n = NULL, *e = NULL, *d = NULL; + const OSSL_PARAM *param_p, *param_q = NULL; + const OSSL_PARAM *param_derive = NULL; + BIGNUM *p = NULL, *q = NULL, *n = NULL, *e = NULL, *d = NULL; STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL; int is_private = 0; + int derive_from_pq = 0; + BN_CTX *ctx = NULL; if (rsa == NULL) return 0; param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); - if (include_private) - param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); - if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n)) - || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e)) - || (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d))) + if ((param_n == NULL || !OSSL_PARAM_get_BN(param_n, &n)) + || (param_e == NULL || !OSSL_PARAM_get_BN(param_e, &e))) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); goto err; + } + + if (include_private) { + + param_derive = OSSL_PARAM_locate_const(params, + OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ); + if ((param_derive != NULL) + && !OSSL_PARAM_get_int(param_derive, &derive_from_pq)) + goto err; + + param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); + if (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d)) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + if (derive_from_pq) { + ctx = BN_CTX_new_ex(rsa->libctx); + if (ctx == NULL) + goto err; + + /* we need at minimum p, q */ + param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1); + param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2); + if ((param_p == NULL || !OSSL_PARAM_get_BN(param_p, &p)) + || (param_q == NULL || !OSSL_PARAM_get_BN(param_q, &q))) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + } + } is_private = (d != NULL); @@ -96,25 +130,127 @@ int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private) ossl_rsa_mp_coeff_names)) goto err; - /* It's ok if this private key just has n, e and d */ + if (derive_from_pq && sk_BIGNUM_num(exps) == 0 + && sk_BIGNUM_num(coeffs) == 0) { + /* + * If we want to use crt to derive our exponents/coefficients, we + * need to have at least 2 factors + */ + if (sk_BIGNUM_num(factors) < 2) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + /* + * if we have more than two factors, n and d must also have + * been provided + */ + if (sk_BIGNUM_num(factors) > 2 + && (param_n == NULL || param_d == NULL)) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + /* build our exponents and coefficients here */ + if (sk_BIGNUM_num(factors) == 2) { + /* for 2 factors we can use the sp800 functions to do this */ + if (!RSA_set0_factors(rsa, sk_BIGNUM_value(factors, 0), + sk_BIGNUM_value(factors, 1))) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + /* + * once consumed by RSA_set0_factors, pop those off the stack + * so we don't free them below + */ + sk_BIGNUM_pop(factors); + sk_BIGNUM_pop(factors); + + /* + * Note: Because we only have 2 factors here, there will be no + * additional pinfo fields to hold additional factors, and + * since we set our key and 2 factors above we can skip + * the call to ossl_rsa_set0_all_params + */ + if (!ossl_rsa_sp800_56b_derive_params_from_pq(rsa, + RSA_bits(rsa), + NULL, ctx)) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + } else { +#ifndef FIPS_MODULE + /* + * in the multiprime case we have to generate exps/coeffs here + * for each additional prime + */ + if (!ossl_rsa_multiprime_derive(rsa, RSA_bits(rsa), + sk_BIGNUM_num(factors), + rsa->e, factors, exps, + coeffs)) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Now we should have all our factors, exponents and + * coefficients + */ + if (!ossl_rsa_set0_all_params(rsa, factors, exps, coeffs)) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + +#else + /* multiprime case is disallowed in FIPS mode, raise an error */ + ERR_raise(ERR_LIB_RSA, ERR_R_UNSUPPORTED); + goto err; +#endif + } + + } else { + /* + * It's ok if this private key just has n, e and d + * but only if we're not using derive_from_pq + */ + if (sk_BIGNUM_num(factors) != 0 + && !ossl_rsa_set0_all_params(rsa, factors, exps, coeffs)) + goto err; + } + /* sanity check to ensure we used everything in our stacks */ if (sk_BIGNUM_num(factors) != 0 - && !ossl_rsa_set0_all_params(rsa, factors, exps, coeffs)) + || sk_BIGNUM_num(exps) != 0 + || sk_BIGNUM_num(coeffs) != 0) { + ERR_raise_data(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR, + "There are %d, %d, %d elements left on our factors, exps, coeffs stacks\n", + sk_BIGNUM_num(factors), sk_BIGNUM_num(exps), + sk_BIGNUM_num(coeffs)); goto err; + } } + if (!ossl_rsa_check_factors(rsa)) { + ERR_raise_data(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR, + "RSA factors/exponents are too big for for n-modulus\n"); + goto err; + } + BN_clear_free(p); + BN_clear_free(q); sk_BIGNUM_free(factors); sk_BIGNUM_free(exps); sk_BIGNUM_free(coeffs); + BN_CTX_free(ctx); return 1; err: BN_free(n); BN_free(e); BN_free(d); - sk_BIGNUM_pop_free(factors, BN_free); - sk_BIGNUM_pop_free(exps, BN_free); - sk_BIGNUM_pop_free(coeffs, BN_free); + sk_BIGNUM_pop_free(factors, BN_clear_free); + sk_BIGNUM_pop_free(exps, BN_clear_free); + sk_BIGNUM_pop_free(coeffs, BN_clear_free); + BN_CTX_free(ctx); return 0; } @@ -152,7 +288,7 @@ int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], || !ossl_param_build_set_multi_key_bn(bld, params, ossl_rsa_mp_coeff_names, coeffs)) - goto err; + goto err; } #if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) @@ -389,10 +525,8 @@ RSA *ossl_rsa_dup(const RSA *rsa, int selection) 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); + if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) goto err; - } /* push first so cleanup in error case works */ (void)sk_RSA_PRIME_INFO_push(dupkey->prime_infos, duppinfo); @@ -514,7 +648,7 @@ int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss, if (pss->trailerField) *ptrailerField = ASN1_INTEGER_get(pss->trailerField); else - *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params);; + *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params); return 1; } |