X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frsa%2Frsa_ameth.c;h=6628e383428ebd53ab579860311fec479c494a57;hp=a94cb54b5e45c853cc067ebbe76701ec3b04f955;hb=7674e92324648b59786d86d8e9014bbaed4e6d07;hpb=b305452f69fc97c586f2f9310014e332ae1d5cd5 diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index a94cb54b5e..6628e38342 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2020 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 @@ -7,6 +7,12 @@ * https://www.openssl.org/source/license.html */ +/* + * RSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include #include "internal/cryptlib.h" #include @@ -14,7 +20,7 @@ #include #include #include -#include "internal/param_build.h" +#include #include "crypto/asn1.h" #include "crypto/evp.h" #include "crypto/rsa.h" @@ -37,7 +43,7 @@ static int rsa_param_encode(const EVP_PKEY *pkey, *pstr = NULL; /* If RSA it's just NULL type */ - if (pkey->ameth->pkey_id != EVP_PKEY_RSA_PSS) { + if (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK) != RSA_FLAG_TYPE_RSASSAPSS) { *pstrtype = V_ASN1_NULL; return 1; } @@ -95,7 +101,7 @@ static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) return 0; } -static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +static int rsa_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey) { const unsigned char *p; int pklen; @@ -190,6 +196,20 @@ static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) RSA_free(rsa); return 0; } + + RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK); + switch (pkey->ameth->pkey_id) { + case EVP_PKEY_RSA: + RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA); + break; + case EVP_PKEY_RSA_PSS: + RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS); + break; + default: + /* Leave the type bits zero */ + break; + } + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa); return 1; } @@ -1072,98 +1092,170 @@ static size_t rsa_pkey_dirty_cnt(const EVP_PKEY *pkey) return pkey->pkey.rsa->dirty_cnt; } -DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) - -static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, - EVP_KEYMGMT *to_keymgmt) +/* + * For the moment, we trust the call path, where keys going through + * rsa_pkey_export_to() match a KEYMGMT for the "RSA" keytype, while + * keys going through rsa_pss_pkey_export_to() match a KEYMGMT for the + * "RSA-PSS" keytype. + * TODO(3.0) Investigate whether we should simply continue to trust the + * call path, or if we should strengthen this function by checking that + * |rsa_type| matches the RSA key subtype. The latter requires ensuring + * that the type flag for the RSA key is properly set by other functions + * in this file. + */ +static int rsa_int_export_to(const EVP_PKEY *from, int rsa_type, + void *to_keydata, EVP_KEYMGMT *to_keymgmt, + OPENSSL_CTX *libctx, const char *propq) { RSA *rsa = from->pkey.rsa; - OSSL_PARAM_BLD tmpl; - 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_BLD *tmpl = OSSL_PARAM_BLD_new(); OSSL_PARAM *params = NULL; + int selection = 0; int rv = 0; - /* Public parameters must always be present */ - if (n == NULL || e == NULL) + if (tmpl == NULL) + return 0; + /* + * If the RSA method is foreign, then we can't be sure of anything, and + * can therefore not export or pretend to export. + */ + if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL()) goto err; - ossl_param_bld_init(&tmpl); - - /* |e| and |n| are always present */ - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, e)) + /* Public parameters must always be present */ + if (RSA_get0_n(rsa) == NULL || RSA_get0_e(rsa) == NULL) goto err; - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_N, n)) + + if (!rsa_todata(rsa, tmpl, NULL)) goto err; - if (d != NULL) { - int i; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + if (RSA_get0_d(rsa) != NULL) + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; - /* 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->pss != NULL) { + const EVP_MD *md = NULL, *mgf1md = NULL; + int md_nid, mgf1md_nid, saltlen; + RSA_PSS_PARAMS_30 pss_params; - if (!rsa_get0_all_params(rsa, primes, exps, coeffs)) + if (!rsa_pss_get_param(rsa->pss, &md, &mgf1md, &saltlen)) goto err; - - numprimes = sk_BIGNUM_const_num(primes); - numexps = sk_BIGNUM_const_num(exps); - numcoeffs = sk_BIGNUM_const_num(coeffs); - - if (numprimes < 2 || numexps < 2 || numcoeffs < 1) + md_nid = EVP_MD_type(md); + mgf1md_nid = EVP_MD_type(mgf1md); + if (!rsa_pss_params_30_set_defaults(&pss_params) + || !rsa_pss_params_30_set_hashalg(&pss_params, md_nid) + || !rsa_pss_params_30_set_maskgenhashalg(&pss_params, mgf1md_nid) + || !rsa_pss_params_30_set_saltlen(&pss_params, saltlen) + || !rsa_pss_params_30_todata(&pss_params, propq, tmpl, NULL)) goto err; + selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS; + } - /* assert that an OSSL_PARAM_BLD has enough space. */ - if (!ossl_assert(/* n, e */ 2 + /* d */ 1 + /* numprimes */ 1 - + numprimes + numexps + numcoeffs - <= OSSL_PARAM_BLD_MAX)) - goto err; + if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) + goto err; - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_D, d)) - goto err; + /* We export, the provider imports */ + rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); - for (i = 0; i < numprimes; i++) { - const BIGNUM *num = sk_BIGNUM_const_value(primes, i); + err: + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(tmpl); + return rv; +} - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_FACTOR, - num)) - goto err; - } +static int rsa_int_import_from(const OSSL_PARAM params[], void *vpctx, + int rsa_type) +{ + EVP_PKEY_CTX *pctx = vpctx; + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + RSA *rsa = rsa_new_with_ctx(pctx->libctx); + RSA_PSS_PARAMS_30 rsa_pss_params = { 0, }; + int ok = 0; - for (i = 0; i < numexps; i++) { - const BIGNUM *num = sk_BIGNUM_const_value(exps, i); + if (rsa == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT, - num)) - goto err; - } + RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK); + RSA_set_flags(rsa, rsa_type); - for (i = 0; i < numcoeffs; i++) { - const BIGNUM *num = sk_BIGNUM_const_value(coeffs, i); + if (!rsa_pss_params_30_fromdata(&rsa_pss_params, params, pctx->libctx)) + goto err; - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT, - num)) + switch (rsa_type) { + case RSA_FLAG_TYPE_RSA: + /* + * Were PSS parameters filled in? + * In that case, something's wrong + */ + if (!rsa_pss_params_30_is_unrestricted(&rsa_pss_params)) + goto err; + break; + case RSA_FLAG_TYPE_RSASSAPSS: + /* + * Were PSS parameters filled in? In that case, create the old + * RSA_PSS_PARAMS structure. Otherwise, this is an unrestricted key. + */ + if (!rsa_pss_params_30_is_unrestricted(&rsa_pss_params)) { + /* Create the older RSA_PSS_PARAMS from RSA_PSS_PARAMS_30 data */ + int mdnid = rsa_pss_params_30_hashalg(&rsa_pss_params); + int mgf1mdnid = rsa_pss_params_30_maskgenhashalg(&rsa_pss_params); + int saltlen = rsa_pss_params_30_saltlen(&rsa_pss_params); + const EVP_MD *md = EVP_get_digestbynid(mdnid); + const EVP_MD *mgf1md = EVP_get_digestbynid(mgf1mdnid); + + if ((rsa->pss = rsa_pss_params_create(md, mgf1md, saltlen)) == NULL) goto err; } + break; + default: + /* RSA key sub-types we don't know how to handle yet */ + goto err; } - if ((params = ossl_param_bld_to_param(&tmpl)) == NULL) + if (!rsa_fromdata(rsa, params)) goto err; - /* We export, the provider imports */ - rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL, - params); + switch (rsa_type) { + case RSA_FLAG_TYPE_RSA: + ok = EVP_PKEY_assign_RSA(pkey, rsa); + break; + case RSA_FLAG_TYPE_RSASSAPSS: + ok = EVP_PKEY_assign(pkey, EVP_PKEY_RSA_PSS, rsa); + break; + } err: - sk_BIGNUM_const_free(primes); - sk_BIGNUM_const_free(exps); - sk_BIGNUM_const_free(coeffs); - ossl_param_bld_free(params); - return rv; + if (!ok) + RSA_free(rsa); + return ok; +} + +static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata, + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) +{ + return rsa_int_export_to(from, RSA_FLAG_TYPE_RSA, to_keydata, + to_keymgmt, libctx, propq); +} + +static int rsa_pss_pkey_export_to(const EVP_PKEY *from, void *to_keydata, + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) +{ + return rsa_int_export_to(from, RSA_FLAG_TYPE_RSASSAPSS, to_keydata, + to_keymgmt, libctx, propq); +} + +static int rsa_pkey_import_from(const OSSL_PARAM params[], void *vpctx) +{ + return rsa_int_import_from(params, vpctx, RSA_FLAG_TYPE_RSA); +} + +static int rsa_pss_pkey_import_from(const OSSL_PARAM params[], void *vpctx) +{ + return rsa_int_import_from(params, vpctx, RSA_FLAG_TYPE_RSASSAPSS); } const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = { @@ -1204,7 +1296,8 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = { 0, 0, 0, 0, rsa_pkey_dirty_cnt, - rsa_pkey_export_to + rsa_pkey_export_to, + rsa_pkey_import_from }, { @@ -1249,5 +1342,6 @@ const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = { 0, 0, 0, 0, rsa_pkey_dirty_cnt, - rsa_pkey_export_to + rsa_pss_pkey_export_to, + rsa_pss_pkey_import_from };