diff options
author | Daniel Bevenius <daniel.bevenius@gmail.com> | 2020-10-09 06:07:43 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2021-01-28 16:25:16 +0100 |
commit | e947a0642db111bb34547b5f7d48e13163492ca5 (patch) | |
tree | a5e71dbadff8d328df119f0c2f12fc8dcbcfa61f | |
parent | d744934b756bc71344818a2cb60b13dd89954afb (diff) |
EVP: fix keygen for EVP_PKEY_RSA_PSS
This commit attempts to fix the an issue when generating a key of type
EVP_PKEY_RSA_PSS. Currently, EVP_PKEY_CTX_set_rsa_keygen_bits will
return -1 if the key id is not of type EVP_PKEY_RSA. This commit adds
EVP_PKEY_RSA_PSS to also be accepted.
The macro EVP_PKEY_CTX_set_rsa_pss_keygen_md si converted into a
function and it is now called in legacy_ctrl_to_param.
Fixes #12384
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13099)
-rw-r--r-- | crypto/evp/pmeth_lib.c | 8 | ||||
-rw-r--r-- | crypto/rsa/rsa_lib.c | 67 | ||||
-rw-r--r-- | doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod | 6 | ||||
-rw-r--r-- | include/openssl/core_names.h | 14 | ||||
-rw-r--r-- | include/openssl/rsa.h | 11 | ||||
-rw-r--r-- | test/evp_extra_test.c | 27 | ||||
-rw-r--r-- | util/libcrypto.num | 2 |
7 files changed, 121 insertions, 14 deletions
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 7c2e648209..7fb32df86a 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -1315,6 +1315,14 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, p1); } } + + if (keytype == EVP_PKEY_RSA_PSS) { + switch(cmd) { + case EVP_PKEY_CTRL_MD: + return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, p2); + } + } + /* * keytype == -1 is used when several key types share the same structure, * or for generic controls that are the same across multiple key types. diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index da0fd4a6eb..6ca4f3a541 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -902,6 +902,70 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode) } +int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) +{ + const char *name; + + if (ctx == NULL || md == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* If key type not RSA return error */ + if (ctx->pmeth != NULL + && ctx->pmeth->pkey_id != EVP_PKEY_RSA + && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + return -1; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.keymgmt.genctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_MD, 0, (void *)md); + + name = EVP_MD_name(md); + + return EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(ctx, name, NULL); +} + +int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx, + const char *mdname, + const char *mdprops) +{ + OSSL_PARAM rsa_params[3], *p = rsa_params; + + if (ctx == NULL || mdname == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* If key type not RSA return error */ + if (ctx->pmeth != NULL + && ctx->pmeth->pkey_id != EVP_PKEY_RSA + && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + return -1; + + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, + /* + * Cast away the const. This is read + * only so should be safe + */ + (char *)mdname, 0); + if (mdprops != NULL) { + *p++ = OSSL_PARAM_construct_utf8_string( + OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, + /* + * Cast away the const. This is read only so should be safe + */ + (char *)mdprops, 0); + } + *p++ = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, rsa_params); +} + int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { const char *name; @@ -1332,7 +1396,8 @@ int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) } /* If key type not RSA return error */ - if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA) + if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA && + ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) return -1; /* TODO(3.0): Remove this eventually when no more legacy */ diff --git a/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod index 1407c8f71a..b842dcbd62 100644 --- a/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod +++ b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod @@ -3,6 +3,7 @@ =head1 NAME EVP_PKEY_CTX_set_rsa_pss_keygen_md, +EVP_PKEY_CTX_set_rsa_pss_keygen_md_name, EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md, EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name, EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen @@ -14,6 +15,9 @@ EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *pctx, const EVP_MD *md); + int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx, + const char *mdname, + const char *mdprops); int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *pctx, const EVP_MD *md); int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *pctx, @@ -59,6 +63,8 @@ when (for example) a certificate request is signed. EVP_PKEY_CTX_set_rsa_pss_keygen_md() restricts the digest algorithm the generated key can use to I<md>. +EVP_PKEY_CTX_set_rsa_pss_keygen_md_name() does the same thing, but +passes the algorithm by name rather than by B<EVP_MD>. EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md() restricts the MGF1 algorithm the generated key can use to I<md>. diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index f579e7df33..07b95e043b 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -385,13 +385,13 @@ extern "C" { #define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO "auto" /* Key generation parameters */ -#define OSSL_PKEY_PARAM_RSA_BITS OSSL_PKEY_PARAM_BITS -#define OSSL_PKEY_PARAM_RSA_PRIMES "primes" -#define OSSL_PKEY_PARAM_RSA_DIGEST OSSL_PKEY_PARAM_DIGEST -#define OSSL_PKEY_PARAM_RSA_DIGEST_PROPS OSSL_PKEY_PARAM_PROPERTIES -#define OSSL_PKEY_PARAM_RSA_MASKGENFUNC OSSL_PKEY_PARAM_MASKGENFUNC -#define OSSL_PKEY_PARAM_RSA_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST -#define OSSL_PKEY_PARAM_RSA_PSS_SALTLEN "saltlen" +#define OSSL_PKEY_PARAM_RSA_BITS OSSL_PKEY_PARAM_BITS +#define OSSL_PKEY_PARAM_RSA_PRIMES "primes" +#define OSSL_PKEY_PARAM_RSA_DIGEST OSSL_PKEY_PARAM_DIGEST +#define OSSL_PKEY_PARAM_RSA_DIGEST_PROPS OSSL_PKEY_PARAM_PROPERTIES +#define OSSL_PKEY_PARAM_RSA_MASKGENFUNC OSSL_PKEY_PARAM_MASKGENFUNC +#define OSSL_PKEY_PARAM_RSA_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST +#define OSSL_PKEY_PARAM_RSA_PSS_SALTLEN "saltlen" /* Key generation parameters */ #define OSSL_PKEY_PARAM_FFC_TYPE "type" diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h index 82f4a9adba..46cc9badec 100644 --- a/include/openssl/rsa.h +++ b/include/openssl/rsa.h @@ -150,6 +150,11 @@ int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname); +int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); +int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx, + const char *mdname, + const char *mdprops); + int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname, const char *mdprops); @@ -159,12 +164,6 @@ int EVP_PKEY_CTX_get_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, char *name, int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen); int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label); -# define EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md) \ - EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, \ - EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, \ - 0, (void *)(md)) - - # define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1) # define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 2) diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 2ef16bc07c..6cca821cf1 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -29,6 +29,7 @@ #include <openssl/dh.h> #include <openssl/aes.h> #include <openssl/decoder.h> +#include <openssl/rsa.h> #include "testutil.h" #include "internal/nelem.h" #include "internal/sizes.h" @@ -2256,6 +2257,31 @@ err: return ret; } +static int test_EVP_rsa_pss_with_keygen_bits(void) +{ + int ret; + OSSL_PROVIDER *provider; + EVP_PKEY_CTX *ctx; + EVP_PKEY *pkey; + const EVP_MD *md; + pkey = NULL; + ret = 0; + provider = OSSL_PROVIDER_load(NULL, "default"); + md = EVP_get_digestbyname("sha256"); + + ret = TEST_ptr((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, NULL))) + && TEST_true(EVP_PKEY_keygen_init(ctx)) + && TEST_int_gt(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 512), 0) + && TEST_true(EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md)) + && TEST_true(EVP_PKEY_keygen(ctx, &pkey)); + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + OSSL_PROVIDER_unload(provider); + return ret; +} + + int setup_tests(void) { testctx = OSSL_LIB_CTX_new(); @@ -2321,6 +2347,7 @@ int setup_tests(void) ADD_TEST(test_rand_agglomeration); ADD_ALL_TESTS(test_evp_iv, 10); + ADD_TEST(test_EVP_rsa_pss_with_keygen_bits); return 1; } diff --git a/util/libcrypto.num b/util/libcrypto.num index 509c694d69..f519518395 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5287,6 +5287,8 @@ PEM_write_bio_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_get_group_name ? 3_0_0 EXIST::FUNCTION: CRYPTO_atomic_or ? 3_0_0 EXIST::FUNCTION: CRYPTO_atomic_load ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set_rsa_pss_keygen_md ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set_rsa_pss_keygen_md_name ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_settable_params ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_set_params ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_set_int_param ? 3_0_0 EXIST::FUNCTION: |