From 645a541a3fdabd32cb8cbda48651f4150486189d Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Sat, 2 May 2020 13:02:29 +0200 Subject: [PATCH] RSA: Extract much of the rsa_pkey_export_to() code to a separate function The resulting function, rsa_todata(), is designed to be usable by providers as well. Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/11710) --- crypto/rsa/rsa_ameth.c | 61 +++------------------------------------- crypto/rsa/rsa_backend.c | 49 ++++++++++++++++++++++++++++++++ include/crypto/rsa.h | 2 ++ 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index b530754528..95350f5a7d 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -1100,10 +1100,6 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, { RSA *rsa = from->pkey.rsa; OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new(); - const BIGNUM *n = RSA_get0_n(rsa), *e = RSA_get0_e(rsa); - const BIGNUM *d = RSA_get0_d(rsa); - STACK_OF(BIGNUM_const) *primes = NULL, *exps = NULL, *coeffs = NULL; - int numprimes = 0, numexps = 0, numcoeffs = 0; OSSL_PARAM *params = NULL; int selection = 0; int rv = 0; @@ -1118,65 +1114,16 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, goto err; /* Public parameters must always be present */ - if (n == NULL || e == NULL) + if (RSA_get0_n(rsa) == NULL || RSA_get0_e(rsa) == NULL) goto err; - /* |e| and |n| are always present */ - if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, e)) + if (!rsa_todata(rsa, tmpl, NULL)) goto err; - if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, n)) - goto err; - selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; - - if (d != NULL) { - int i; - - /* Get all the primes and CRT params */ - if ((primes = sk_BIGNUM_const_new_null()) == NULL - || (exps = sk_BIGNUM_const_new_null()) == NULL - || (coeffs = sk_BIGNUM_const_new_null()) == NULL) - goto err; - if (!rsa_get0_all_params(rsa, primes, exps, coeffs)) - goto err; - - numprimes = sk_BIGNUM_const_num(primes); - numexps = sk_BIGNUM_const_num(exps); - numcoeffs = sk_BIGNUM_const_num(coeffs); - - /* - * It's permisssible to have zero primes, i.e. no CRT params. - * Otherwise, there must be at least two, as many exponents, - * and one coefficient less. - */ - if (numprimes != 0 - && (numprimes < 2 || numexps < 2 || numcoeffs < 1)) - goto err; - - if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, d)) - goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + if (RSA_get0_d(rsa) != NULL) selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; - for (i = 0; i < numprimes && rsa_mp_factor_names[i] != NULL; i++) { - const BIGNUM *num = sk_BIGNUM_const_value(primes, i); - - if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_factor_names[i], num)) - goto err; - } - - for (i = 0; i < numexps && rsa_mp_exp_names[i] != NULL; i++) { - const BIGNUM *num = sk_BIGNUM_const_value(exps, i); - - if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_exp_names[i], num)) - goto err; - } - - for (i = 0; i < numcoeffs && rsa_mp_coeff_names[i] != NULL; i++) { - const BIGNUM *num = sk_BIGNUM_const_value(coeffs, i); - - if (!OSSL_PARAM_BLD_push_BN(tmpl, rsa_mp_coeff_names[i], num)) - goto err; - } } if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index 57a539c051..cf0bff0822 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -97,3 +97,52 @@ int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]) return 0; } +DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) + +int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) +{ + int ret = 0; + const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL; + STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null(); + + if (rsa == NULL || factors == NULL || exps == NULL || coeffs == NULL) + goto err; + + RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); + rsa_get0_all_params(rsa, factors, exps, coeffs); + + /* Check private key data integrity */ + if (rsa_d != NULL) { + int numprimes = sk_BIGNUM_const_num(factors); + int numexps = sk_BIGNUM_const_num(exps); + int numcoeffs = sk_BIGNUM_const_num(coeffs); + + /* + * It's permisssible to have zero primes, i.e. no CRT params. + * Otherwise, there must be at least two, as many exponents, + * and one coefficient less. + */ + if (numprimes != 0 + && (numprimes < 2 || numexps < 2 || numcoeffs < 1)) + goto err; + } + + if (!ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_N, rsa_n) + || !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_E, rsa_e) + || !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_D, rsa_d) + || !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_factor_names, + factors) + || !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_exp_names, + exps) + || !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_coeff_names, + coeffs)) + goto err; + ret = 1; + err: + sk_BIGNUM_const_free(factors); + sk_BIGNUM_const_free(exps); + sk_BIGNUM_const_free(coeffs); + return ret; +} diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h index 7ce1fdb339..321c7f8c1e 100644 --- a/include/crypto/rsa.h +++ b/include/crypto/rsa.h @@ -21,6 +21,8 @@ int rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, int rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes, STACK_OF(BIGNUM_const) *exps, STACK_OF(BIGNUM_const) *coeffs); + +int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]); int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]); int rsa_padding_check_PKCS1_type_2_TLS(OPENSSL_CTX *ctx, unsigned char *to, -- 2.25.1