aboutsummaryrefslogtreecommitdiff
path: root/crypto/rsa/rsa_backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/rsa/rsa_backend.c')
-rw-r--r--crypto/rsa/rsa_backend.c170
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;
}