#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
+#include <openssl/obj_mac.h>
#include <openssl/rsa.h>
#include <openssl/params.h>
#include <openssl/evp.h>
static OSSL_FUNC_signature_verify_init_fn rsa_verify_init;
static OSSL_FUNC_signature_verify_recover_init_fn rsa_verify_recover_init;
static OSSL_FUNC_signature_sign_fn rsa_sign;
+static OSSL_FUNC_signature_sign_message_update_fn rsa_signverify_message_update;
+static OSSL_FUNC_signature_sign_message_final_fn rsa_sign_message_final;
static OSSL_FUNC_signature_verify_fn rsa_verify;
static OSSL_FUNC_signature_verify_recover_fn rsa_verify_recover;
+static OSSL_FUNC_signature_verify_message_update_fn rsa_signverify_message_update;
+static OSSL_FUNC_signature_verify_message_final_fn rsa_verify_message_final;
static OSSL_FUNC_signature_digest_sign_init_fn rsa_digest_sign_init;
-static OSSL_FUNC_signature_digest_sign_update_fn rsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_sign_update_fn rsa_digest_sign_update;
static OSSL_FUNC_signature_digest_sign_final_fn rsa_digest_sign_final;
static OSSL_FUNC_signature_digest_verify_init_fn rsa_digest_verify_init;
-static OSSL_FUNC_signature_digest_verify_update_fn rsa_digest_signverify_update;
+static OSSL_FUNC_signature_digest_verify_update_fn rsa_digest_verify_update;
static OSSL_FUNC_signature_digest_verify_final_fn rsa_digest_verify_final;
static OSSL_FUNC_signature_freectx_fn rsa_freectx;
static OSSL_FUNC_signature_dupctx_fn rsa_dupctx;
+static OSSL_FUNC_signature_query_key_types_fn rsa_sigalg_query_key_types;
static OSSL_FUNC_signature_get_ctx_params_fn rsa_get_ctx_params;
static OSSL_FUNC_signature_gettable_ctx_params_fn rsa_gettable_ctx_params;
static OSSL_FUNC_signature_set_ctx_params_fn rsa_set_ctx_params;
static OSSL_FUNC_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params;
static OSSL_FUNC_signature_set_ctx_md_params_fn rsa_set_ctx_md_params;
static OSSL_FUNC_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params;
+static OSSL_FUNC_signature_set_ctx_params_fn rsa_sigalg_set_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn rsa_sigalg_settable_ctx_params;
static OSSL_ITEM padding_item[] = {
{ RSA_PKCS1_PADDING, OSSL_PKEY_RSA_PAD_MODE_PKCSV15 },
RSA *rsa;
int operation;
+ /*
+ * Flag to determine if a full sigalg is run (1) or if a composable
+ * signature algorithm is run (0).
+ *
+ * When a full sigalg is run (1), this currently affects the following
+ * other flags, which are to remain untouched after their initialization:
+ *
+ * - flag_allow_md (initialized to 0)
+ */
+ unsigned int flag_sigalg : 1;
/*
* Flag to determine if the hash function can be changed (1) or not (0)
* Because it's dangerous to change during a DigestSign or DigestVerify
* operation, this flag is cleared by their Init function, and set again
* by their Final function.
+ * Implementations of full sigalgs (such as RSA-SHA256) hard-code this
+ * flag to not allow changes (0).
*/
unsigned int flag_allow_md : 1;
unsigned int mgf1_md_set : 1;
+ /*
+ * Flags to say what are the possible next external calls in what
+ * consitutes the life cycle of an algorithm. The relevant calls are:
+ * - init
+ * - update
+ * - final
+ * - oneshot
+ * All other external calls are regarded as utilitarian and are allowed
+ * at any time (they may be affected by other flags, like flag_allow_md,
+ * though).
+ */
+ unsigned int flag_allow_update : 1;
+ unsigned int flag_allow_final : 1;
+ unsigned int flag_allow_oneshot : 1;
/* main digest */
EVP_MD *md;
/* Minimum salt length or -1 if no PSS parameter restriction */
int min_saltlen;
+ /* Signature, for verification */
+ unsigned char *sig;
+ size_t siglen;
+
/* Temp buffer */
unsigned char *tbuf;
- OSSL_FIPS_IND_DECLARE
+ OSSL_FIPS_IND_DECLARE
} PROV_RSA_CTX;
/* True if PSS parameters are restricted */
}
#ifdef FIPS_MODULE
{
- int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
+ int sha1_allowed
+ = ((ctx->operation
+ & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_SIGNMSG)) == 0);
if (!ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND_GET(ctx),
OSSL_FIPS_IND_SETTABLE1,
if (!rsa_check_padding(ctx, mdname, NULL, md_nid))
goto err;
if (mdname_len >= sizeof(ctx->mdname)) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
- "%s exceeds name buffer length", mdname);
+ ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
+ "%s exceeds name buffer length", mdname);
goto err;
}
return 1;
}
-static int rsa_signverify_init(void *vprsactx, void *vrsa,
- const OSSL_PARAM params[], int operation,
- const char *desc)
+static int
+rsa_signverify_init(void *vprsactx, void *vrsa,
+ OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params,
+ const OSSL_PARAM params[], int operation,
+ const char *desc)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int protect;
return 0;
prsactx->operation = operation;
+ prsactx->flag_allow_update = 1;
+ prsactx->flag_allow_final = 1;
+ prsactx->flag_allow_oneshot = 1;
/* Maximize up to digest length for sign, auto for verify */
prsactx->saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX;
}
OSSL_FIPS_IND_SET_APPROVED(prsactx)
- if (!rsa_set_ctx_params(prsactx, params))
+ if (!set_ctx_params(prsactx, params))
return 0;
#ifdef FIPS_MODULE
if (!ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND_GET(prsactx),
{
if (!ossl_prov_is_running())
return 0;
- return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN,
- "RSA Sign Init");
+ return rsa_signverify_init(vprsactx, vrsa, rsa_set_ctx_params, params,
+ EVP_PKEY_OP_SIGN, "RSA Sign Init");
}
-static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
- size_t sigsize, const unsigned char *tbs, size_t tbslen)
+/*
+ * Sign tbs without digesting it first. This is suitable for "primitive"
+ * signing and signing the digest of a message, i.e. should be used with
+ * implementations of the keytype related algorithms.
+ */
+static int rsa_sign_directly(void *vprsactx, unsigned char *sig, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
return 1;
}
+static int rsa_signverify_message_update(void *vprsactx,
+ const unsigned char *data,
+ size_t datalen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx == NULL || prsactx->mdctx == NULL)
+ return 0;
+
+ if (!prsactx->flag_allow_update) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER);
+ return 0;
+ }
+ prsactx->flag_allow_oneshot = 0;
+
+ return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
+}
+
+static int rsa_sign_message_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];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running() || prsactx == NULL)
+ return 0;
+ if (prsactx->mdctx == NULL)
+ return 0;
+ if (!prsactx->flag_allow_final) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER);
+ return 0;
+ }
+
+ /*
+ * If sig is NULL then we're just finding out the sig size. Other fields
+ * are ignored. Defer to rsa_sign.
+ */
+ if (sig != NULL) {
+ /*
+ * The digests used here are all known (see rsa_get_md_nid()), so they
+ * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
+ */
+ if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
+ return 0;
+
+ prsactx->flag_allow_update = 0;
+ prsactx->flag_allow_oneshot = 0;
+ prsactx->flag_allow_final = 0;
+ }
+
+ return rsa_sign_directly(vprsactx, sig, siglen, sigsize, digest, dlen);
+}
+
+/*
+ * If signing a message, digest tbs and sign the result.
+ * Otherwise, sign tbs directly.
+ */
+static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
+ size_t sigsize, const unsigned char *tbs, size_t tbslen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (!ossl_prov_is_running() || prsactx == NULL)
+ return 0;
+ if (!prsactx->flag_allow_oneshot) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER);
+ return 0;
+ }
+
+ if (prsactx->operation == EVP_PKEY_OP_SIGNMSG) {
+ /*
+ * If |sig| is NULL, the caller is only looking for the sig length.
+ * DO NOT update the input in this case.
+ */
+ if (sig == NULL)
+ return rsa_sign_message_final(prsactx, sig, siglen, sigsize);
+
+ return rsa_signverify_message_update(prsactx, tbs, tbslen)
+ && rsa_sign_message_final(prsactx, sig, siglen, sigsize);
+ }
+ return rsa_sign_directly(prsactx, sig, siglen, sigsize, tbs, tbslen);
+}
+
static int rsa_verify_recover_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
- return rsa_signverify_init(vprsactx, vrsa, params,
+ return rsa_signverify_init(vprsactx, vrsa, rsa_set_ctx_params, params,
EVP_PKEY_OP_VERIFYRECOVER, "RSA VerifyRecover Init");
}
+/*
+ * There is no message variant of verify recover, so no need for
+ * 'rsa_verify_recover_directly', just use this function, er, directly.
+ */
static int rsa_verify_recover(void *vprsactx,
- unsigned char *rout,
- size_t *routlen,
+ unsigned char *rout, size_t *routlen,
size_t routsize,
- const unsigned char *sig,
- size_t siglen)
+ const unsigned char *sig, size_t siglen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
{
if (!ossl_prov_is_running())
return 0;
- return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY,
- "RSA Verify Init");
+ return rsa_signverify_init(vprsactx, vrsa, rsa_set_ctx_params, params,
+ EVP_PKEY_OP_VERIFY, "RSA Verify Init");
}
-static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen,
- const unsigned char *tbs, size_t tbslen)
+static int rsa_verify_directly(void *vprsactx,
+ const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
size_t rslen;
return 1;
}
+static int rsa_verify_set_sig(void *vprsactx,
+ const unsigned char *sig, size_t siglen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ OSSL_PARAM params[2];
+
+ params[0] =
+ OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE,
+ (unsigned char *)sig, siglen);
+ params[1] = OSSL_PARAM_construct_end();
+ return rsa_sigalg_set_ctx_params(prsactx, params);
+}
+
+static int rsa_verify_message_final(void *vprsactx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dlen = 0;
+
+ if (!ossl_prov_is_running() || prsactx == NULL)
+ return 0;
+ if (prsactx->mdctx == NULL)
+ return 0;
+ if (!prsactx->flag_allow_final) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER);
+ return 0;
+ }
+
+ /*
+ * The digests used here are all known (see rsa_get_md_nid()), so they
+ * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
+ */
+ if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
+ return 0;
+
+ prsactx->flag_allow_update = 0;
+ prsactx->flag_allow_final = 0;
+ prsactx->flag_allow_oneshot = 0;
+
+ return rsa_verify_directly(vprsactx, prsactx->sig, prsactx->siglen,
+ digest, dlen);
+}
+
+/*
+ * If verifying a message, digest tbs and verify the result.
+ * Otherwise, verify tbs directly.
+ */
+static int rsa_verify(void *vprsactx,
+ const unsigned char *sig, size_t siglen,
+ const unsigned char *tbs, size_t tbslen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (!ossl_prov_is_running() || prsactx == NULL)
+ return 0;
+ if (!prsactx->flag_allow_oneshot) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER);
+ return 0;
+ }
+
+ if (prsactx->operation == EVP_PKEY_OP_VERIFYMSG)
+ return rsa_verify_set_sig(prsactx, sig, siglen)
+ && rsa_signverify_message_update(prsactx, tbs, tbslen)
+ && rsa_verify_message_final(prsactx);
+ return rsa_verify_directly(prsactx, sig, siglen, tbs, tbslen);
+}
+
+/* DigestSign/DigestVerify wrappers */
+
static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
void *vrsa, const OSSL_PARAM params[],
int operation, const char *desc)
if (!ossl_prov_is_running())
return 0;
- if (!rsa_signverify_init(vprsactx, vrsa, params, operation, desc))
+ if (!rsa_signverify_init(vprsactx, vrsa, rsa_set_ctx_params, params,
+ operation, desc))
return 0;
if (mdname != NULL
return 0;
}
-static int rsa_digest_signverify_update(void *vprsactx,
- const unsigned char *data,
- size_t datalen)
-{
- PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
-
- if (prsactx == NULL || prsactx->mdctx == NULL)
- return 0;
-
- return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
-}
-
static int rsa_digest_sign_init(void *vprsactx, const char *mdname,
void *vrsa, const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
- params, EVP_PKEY_OP_SIGN,
+ params, EVP_PKEY_OP_SIGNMSG,
"RSA Digest Sign Init");
}
+static int rsa_digest_sign_update(void *vprsactx, const unsigned char *data,
+ size_t datalen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx == NULL)
+ return 0;
+ /* Sigalg implementations shouldn't do digest_sign */
+ if (prsactx->flag_sigalg)
+ return 0;
+
+ return rsa_signverify_message_update(vprsactx, data, datalen);
+}
+
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];
- unsigned int dlen = 0;
+ int ok = 0;
- if (!ossl_prov_is_running() || prsactx == NULL)
+ if (prsactx == NULL)
return 0;
- prsactx->flag_allow_md = 1;
- if (prsactx->mdctx == NULL)
+ /* Sigalg implementations shouldn't do digest_sign */
+ if (prsactx->flag_sigalg)
return 0;
- /*
- * If sig is NULL then we're just finding out the sig size. Other fields
- * are ignored. Defer to rsa_sign.
- */
- if (sig != NULL) {
- /*
- * The digests used here are all known (see rsa_get_md_nid()), so they
- * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
- */
- if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
- return 0;
- }
- return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen);
+ if (rsa_sign_message_final(prsactx, sig, siglen, sigsize))
+ ok = 1;
+
+ prsactx->flag_allow_md = 1;
+
+ return ok;
}
static int rsa_digest_verify_init(void *vprsactx, const char *mdname,
if (!ossl_prov_is_running())
return 0;
return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
- params, EVP_PKEY_OP_VERIFY,
+ params, EVP_PKEY_OP_VERIFYMSG,
"RSA Digest Verify Init");
}
-int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
- size_t siglen)
+static int rsa_digest_verify_update(void *vprsactx, const unsigned char *data,
+ size_t datalen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
- unsigned char digest[EVP_MAX_MD_SIZE];
- unsigned int dlen = 0;
- if (!ossl_prov_is_running())
+ if (prsactx == NULL)
+ return 0;
+ /* Sigalg implementations shouldn't do digest_sign */
+ if (prsactx->flag_sigalg)
return 0;
+ return rsa_signverify_message_update(vprsactx, data, datalen);
+}
+
+int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
+ size_t siglen)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ int ok = 0;
+
if (prsactx == NULL)
return 0;
- prsactx->flag_allow_md = 1;
- if (prsactx->mdctx == NULL)
+ /* Sigalg implementations shouldn't do digest_verify */
+ if (prsactx->flag_sigalg)
return 0;
- /*
- * The digests used here are all known (see rsa_get_md_nid()), so they
- * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
- */
- if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
- return 0;
+ if (rsa_verify_set_sig(prsactx, sig, siglen)
+ && rsa_verify_message_final(vprsactx))
+ ok = 1;
+
+ prsactx->flag_allow_md = 1;
- return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen);
+ return ok;
}
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->sig);
OPENSSL_free(prsactx->propq);
free_tbuf(prsactx);
RSA_free(prsactx->rsa);
goto bad_pad;
case RSA_PKCS1_PSS_PADDING:
if ((prsactx->operation
- & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)) == 0) {
+ & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_SIGNMSG
+ | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYMSG)) == 0) {
err_extra_text =
"PSS padding only allowed for sign and verify operations";
goto bad_pad;
switch (saltlen) {
case RSA_PSS_SALTLEN_AUTO:
case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX:
- if (prsactx->operation == EVP_PKEY_OP_VERIFY) {
+ if ((prsactx->operation
+ & (EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYMSG)) == 0) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH,
"Cannot use autodetected salt length");
return 0;
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
(void (*)(void))rsa_digest_sign_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
- (void (*)(void))rsa_digest_signverify_update },
+ (void (*)(void))rsa_digest_sign_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
(void (*)(void))rsa_digest_sign_final },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
(void (*)(void))rsa_digest_verify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
- (void (*)(void))rsa_digest_signverify_update },
+ (void (*)(void))rsa_digest_verify_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
(void (*)(void))rsa_digest_verify_final },
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx },
(void (*)(void))rsa_settable_ctx_md_params },
OSSL_DISPATCH_END
};
+
+/* ------------------------------------------------------------------ */
+
+/*
+ * So called sigalgs (composite RSA+hash) implemented below. They
+ * are pretty much hard coded, and rely on the hash implementation
+ * being available as per what OPENSSL_NO_ macros allow.
+ */
+
+static OSSL_FUNC_signature_query_key_types_fn rsa_sigalg_query_key_types;
+static OSSL_FUNC_signature_settable_ctx_params_fn rsa_sigalg_settable_ctx_params;
+static OSSL_FUNC_signature_set_ctx_params_fn rsa_sigalg_set_ctx_params;
+
+/*
+ * rsa_sigalg_signverify_init() is almost like rsa_digest_signverify_init(),
+ * just doesn't allow fetching an MD from whatever the user chooses.
+ */
+static int rsa_sigalg_signverify_init(void *vprsactx, void *vrsa,
+ OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params,
+ const OSSL_PARAM params[],
+ const char *mdname,
+ int operation, int pad_mode,
+ const char *desc)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (!rsa_signverify_init(vprsactx, vrsa, set_ctx_params, params, operation,
+ desc))
+ return 0;
+
+ /* PSS is currently not supported as a sigalg */
+ if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) {
+ ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+
+ if (!rsa_setup_md(prsactx, mdname, NULL, desc))
+ return 0;
+
+ prsactx->pad_mode = pad_mode;
+ prsactx->flag_sigalg = 1;
+ prsactx->flag_allow_md = 0;
+
+ if (prsactx->mdctx == NULL) {
+ prsactx->mdctx = EVP_MD_CTX_new();
+ if (prsactx->mdctx == NULL)
+ goto error;
+ }
+
+ if (!EVP_DigestInit_ex2(prsactx->mdctx, prsactx->md, params))
+ goto error;
+
+ return 1;
+
+ error:
+ EVP_MD_CTX_free(prsactx->mdctx);
+ prsactx->mdctx = NULL;
+ return 0;
+}
+
+static const char **rsa_sigalg_query_key_types(void)
+{
+ static const char *keytypes[] = { "RSA", NULL };
+
+ return keytypes;
+}
+
+static const OSSL_PARAM settable_sigalg_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_sigalg_settable_ctx_params(void *vprsactx,
+ ossl_unused void *provctx)
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+ if (prsactx != NULL && prsactx->operation == EVP_PKEY_OP_VERIFYMSG)
+ return settable_sigalg_ctx_params;
+ return NULL;
+}
+
+static int rsa_sigalg_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
+{
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ const OSSL_PARAM *p;
+
+ if (prsactx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ if (prsactx->operation == EVP_PKEY_OP_VERIFYMSG) {
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE);
+ if (p != NULL) {
+ OPENSSL_free(prsactx->sig);
+ prsactx->sig = NULL;
+ prsactx->siglen = 0;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)&prsactx->sig,
+ 0, &prsactx->siglen))
+ return 0;
+ }
+ return 1;
+ }
+
+ /* Wrong operation */
+ return 0;
+}
+
+#define IMPL_RSA_SIGALG(md, MD) \
+ static OSSL_FUNC_signature_sign_init_fn rsa_##md##_sign_init; \
+ static OSSL_FUNC_signature_sign_message_init_fn \
+ rsa_##md##_sign_message_init; \
+ static OSSL_FUNC_signature_verify_init_fn rsa_##md##_verify_init; \
+ static OSSL_FUNC_signature_verify_message_init_fn \
+ rsa_##md##_verify_message_init; \
+ \
+ static int \
+ rsa_##md##_sign_init(void *vprsactx, void *vrsa, \
+ const OSSL_PARAM params[]) \
+ { \
+ static const char desc[] = "RSA Sigalg Sign Init"; \
+ \
+ return rsa_sigalg_signverify_init(vprsactx, vrsa, \
+ rsa_sigalg_set_ctx_params, \
+ params, #MD, \
+ EVP_PKEY_OP_SIGN, \
+ RSA_PKCS1_PADDING, \
+ desc); \
+ } \
+ \
+ static int \
+ rsa_##md##_sign_message_init(void *vprsactx, void *vrsa, \
+ const OSSL_PARAM params[]) \
+ { \
+ static const char desc[] = "RSA Sigalg Sign Message Init"; \
+ \
+ return rsa_sigalg_signverify_init(vprsactx, vrsa, \
+ rsa_sigalg_set_ctx_params, \
+ params, #MD, \
+ EVP_PKEY_OP_SIGNMSG, \
+ RSA_PKCS1_PADDING, \
+ desc); \
+ } \
+ \
+ static int \
+ rsa_##md##_verify_init(void *vprsactx, void *vrsa, \
+ const OSSL_PARAM params[]) \
+ { \
+ static const char desc[] = "RSA Sigalg Verify Init"; \
+ \
+ return rsa_sigalg_signverify_init(vprsactx, vrsa, \
+ rsa_sigalg_set_ctx_params, \
+ params, #MD, \
+ EVP_PKEY_OP_VERIFY, \
+ RSA_PKCS1_PADDING, \
+ desc); \
+ } \
+ \
+ static int \
+ rsa_##md##_verify_recover_init(void *vprsactx, void *vrsa, \
+ const OSSL_PARAM params[]) \
+ { \
+ static const char desc[] = "RSA Sigalg Verify Recover Init"; \
+ \
+ return rsa_sigalg_signverify_init(vprsactx, vrsa, \
+ rsa_sigalg_set_ctx_params, \
+ params, #MD, \
+ EVP_PKEY_OP_VERIFYRECOVER, \
+ RSA_PKCS1_PADDING, \
+ desc); \
+ } \
+ \
+ static int \
+ rsa_##md##_verify_message_init(void *vprsactx, void *vrsa, \
+ const OSSL_PARAM params[]) \
+ { \
+ static const char desc[] = "RSA Sigalg Verify Message Init"; \
+ \
+ return rsa_sigalg_signverify_init(vprsactx, vrsa, \
+ rsa_sigalg_set_ctx_params, \
+ params, #MD, \
+ EVP_PKEY_OP_VERIFYMSG, \
+ RSA_PKCS1_PADDING, \
+ desc); \
+ } \
+ \
+ const OSSL_DISPATCH ossl_rsa_##md##_signature_functions[] = { \
+ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx }, \
+ { OSSL_FUNC_SIGNATURE_SIGN_INIT, \
+ (void (*)(void))rsa_##md##_sign_init }, \
+ { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign }, \
+ { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, \
+ (void (*)(void))rsa_##md##_sign_message_init }, \
+ { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE, \
+ (void (*)(void))rsa_signverify_message_update }, \
+ { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL, \
+ (void (*)(void))rsa_sign_message_final }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, \
+ (void (*)(void))rsa_##md##_verify_init }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY, \
+ (void (*)(void))rsa_verify }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, \
+ (void (*)(void))rsa_##md##_verify_message_init }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE, \
+ (void (*)(void))rsa_signverify_message_update }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL, \
+ (void (*)(void))rsa_verify_message_final }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, \
+ (void (*)(void))rsa_##md##_verify_recover_init }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, \
+ (void (*)(void))rsa_verify_recover }, \
+ { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx }, \
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx }, \
+ { OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES, \
+ (void (*)(void))rsa_sigalg_query_key_types }, \
+ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \
+ (void (*)(void))rsa_get_ctx_params }, \
+ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))rsa_gettable_ctx_params }, \
+ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \
+ (void (*)(void))rsa_sigalg_set_ctx_params }, \
+ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))rsa_sigalg_settable_ctx_params }, \
+ OSSL_DISPATCH_END \
+ }
+
+#if !defined(OPENSSL_NO_RMD160) && !defined(FIPS_MODULE)
+IMPL_RSA_SIGALG(ripemd160, RIPEMD160);
+#endif
+IMPL_RSA_SIGALG(sha1, SHA1);
+IMPL_RSA_SIGALG(sha224, SHA2-224);
+IMPL_RSA_SIGALG(sha256, SHA2-256);
+IMPL_RSA_SIGALG(sha384, SHA2-384);
+IMPL_RSA_SIGALG(sha512, SHA2-512);
+IMPL_RSA_SIGALG(sha512_224, SHA2-512/224);
+IMPL_RSA_SIGALG(sha512_256, SHA2-512/256);
+IMPL_RSA_SIGALG(sha3_224, SHA3-224);
+IMPL_RSA_SIGALG(sha3_256, SHA3-256);
+IMPL_RSA_SIGALG(sha3_384, SHA3-384);
+IMPL_RSA_SIGALG(sha3_512, SHA3-512);
+#if !defined(OPENSSL_NO_SM3) && !defined(FIPS_MODULE)
+IMPL_RSA_SIGALG(sm3, SM3);
+#endif