From 13f91a7245d4271486c018b440940a696eaaa12d Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Mon, 25 Jan 2021 15:38:32 +0100 Subject: EVP: Adapt the RSA specific EVP_PKEY_CTX setter / getter functions Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/13913) --- crypto/rsa/rsa_lib.c | 671 ++++++++++++++++----------------------------------- 1 file changed, 207 insertions(+), 464 deletions(-) (limited to 'crypto/rsa') diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index 6ca4f3a541..817372cbb7 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -838,399 +838,219 @@ int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes, } #ifndef FIPS_MODULE -int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode) +/* Helpers to set or get diverse hash algorithm names */ +static int int_set_rsa_md_name(EVP_PKEY_CTX *ctx, + /* For checks */ + int keytype, int optype, + /* For EVP_PKEY_CTX_set_params() */ + const char *mdkey, const char *mdname, + const char *propkey, const char *mdprops) { - OSSL_PARAM pad_params[2], *p = pad_params; + OSSL_PARAM params[3], *p = params; - if (ctx == NULL) { + if (ctx == NULL || mdname == NULL || (ctx->operation & optype) == 0) { 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 or RSA-PSS 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 ((!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - || ctx->op.ciph.ciphprovctx == NULL) - && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) - || ctx->op.sig.sigprovctx == NULL)) - return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_RSA_PADDING, - pad_mode, NULL); + /* If key type not RSA return error */ + switch (keytype) { + case -1: + if (!EVP_PKEY_CTX_is_a(ctx, "RSA") + && !EVP_PKEY_CTX_is_a(ctx, "RSA-PSS")) + return -1; + break; + default: + if (!EVP_PKEY_CTX_is_a(ctx, evp_pkey_type2name(keytype))) + return -1; + break; + } - *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_PAD_MODE, &pad_mode); + /* Cast away the const. This is read only so should be safe */ + *p++ = OSSL_PARAM_construct_utf8_string(mdkey, (char *)mdname, 0); + if (evp_pkey_ctx_is_provided(ctx) && mdprops != NULL) { + /* Cast away the const. This is read only so should be safe */ + *p++ = OSSL_PARAM_construct_utf8_string(propkey, (char *)mdprops, 0); + } *p++ = OSSL_PARAM_construct_end(); - return EVP_PKEY_CTX_set_params(ctx, pad_params); + return evp_pkey_ctx_set_params_strict(ctx, params); } -int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode) +/* Helpers to set or get diverse hash algorithm names */ +static int int_get_rsa_md_name(EVP_PKEY_CTX *ctx, + /* For checks */ + int keytype, int optype, + /* For EVP_PKEY_CTX_get_params() */ + const char *mdkey, + char *mdname, size_t mdnamesize) { - OSSL_PARAM pad_params[2], *p = pad_params; + OSSL_PARAM params[2], *p = params; - if (ctx == NULL || pad_mode == NULL) { + if (ctx == NULL || mdname == NULL || (ctx->operation & optype) == 0) { 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 or RSA-PSS 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 ((!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - || ctx->op.ciph.ciphprovctx == NULL) - && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) - || ctx->op.sig.sigprovctx == NULL)) - return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, - pad_mode); + /* If key type not RSA return error */ + switch (keytype) { + case -1: + if (!EVP_PKEY_CTX_is_a(ctx, "RSA") + && !EVP_PKEY_CTX_is_a(ctx, "RSA-PSS")) + return -1; + break; + default: + if (!EVP_PKEY_CTX_is_a(ctx, evp_pkey_type2name(keytype))) + return -1; + break; + } - *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_PAD_MODE, pad_mode); + /* Cast away the const. This is read only so should be safe */ + *p++ = OSSL_PARAM_construct_utf8_string(mdkey, (char *)mdname, mdnamesize); *p++ = OSSL_PARAM_construct_end(); - if (!EVP_PKEY_CTX_get_params(ctx, pad_params)) - return 0; + return evp_pkey_ctx_get_params_strict(ctx, params); +} - return 1; +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated? + */ +int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode) +{ + return RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, + pad_mode, NULL); +} +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated? + */ +int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode) +{ + return RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, + 0, pad_mode); } +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated in favor of passing a name? + */ 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); + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_MD, 0, (void *)(md)); } 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); + return int_set_rsa_md_name(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, + OSSL_PKEY_PARAM_RSA_DIGEST, mdname, + OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, mdprops); } +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated in favor of passing a name? + */ int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { - const char *name; - - if (ctx == NULL || !EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) { - 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) - return -1; - - /* TODO(3.0): Remove this eventually when no more legacy */ - if (ctx->op.ciph.ciphprovctx == NULL) - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md); - - name = (md == NULL) ? "" : EVP_MD_name(md); - - return EVP_PKEY_CTX_set_rsa_oaep_md_name(ctx, name, NULL); + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)(md)); } int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname, const char *mdprops) { - OSSL_PARAM rsa_params[3], *p = rsa_params; - - if (ctx == NULL || !EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) { - 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) - return -1; - - - *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_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_ASYM_CIPHER_PARAM_OAEP_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); + return + int_set_rsa_md_name(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, mdname, + OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS, mdprops); } int EVP_PKEY_CTX_get_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, char *name, - size_t namelen) + size_t namesize) { - OSSL_PARAM rsa_params[2], *p = rsa_params; - - if (ctx == NULL || !EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) { - 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) - return -1; - - *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, - name, namelen); - *p++ = OSSL_PARAM_construct_end(); - - if (!EVP_PKEY_CTX_get_params(ctx, rsa_params)) - return -1; - - return 1; + return int_get_rsa_md_name(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, + name, namesize); } +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated in favor of getting a name? + */ int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md) { - /* 80 should be big enough */ - char name[80] = ""; - - if (ctx == NULL || md == NULL || !EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) { - 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) - return -1; - - /* TODO(3.0): Remove this eventually when no more legacy */ - if (ctx->op.ciph.ciphprovctx == NULL) - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)md); - - if (EVP_PKEY_CTX_get_rsa_oaep_md_name(ctx, name, sizeof(name)) <= 0) - return -1; - - /* May be NULL meaning "unknown" */ - *md = evp_get_digestbyname_ex(ctx->libctx, name); - - return 1; + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)md); } -static int int_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, - /* For EVP_PKEY_CTX_ctrl() */ - int keytype, int optype, int cmd, - const EVP_MD *md, - /* For EVP_PKEY_CTX_set_params() */ - const char *mdname, const char *mdprops) +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated in favor of passing a name? + */ +int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { - OSSL_PARAM rsa_params[3], *p = rsa_params; - - if (ctx == NULL || (ctx->operation & optype) == 0) { - 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 - && (keytype == -1 - ? (ctx->pmeth->pkey_id != EVP_PKEY_RSA - && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) - : ctx->pmeth->pkey_id != keytype)) - return -1; - - /* TODO(3.0): Remove this eventually when no more legacy */ - if (cmd != -1) { - if ((EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && ctx->op.ciph.ciphprovctx == NULL) - || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) - && ctx->op.sig.sigprovctx == NULL) - || (EVP_PKEY_CTX_IS_GEN_OP(ctx) - && ctx->op.keymgmt.genctx == NULL)) - return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, (void *)md); - - mdname = (md == NULL) ? "" : EVP_MD_name(md); - } - - - *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MGF1_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_MGF1_PROPERTIES, - /* - * 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); + return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)); } -int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) +int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname, + const char *mdprops) { - return int_set_rsa_mgf1_md(ctx, -1, + return int_set_rsa_md_name(ctx, -1, EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG, - EVP_PKEY_CTRL_RSA_MGF1_MD, md, NULL, NULL); + OSSL_PKEY_PARAM_MGF1_DIGEST, mdname, + OSSL_PKEY_PARAM_MGF1_PROPERTIES, mdprops); } -int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname, - const char *mdprops) +int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name, + size_t namesize) { - return int_set_rsa_mgf1_md(ctx, -1, + return int_get_rsa_md_name(ctx, -1, EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG, - -1, NULL, mdname, mdprops); + OSSL_PKEY_PARAM_MGF1_DIGEST, name, namesize); } +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated in favor of passing a name? + */ int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { - return int_set_rsa_mgf1_md(ctx, EVP_PKEY_RSA_PSS, - EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_MGF1_MD, - md, NULL, NULL); + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)); } int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname) { - return int_set_rsa_mgf1_md(ctx, EVP_PKEY_RSA_PSS, - EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_TYPE_SIG, - -1, NULL, mdname, NULL); -} - -int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name, - size_t namelen) -{ - OSSL_PARAM rsa_params[2], *p = rsa_params; - - if (ctx == NULL - || (!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx))) { - 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 or RSA-PSS 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_MGF1_DIGEST, - name, namelen); - *p++ = OSSL_PARAM_construct_end(); - - if (!EVP_PKEY_CTX_get_params(ctx, rsa_params)) - return -1; - - return 1; + return int_set_rsa_md_name(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, + OSSL_PKEY_PARAM_MGF1_DIGEST, mdname, + NULL, NULL); } +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + * TODO(3.0) Should this be deprecated in favor of getting a name? + */ int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md) { - /* 80 should be big enough */ - char name[80] = ""; - - if (ctx == NULL - || (!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx))) { - 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 or RSA-PSS 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 ((EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && ctx->op.ciph.ciphprovctx == NULL) - || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) - && ctx->op.sig.sigprovctx == NULL)) - return EVP_PKEY_CTX_ctrl(ctx, -1, - EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)md); - - if (EVP_PKEY_CTX_get_rsa_mgf1_md_name(ctx, name, sizeof(name)) <= 0) - return -1; - - /* May be NULL meaning "unknown" */ - *md = evp_get_digestbyname_ex(ctx->libctx, name); - - return 1; + return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)(md)); } int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen) @@ -1244,27 +1064,20 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen) } /* If key type not RSA return error */ - if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA) + if (!EVP_PKEY_CTX_is_a(ctx, "RSA")) return -1; - /* TODO(3.0): Remove this eventually when no more legacy */ - if (ctx->op.ciph.ciphprovctx == NULL) - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, - (void *)label); + /* TODO(3.0) Shouldn't a set0 translate into setting an OCTET_PTR? */ + /* Cast away the const. This is read only so should be safe */ *p++ = OSSL_PARAM_construct_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, - /* - * Cast away the const. This is - * read only so should be safe - */ - (void *)label, - (size_t)llen); + (void *)label, (size_t)llen); *p++ = OSSL_PARAM_construct_end(); - if (!EVP_PKEY_CTX_set_params(ctx, rsa_params)) + if (!evp_pkey_ctx_set_params_strict(ctx, rsa_params)) return 0; + /* TODO(3.0) ????? */ OPENSSL_free(label); return 1; } @@ -1281,15 +1094,9 @@ int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label) } /* If key type not RSA return error */ - if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA) + if (!EVP_PKEY_CTX_is_a(ctx, "RSA")) return -1; - /* TODO(3.0): Remove this eventually when no more legacy */ - if (ctx->op.ciph.ciphprovctx == NULL) - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, - (void *)label); - *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, (void **)label, 0); *p++ = OSSL_PARAM_construct_end(); @@ -1304,84 +1111,63 @@ int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label) return (int)labellen; } -static int int_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen, - int keytype, int optype) -{ - OSSL_PARAM pad_params[2], *p = pad_params; - - if (ctx == NULL || (ctx->operation & optype) == 0) { - 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 or RSA-PSS return error */ - if (ctx->pmeth != NULL - && (keytype == -1 - ? (ctx->pmeth->pkey_id != EVP_PKEY_RSA - && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) - : ctx->pmeth->pkey_id != keytype)) - return -1; - - /* TODO(3.0): Remove this eventually when no more legacy */ - if ((EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) - && ctx->op.sig.sigprovctx == NULL) - || (EVP_PKEY_CTX_IS_GEN_OP(ctx) - && ctx->op.keymgmt.genctx == NULL)) - return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, - EVP_PKEY_CTRL_RSA_PSS_SALTLEN, - saltlen, NULL); - - *p++ = - OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, &saltlen); - *p++ = OSSL_PARAM_construct_end(); - - return EVP_PKEY_CTX_set_params(ctx, pad_params); -} - +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + */ int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen) { - return int_set_rsa_pss_saltlen(ctx, saltlen, -1, EVP_PKEY_OP_TYPE_SIG); + /* + * For some reason, the optype was set to this: + * + * EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY + * + * However, we do use RSA-PSS with the whole gamut of diverse signature + * and verification operations, so the optype gets upgraded to this: + * + * EVP_PKEY_OP_TYPE_SIG + */ + return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG, + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, saltlen, NULL); } -int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, int saltlen) +/* + * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, + * simply because that's easier. + */ +int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen) { - return int_set_rsa_pss_saltlen(ctx, saltlen, EVP_PKEY_RSA_PSS, - EVP_PKEY_OP_KEYGEN); + /* + * Because of circumstances, the optype is updated from: + * + * EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY + * + * to: + * + * EVP_PKEY_OP_TYPE_SIG + */ + return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG, + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, saltlen); } -int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen) +int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, int saltlen) { OSSL_PARAM pad_params[2], *p = pad_params; - if (ctx == NULL || saltlen == NULL) { + if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { 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 or RSA-PSS return error */ - if (ctx->pmeth != NULL - && ctx->pmeth->pkey_id != EVP_PKEY_RSA - && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + if (!EVP_PKEY_CTX_is_a(ctx, "RSA-PSS")) return -1; - /* TODO(3.0): Remove this eventually when no more legacy */ - if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) - || ctx->op.sig.sigprovctx == NULL) - return EVP_PKEY_CTX_ctrl(ctx, -1, -1, - EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, - 0, saltlen); - - *p++ = - OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, saltlen); + *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, + &saltlen); *p++ = OSSL_PARAM_construct_end(); - if (!EVP_PKEY_CTX_get_params(ctx, pad_params)) - return 0; - - return 1; - + return evp_pkey_ctx_set_params_strict(ctx, pad_params); } int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) @@ -1396,84 +1182,49 @@ 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 && - ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + if (!EVP_PKEY_CTX_is_a(ctx, "RSA") + && !EVP_PKEY_CTX_is_a(ctx, "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, EVP_PKEY_OP_KEYGEN, - EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL); - *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &bits2); *p++ = OSSL_PARAM_construct_end(); - if (!EVP_PKEY_CTX_set_params(ctx, params)) - return 0; - - return 1; + return evp_pkey_ctx_set_params_strict(ctx, params); } -static int evp_pkey_ctx_set_rsa_keygen_pubexp_intern(EVP_PKEY_CTX *ctx, - BIGNUM *pubexp, - int copy) +int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp) { - OSSL_PARAM_BLD *tmpl; - OSSL_PARAM *params; - int ret; - - if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { - 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) - return -1; - - /* TODO(3.0): Remove this eventually when no more legacy */ - if (ctx->op.keymgmt.genctx == NULL) { - if (copy == 1) - pubexp = BN_dup(pubexp); - ret = EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, + int ret = RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp); - if ((copy == 1) && (ret <= 0)) - BN_free(pubexp); - return ret; - } - - if ((tmpl = OSSL_PARAM_BLD_new()) == NULL) - return 0; - if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, pubexp) - || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) { - OSSL_PARAM_BLD_free(tmpl); - return 0; - } - OSSL_PARAM_BLD_free(tmpl); - - ret = EVP_PKEY_CTX_set_params(ctx, params); - OSSL_PARAM_BLD_free_params(params); /* * Satisfy memory semantics for pre-3.0 callers of * EVP_PKEY_CTX_set_rsa_keygen_pubexp(): their expectation is that input * pubexp BIGNUM becomes managed by the EVP_PKEY_CTX on success. */ - if ((copy == 0) && (ret > 0)) + if (ret > 0 && evp_pkey_ctx_is_provided(ctx)) { + BN_free(ctx->rsa_pubexp); ctx->rsa_pubexp = pubexp; + } return ret; } -int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp) -{ - return evp_pkey_ctx_set_rsa_keygen_pubexp_intern(ctx, pubexp, 0); -} - int EVP_PKEY_CTX_set1_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp) { - return evp_pkey_ctx_set_rsa_keygen_pubexp_intern(ctx, pubexp, 1); + int ret = 0; + + /* + * When we're dealing with a provider, there's no need to duplicate + * pubexp, as it gets copied when transforming to an OSSL_PARAM anyway. + */ + if (evp_pkey_ctx_is_legacy(ctx)) + pubexp = BN_dup(pubexp); + ret = EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp); + if (evp_pkey_ctx_is_legacy(ctx) && ret <= 0) + BN_free(pubexp); + return ret; } int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes) @@ -1488,21 +1239,13 @@ int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes) } /* If key type not RSA return error */ - if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA) + if (!EVP_PKEY_CTX_is_a(ctx, "RSA") + && !EVP_PKEY_CTX_is_a(ctx, "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, EVP_PKEY_OP_KEYGEN, - EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, - NULL); - *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, &primes2); *p++ = OSSL_PARAM_construct_end(); - if (!EVP_PKEY_CTX_set_params(ctx, params)) - return 0; - - return 1; + return evp_pkey_ctx_set_params_strict(ctx, params); } #endif -- cgit v1.2.3