X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=providers%2Fimplementations%2Fsignature%2Frsa.c;h=49334e5cf0aa6564a58e6283b74403e95ecd87b0;hp=fdcdb56194f5841ebf905c3d3f81e8b949b96e46;hb=23c48d94d4d34eedc15fa65e0fa0e38a6137e09f;hpb=f844f9eb44186df2f8b0cfd3264b4eb003d8c61a diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c index fdcdb56194..49334e5cf0 100644 --- a/providers/implementations/signature/rsa.c +++ b/providers/implementations/signature/rsa.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -31,16 +31,16 @@ #include "prov/der_rsa.h" static OSSL_OP_signature_newctx_fn rsa_newctx; -static OSSL_OP_signature_sign_init_fn rsa_signature_init; -static OSSL_OP_signature_verify_init_fn rsa_signature_init; -static OSSL_OP_signature_verify_recover_init_fn rsa_signature_init; +static OSSL_OP_signature_sign_init_fn rsa_sign_init; +static OSSL_OP_signature_verify_init_fn rsa_verify_init; +static OSSL_OP_signature_verify_recover_init_fn rsa_verify_recover_init; static OSSL_OP_signature_sign_fn rsa_sign; static OSSL_OP_signature_verify_fn rsa_verify; static OSSL_OP_signature_verify_recover_fn rsa_verify_recover; -static OSSL_OP_signature_digest_sign_init_fn rsa_digest_signverify_init; +static OSSL_OP_signature_digest_sign_init_fn rsa_digest_sign_init; static OSSL_OP_signature_digest_sign_update_fn rsa_digest_signverify_update; static OSSL_OP_signature_digest_sign_final_fn rsa_digest_sign_final; -static OSSL_OP_signature_digest_verify_init_fn rsa_digest_signverify_init; +static OSSL_OP_signature_digest_verify_init_fn rsa_digest_verify_init; static OSSL_OP_signature_digest_verify_update_fn rsa_digest_signverify_update; static OSSL_OP_signature_digest_verify_final_fn rsa_digest_verify_final; static OSSL_OP_signature_freectx_fn rsa_freectx; @@ -55,13 +55,11 @@ static OSSL_OP_signature_set_ctx_md_params_fn rsa_set_ctx_md_params; static OSSL_OP_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params; static OSSL_ITEM padding_item[] = { - { RSA_PKCS1_PADDING, "pkcs1" }, - { RSA_SSLV23_PADDING, "sslv23" }, - { RSA_NO_PADDING, "none" }, - { RSA_PKCS1_OAEP_PADDING, "oaep" }, /* Correct spelling first */ - { RSA_PKCS1_OAEP_PADDING, "oeap" }, - { RSA_X931_PADDING, "x931" }, - { RSA_PKCS1_PSS_PADDING, "pss" }, + { RSA_PKCS1_PADDING, OSSL_PKEY_RSA_PAD_MODE_PKCSV15 }, + { RSA_SSLV23_PADDING, OSSL_PKEY_RSA_PAD_MODE_SSLV23 }, + { RSA_NO_PADDING, OSSL_PKEY_RSA_PAD_MODE_NONE }, + { RSA_X931_PADDING, OSSL_PKEY_RSA_PAD_MODE_X931 }, + { RSA_PKCS1_PSS_PADDING, OSSL_PKEY_RSA_PAD_MODE_PSS }, { 0, NULL } }; @@ -73,7 +71,9 @@ static OSSL_ITEM padding_item[] = { typedef struct { OPENSSL_CTX *libctx; + char *propq; RSA *rsa; + int operation; /* * Flag to determine if the hash function can be changed (1) or not (0) @@ -129,6 +129,8 @@ static int rsa_get_md_nid(const EVP_MD *md) { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 }, { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 }, { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 }, + { NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224 }, + { NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256 }, { NID_md5, OSSL_DIGEST_NAME_MD5 }, { NID_md5_sha1, OSSL_DIGEST_NAME_MD5_SHA1 }, { NID_md2, OSSL_DIGEST_NAME_MD2 }, @@ -153,9 +155,6 @@ static int rsa_get_md_nid(const EVP_MD *md) } } - if (mdnid == NID_undef) - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); - end: return mdnid; } @@ -177,52 +176,71 @@ static int rsa_check_padding(int mdnid, int padding) return 1; } -static void *rsa_newctx(void *provctx) +static int rsa_check_parameters(EVP_MD *md, PROV_RSA_CTX *prsactx) +{ + if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) { + int max_saltlen; + + /* See if minimum salt length exceeds maximum possible */ + max_saltlen = RSA_size(prsactx->rsa) - EVP_MD_size(md); + if ((RSA_bits(prsactx->rsa) & 0x7) == 1) + max_saltlen--; + if (prsactx->min_saltlen > max_saltlen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); + return 0; + } + } + return 1; +} + +static void *rsa_newctx(void *provctx, const char *propq) { - PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX)); + PROV_RSA_CTX *prsactx = NULL; + char *propq_copy = NULL; - if (prsactx == NULL) + if ((prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX))) == NULL + || (propq != NULL + && (propq_copy = OPENSSL_strdup(propq)) == NULL)) { + OPENSSL_free(prsactx); + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return NULL; + } prsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); prsactx->flag_allow_md = 1; + prsactx->propq = propq_copy; return prsactx; } /* True if PSS parameters are restricted */ #define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1) -static int rsa_signature_init(void *vprsactx, void *vrsa) -{ - PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; - - if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa)) - return 0; - - RSA_free(prsactx->rsa); - prsactx->rsa = vrsa; - if (RSA_get0_pss_params(prsactx->rsa) != NULL) - prsactx->pad_mode = RSA_PKCS1_PSS_PADDING; - else - prsactx->pad_mode = RSA_PKCS1_PADDING; - /* Maximum for sign, auto for verify */ - prsactx->saltlen = RSA_PSS_SALTLEN_AUTO; - prsactx->min_saltlen = -1; - - return 1; -} - static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, const char *mdprops) { + if (mdprops == NULL) + mdprops = ctx->propq; + if (mdname != NULL) { EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); int md_nid = rsa_get_md_nid(md); WPACKET pkt; + size_t mdname_len = strlen(mdname); if (md == NULL || md_nid == NID_undef - || !rsa_check_padding(md_nid, ctx->pad_mode)) { + || !rsa_check_padding(md_nid, ctx->pad_mode) + || !rsa_check_parameters(md, ctx) + || mdname_len >= sizeof(ctx->mdname)) { + if (md == NULL) + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "%s could not be fetched", mdname); + if (md_nid == NID_undef) + ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, + "digest=%s", mdname); + if (mdname_len >= sizeof(ctx->mdname)) + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "%s exceeds name buffer length", mdname); EVP_MD_free(md); return 0; } @@ -239,7 +257,8 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, */ ctx->aid_len = 0; if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf)) - && DER_w_algorithmIdentifier_RSA_with(&pkt, -1, ctx->rsa, md_nid) + && DER_w_algorithmIdentifier_MDWithRSAEncryption(&pkt, -1, ctx->rsa, + md_nid) && WPACKET_finish(&pkt)) { WPACKET_get_total_written(&pkt, &ctx->aid_len); ctx->aid = WPACKET_get_curr(&pkt); @@ -256,14 +275,105 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, } static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname, - const char *props) + const char *mdprops) { + size_t len; + + if (mdprops == NULL) + mdprops = ctx->propq; + if (ctx->mgf1_mdname[0] != '\0') EVP_MD_free(ctx->mgf1_md); - if ((ctx->mgf1_md = EVP_MD_fetch(ctx->libctx, mdname, props)) == NULL) + if ((ctx->mgf1_md = EVP_MD_fetch(ctx->libctx, mdname, mdprops)) == NULL) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "%s could not be fetched", mdname); + return 0; + } + len = OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname)); + if (len >= sizeof(ctx->mgf1_mdname)) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "%s exceeds name buffer length", mdname); + return 0; + } + + return 1; +} + +static int rsa_signature_init(void *vprsactx, void *vrsa, int operation) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa)) + return 0; + + RSA_free(prsactx->rsa); + prsactx->rsa = vrsa; + prsactx->operation = operation; + + /* Maximum for sign, auto for verify */ + prsactx->saltlen = RSA_PSS_SALTLEN_AUTO; + prsactx->min_saltlen = -1; + + switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) { + case RSA_FLAG_TYPE_RSA: + prsactx->pad_mode = RSA_PKCS1_PADDING; + break; + case RSA_FLAG_TYPE_RSASSAPSS: + prsactx->pad_mode = RSA_PKCS1_PSS_PADDING; + + { + const RSA_PSS_PARAMS_30 *pss = + rsa_get0_pss_params_30(prsactx->rsa); + + if (!rsa_pss_params_30_is_unrestricted(pss)) { + int md_nid = rsa_pss_params_30_hashalg(pss); + int mgf1md_nid = rsa_pss_params_30_maskgenhashalg(pss); + int min_saltlen = rsa_pss_params_30_saltlen(pss); + const char *mdname, *mgf1mdname; + size_t len; + + mdname = rsa_oaeppss_nid2name(md_nid); + mgf1mdname = rsa_oaeppss_nid2name(mgf1md_nid); + prsactx->min_saltlen = min_saltlen; + + if (mdname == NULL) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "PSS restrictions lack hash algorithm"); + return 0; + } + if (mgf1mdname == NULL) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "PSS restrictions lack MGF1 hash algorithm"); + return 0; + } + + len = OPENSSL_strlcpy(prsactx->mdname, mdname, + sizeof(prsactx->mdname)); + if (len >= sizeof(prsactx->mdname)) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "hash algorithm name too long"); + return 0; + } + len = OPENSSL_strlcpy(prsactx->mgf1_mdname, mgf1mdname, + sizeof(prsactx->mgf1_mdname)); + if (len >= sizeof(prsactx->mgf1_mdname)) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "MGF1 hash algorithm name too long"); + return 0; + } + prsactx->saltlen = min_saltlen; + + return rsa_setup_md(prsactx, mdname, prsactx->propq) + && rsa_setup_mgf1_md(prsactx, mgf1mdname, prsactx->propq); + } + } + + break; + default: + ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return 0; - OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname)); + } return 1; } @@ -287,10 +397,16 @@ static void clean_tbuf(PROV_RSA_CTX *ctx) static void free_tbuf(PROV_RSA_CTX *ctx) { - OPENSSL_clear_free(ctx->tbuf, RSA_size(ctx->rsa)); + clean_tbuf(ctx); + OPENSSL_free(ctx->tbuf); ctx->tbuf = NULL; } +static int rsa_sign_init(void *vprsactx, void *vrsa) +{ + return rsa_signature_init(vprsactx, vrsa, EVP_PKEY_OP_SIGN); +} + static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen, size_t sigsize, const unsigned char *tbs, size_t tbslen) { @@ -304,8 +420,11 @@ static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen, return 1; } - if (sigsize < (size_t)rsasize) + if (sigsize < rsasize) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE, + "is %zu, should be at least %zu", sigsize, rsasize); return 0; + } if (mdsize != 0) { if (tbslen != mdsize) { @@ -336,7 +455,9 @@ static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen, switch (prsactx->pad_mode) { case RSA_X931_PADDING: if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) { - ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL); + ERR_raise_data(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL, + "RSA key size = %d, expected minimum = %d", + RSA_size(prsactx->rsa), tbslen + 1); return 0; } if (!setup_tbuf(prsactx)) { @@ -370,14 +491,24 @@ static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen, switch (prsactx->saltlen) { case RSA_PSS_SALTLEN_DIGEST: if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) { - ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL); + ERR_raise_data(ERR_LIB_PROV, + PROV_R_PSS_SALTLEN_TOO_SMALL, + "minimum salt length set to %d, " + "but the digest only gives %d", + prsactx->min_saltlen, + EVP_MD_size(prsactx->md)); return 0; } /* FALLTHRU */ default: if (prsactx->saltlen >= 0 && prsactx->saltlen < prsactx->min_saltlen) { - ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL); + ERR_raise_data(ERR_LIB_PROV, + PROV_R_PSS_SALTLEN_TOO_SMALL, + "minimum salt length set to %d, but the" + "actual salt length is only set to %d", + prsactx->min_saltlen, + prsactx->saltlen); return 0; } break; @@ -419,6 +550,11 @@ static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen, return 1; } +static int rsa_verify_recover_init(void *vprsactx, void *vrsa) +{ + return rsa_signature_init(vprsactx, vrsa, EVP_PKEY_OP_VERIFYRECOVER); +} + static int rsa_verify_recover(void *vprsactx, unsigned char *rout, size_t *routlen, @@ -458,11 +594,15 @@ static int rsa_verify_recover(void *vprsactx, } *routlen = ret; - if (routsize < (size_t)ret) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; + if (rout != prsactx->tbuf) { + if (routsize < (size_t)ret) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL, + "buffer size is %d, should be %d", + routsize, ret); + return 0; + } + memcpy(rout, prsactx->tbuf, ret); } - memcpy(rout, prsactx->tbuf, ret); break; case RSA_PKCS1_PADDING: @@ -496,6 +636,11 @@ static int rsa_verify_recover(void *vprsactx, return 1; } +static int rsa_verify_init(void *vprsactx, void *vrsa) +{ + return rsa_signature_init(vprsactx, vrsa, EVP_PKEY_OP_VERIFY); +} + static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { @@ -512,7 +657,10 @@ static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, } return 1; case RSA_X931_PADDING: - if (rsa_verify_recover(prsactx, NULL, &rslen, 0, sig, siglen) <= 0) + if (!setup_tbuf(prsactx)) + return 0; + if (rsa_verify_recover(prsactx, prsactx->tbuf, &rslen, 0, + sig, siglen) <= 0) return 0; break; case RSA_PKCS1_PSS_PADDING: @@ -520,29 +668,6 @@ static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, int ret; size_t mdsize; - /* Check PSS restrictions */ - if (rsa_pss_restricted(prsactx)) { - switch (prsactx->saltlen) { - case RSA_PSS_SALTLEN_AUTO: - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN); - return 0; - case RSA_PSS_SALTLEN_DIGEST: - if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) { - ERR_raise(ERR_LIB_PROV, - PROV_R_PSS_SALTLEN_TOO_SMALL); - return 0; - } - /* FALLTHRU */ - default: - if (prsactx->saltlen >= 0 - && prsactx->saltlen < prsactx->min_saltlen) { - ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL); - return 0; - } - break; - } - } - /* * We need to check this for the RSA_verify_PKCS1_PSS_mgf1() * call @@ -596,18 +721,20 @@ static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, } static int rsa_digest_signverify_init(void *vprsactx, const char *mdname, - const char *props, void *vrsa) + void *vrsa, int operation) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; prsactx->flag_allow_md = 0; - if (!rsa_signature_init(vprsactx, vrsa) - || !rsa_setup_md(prsactx, mdname, props)) + if (!rsa_signature_init(vprsactx, vrsa, operation) + || !rsa_setup_md(prsactx, mdname, NULL)) /* TODO RL */ return 0; prsactx->mdctx = EVP_MD_CTX_new(); - if (prsactx->mdctx == NULL) + if (prsactx->mdctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto error; + } if (!EVP_DigestInit_ex(prsactx->mdctx, prsactx->md, NULL)) goto error; @@ -622,8 +749,9 @@ static int rsa_digest_signverify_init(void *vprsactx, const char *mdname, return 0; } -int rsa_digest_signverify_update(void *vprsactx, const unsigned char *data, - size_t datalen) +static int rsa_digest_signverify_update(void *vprsactx, + const unsigned char *data, + size_t datalen) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; @@ -633,8 +761,15 @@ int rsa_digest_signverify_update(void *vprsactx, const unsigned char *data, return EVP_DigestUpdate(prsactx->mdctx, data, datalen); } -int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, size_t *siglen, - size_t sigsize) +static int rsa_digest_sign_init(void *vprsactx, const char *mdname, + void *vrsa) +{ + return rsa_digest_signverify_init(vprsactx, mdname, vrsa, + EVP_PKEY_OP_SIGN); +} + +static int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, + size_t *siglen, size_t sigsize) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; unsigned char digest[EVP_MAX_MD_SIZE]; @@ -661,6 +796,12 @@ int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, size_t *siglen, return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen); } +static int rsa_digest_verify_init(void *vprsactx, const char *mdname, + void *vrsa) +{ + return rsa_digest_signverify_init(vprsactx, mdname, vrsa, + EVP_PKEY_OP_VERIFY); +} int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig, size_t siglen) @@ -695,6 +836,7 @@ static void rsa_freectx(void *vprsactx) EVP_MD_CTX_free(prsactx->mdctx); EVP_MD_free(prsactx->md); EVP_MD_free(prsactx->mgf1_md); + OPENSSL_free(prsactx->propq); free_tbuf(prsactx); OPENSSL_clear_free(prsactx, sizeof(prsactx)); @@ -706,8 +848,10 @@ static void *rsa_dupctx(void *vprsactx) PROV_RSA_CTX *dstctx; dstctx = OPENSSL_zalloc(sizeof(*srcctx)); - if (dstctx == NULL) + if (dstctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return NULL; + } *dstctx = *srcctx; dstctx->rsa = NULL; @@ -798,25 +942,32 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) if (!OSSL_PARAM_set_int(p, prsactx->saltlen)) return 0; } else if (p->data_type == OSSL_PARAM_UTF8_STRING) { + const char *value = NULL; + switch (prsactx->saltlen) { case RSA_PSS_SALTLEN_DIGEST: - if (!OSSL_PARAM_set_utf8_string(p, "digest")) - return 0; + value = OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST; break; case RSA_PSS_SALTLEN_MAX: - if (!OSSL_PARAM_set_utf8_string(p, "max")) - return 0; + value = OSSL_PKEY_RSA_PSS_SALT_LEN_MAX; break; case RSA_PSS_SALTLEN_AUTO: - if (!OSSL_PARAM_set_utf8_string(p, "auto")) - return 0; + value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO; break; default: - if (BIO_snprintf(p->data, p->data_size, "%d", prsactx->saltlen) - <= 0) - return 0; - break; + { + int len = BIO_snprintf(p->data, p->data_size, "%d", + prsactx->saltlen); + + if (len <= 0) + return 0; + p->return_size = len; + break; + } } + if (value != NULL + && !OSSL_PARAM_set_utf8_string(p, value)) + return 0; } } @@ -858,11 +1009,13 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname))) return 0; - if (propsp != NULL - && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops))) + + if (propsp == NULL) + pmdprops = NULL; + else if (!OSSL_PARAM_get_utf8_string(propsp, + &pmdprops, sizeof(mdprops))) return 0; - /* TODO(3.0) PSS check needs more work */ if (rsa_pss_restricted(prsactx)) { /* TODO(3.0) figure out what to do for prsactx->md == NULL */ if (prsactx->md == NULL || EVP_MD_is_a(prsactx->md, mdname)) @@ -872,13 +1025,14 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) } /* non-PSS code follows */ - if (!rsa_setup_md(prsactx, mdname, mdprops)) + if (!rsa_setup_md(prsactx, mdname, pmdprops)) return 0; } p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE); if (p != NULL) { int pad_mode = 0; + const char *err_extra_text = NULL; switch (p->data_type) { case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */ @@ -910,31 +1064,49 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) * OAEP padding is for asymmetric cipher only so is not compatible * with signature use. */ - ERR_raise_data(ERR_LIB_PROV, - PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE, - "OAEP padding not allowed for signing / verifying"); - return 0; + err_extra_text = "OAEP padding not allowed for signing / verifying"; + goto bad_pad; case RSA_PKCS1_PSS_PADDING: - if (prsactx->mdname[0] == '\0') - rsa_setup_md(prsactx, "SHA1", ""); - goto cont; + if ((prsactx->operation + & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)) == 0) { + err_extra_text = + "PSS padding only allowed for sign and verify operations"; + goto bad_pad; + } + if (prsactx->md == NULL + && !rsa_setup_md(prsactx, OSSL_DIGEST_NAME_SHA1, NULL)) { + return 0; + } + break; case RSA_PKCS1_PADDING: + err_extra_text = "PKCS#1 padding not allowed with RSA-PSS"; + goto cont; case RSA_SSLV23_PADDING: + err_extra_text = "SSLv3 padding not allowed with RSA-PSS"; + goto cont; case RSA_NO_PADDING: + err_extra_text = "No padding not allowed with RSA-PSS"; + goto cont; case RSA_X931_PADDING: - if (RSA_get0_pss_params(prsactx->rsa) != NULL) { - ERR_raise_data(ERR_LIB_PROV, - PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE, - "X.931 padding not allowed with RSA-PSS"); - return 0; - } + err_extra_text = "X.931 padding not allowed with RSA-PSS"; cont: - if (!rsa_check_padding(prsactx->mdnid, pad_mode)) - return 0; - break; + if (RSA_test_flags(prsactx->rsa, + RSA_FLAG_TYPE_MASK) == RSA_FLAG_TYPE_RSA) + break; + /* FALLTHRU */ default: + bad_pad: + if (err_extra_text == NULL) + ERR_raise(ERR_LIB_PROV, + PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); + else + ERR_raise_data(ERR_LIB_PROV, + PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE, + err_extra_text); return 0; } + if (!rsa_check_padding(prsactx->mdnid, pad_mode)) + return 0; prsactx->pad_mode = pad_mode; } @@ -955,11 +1127,11 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) return 0; break; case OSSL_PARAM_UTF8_STRING: - if (strcmp(p->data, "digest") == 0) + if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST) == 0) saltlen = RSA_PSS_SALTLEN_DIGEST; - else if (strcmp(p->data, "max") == 0) + else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX) == 0) saltlen = RSA_PSS_SALTLEN_MAX; - else if (strcmp(p->data, "auto") == 0) + else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0) saltlen = RSA_PSS_SALTLEN_AUTO; else saltlen = atoi(p->data); @@ -978,6 +1150,37 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) return 0; } + if (rsa_pss_restricted(prsactx)) { + switch (prsactx->saltlen) { + case RSA_PSS_SALTLEN_AUTO: + if (prsactx->operation == EVP_PKEY_OP_VERIFY) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN); + return 0; + } + break; + case RSA_PSS_SALTLEN_DIGEST: + if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) { + ERR_raise_data(ERR_LIB_PROV, + PROV_R_PSS_SALTLEN_TOO_SMALL, + "Should be more than %d, but would be " + "set to match digest size (%d)", + prsactx->min_saltlen, + EVP_MD_size(prsactx->md)); + return 0; + } + /* FALLTHRU */ + default: + if (saltlen >= 0 && saltlen < prsactx->min_saltlen) { + ERR_raise_data(ERR_LIB_PROV, + PROV_R_PSS_SALTLEN_TOO_SMALL, + "Should be more than %d, " + "but would be set to %d", + prsactx->min_saltlen, saltlen); + return 0; + } + } + } + prsactx->saltlen = saltlen; } @@ -991,8 +1194,11 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname))) return 0; - if (propsp != NULL - && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops))) + + if (propsp == NULL) + pmdprops = NULL; + else if (!OSSL_PARAM_get_utf8_string(propsp, + &pmdprops, sizeof(mdprops))) return 0; if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) { @@ -1000,9 +1206,8 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) return 0; } - /* TODO(3.0) PSS check needs more work */ if (rsa_pss_restricted(prsactx)) { - /* TODO(3.0) figure out what to do for prsactx->md == NULL */ + /* TODO(3.0) figure out what to do for prsactx->mgf1_md == NULL */ if (prsactx->mgf1_md == NULL || EVP_MD_is_a(prsactx->mgf1_md, mdname)) return 1; @@ -1011,7 +1216,7 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) } /* non-PSS code follows */ - if (!rsa_setup_mgf1_md(prsactx, mdname, mdprops)) + if (!rsa_setup_mgf1_md(prsactx, mdname, pmdprops)) return 0; } @@ -1081,20 +1286,22 @@ static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx) const OSSL_DISPATCH rsa_signature_functions[] = { { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx }, - { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_signature_init }, + { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_sign_init }, { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign }, - { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_signature_init }, + { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_verify_init }, { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify }, - { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, (void (*)(void))rsa_signature_init }, - { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, (void (*)(void))rsa_verify_recover }, + { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, + (void (*)(void))rsa_verify_recover_init }, + { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, + (void (*)(void))rsa_verify_recover }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, - (void (*)(void))rsa_digest_signverify_init }, + (void (*)(void))rsa_digest_sign_init }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, (void (*)(void))rsa_digest_signverify_update }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, (void (*)(void))rsa_digest_sign_final }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, - (void (*)(void))rsa_digest_signverify_init }, + (void (*)(void))rsa_digest_verify_init }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, (void (*)(void))rsa_digest_signverify_update }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,