From 28a9d0e52d2ed8c330e8767403966eccdeb4f4a0 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 6 Nov 2025 16:16:01 -0600 Subject: [PATCH] Implement EVP_SIGNATURE_hash_message_update() and use it Implement EVP_SIGNATURE_hash_message_update() to check for support of EVP_PKEY_sign_message_update() and EVP_PKEY_verify_message_update() and use this function to replace the has_msg_update column in CMS. Signed-off-by: Stefan Berger Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/28923) --- crypto/cms/cms_sd.c | 52 ++++++++++++++++++-------------------- crypto/evp/signature.c | 6 +++++ doc/man3/EVP_SIGNATURE.pod | 13 ++++++++-- include/openssl/evp.h | 1 + util/libcrypto.num | 1 + 5 files changed, 43 insertions(+), 30 deletions(-) diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 1eb8dca646c..b7134711256 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -347,39 +347,35 @@ static const struct { int md_a_must; /* md is a 'MUST' */ int noattr_md_nid; /* in case of 'without signed attributes' */ int noattr_md_a_must; /* noattr_md is a 'MUST' not a 'SHOULD' */ - int has_msg_update; } key2data[] = { - { "ML-DSA-44", NID_shake256, 0, NID_sha512, 0, 1, }, - { "ML-DSA-65", NID_shake256, 0, NID_sha512, 0, 1, }, - { "ML-DSA-87", NID_shake256, 0, NID_sha512, 0, 1, }, - { "ED25519", NID_sha512, 0, NID_sha512, 1, 0, }, /* RFC 8419 */ + { "ML-DSA-44", NID_shake256, 0, NID_sha512, 0, }, + { "ML-DSA-65", NID_shake256, 0, NID_sha512, 0, }, + { "ML-DSA-87", NID_shake256, 0, NID_sha512, 0, }, + { "ED25519", NID_sha512, 0, NID_sha512, 1, }, /* RFC 8419 */ /* RFC 8419 3.1 ED448: id-shake256-len MUST be used => NID_undef for now */ - { "ED448", NID_undef, 1, NID_shake256, 1, 0, }, - { "SLH-DSA-SHA2-128f", NID_sha256, 0, NID_sha256, 0, 0, }, /* RFC 9814 */ - { "SLH-DSA-SHA2-128s", NID_sha256, 0, NID_sha256, 0, 0, }, - { "SLH-DSA-SHA2-192f", NID_sha512, 0, NID_sha512, 0, 0, }, - { "SLH-DSA-SHA2-192s", NID_sha512, 0, NID_sha512, 0, 0, }, - { "SLH-DSA-SHA2-256f", NID_sha512, 0, NID_sha512, 0, 0, }, - { "SLH-DSA-SHA2-256s", NID_sha512, 0, NID_sha512, 0, 0, }, - { "SLH-DSA-SHAKE-128f", NID_shake128, 0, NID_shake128, 0, 0, }, - { "SLH-DSA-SHAKE-128s", NID_shake128, 0, NID_shake128, 0, 0, }, - { "SLH-DSA-SHAKE-192f", NID_shake256, 0, NID_shake256, 0, 0, }, - { "SLH-DSA-SHAKE-192s", NID_shake256, 0, NID_shake256, 0, 0, }, - { "SLH-DSA-SHAKE-256f", NID_shake256, 0, NID_shake256, 0, 0, }, - { "SLH-DSA-SHAKE-256s", NID_shake256, 0, NID_shake256, 0, 0, }, - { NULL, NID_undef, 0, NID_undef, 0, 0, } /* last */ + { "ED448", NID_undef, 1, NID_shake256, 1, }, + { "SLH-DSA-SHA2-128f", NID_sha256, 0, NID_sha256, 0, }, /* RFC 9814 */ + { "SLH-DSA-SHA2-128s", NID_sha256, 0, NID_sha256, 0, }, + { "SLH-DSA-SHA2-192f", NID_sha512, 0, NID_sha512, 0, }, + { "SLH-DSA-SHA2-192s", NID_sha512, 0, NID_sha512, 0, }, + { "SLH-DSA-SHA2-256f", NID_sha512, 0, NID_sha512, 0, }, + { "SLH-DSA-SHA2-256s", NID_sha512, 0, NID_sha512, 0, }, + { "SLH-DSA-SHAKE-128f", NID_shake128, 0, NID_shake128, 0, }, + { "SLH-DSA-SHAKE-128s", NID_shake128, 0, NID_shake128, 0, }, + { "SLH-DSA-SHAKE-192f", NID_shake256, 0, NID_shake256, 0, }, + { "SLH-DSA-SHAKE-192s", NID_shake256, 0, NID_shake256, 0, }, + { "SLH-DSA-SHAKE-256f", NID_shake256, 0, NID_shake256, 0, }, + { "SLH-DSA-SHAKE-256s", NID_shake256, 0, NID_shake256, 0, }, + { NULL, NID_undef, 0, NID_undef, 0, } /* last */ }; -static const char *cms_mdless_signing(EVP_PKEY *pkey, - int *has_msg_update) +static const char *cms_mdless_signing(EVP_PKEY *pkey) { unsigned int i; for (i = 0; key2data[i].name; i++) { - if (EVP_PKEY_is_a(pkey, key2data[i].name)) { - *has_msg_update = key2data[i].has_msg_update; + if (EVP_PKEY_is_a(pkey, key2data[i].name)) return key2data[i].name; - } } return NULL; } @@ -1020,8 +1016,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, if (siglen == 0 || (sig = OPENSSL_malloc(siglen)) == NULL) goto err; - if ((algorithm = cms_mdless_signing(si->pkey, - &has_msg_update)) != NULL) { + if ((algorithm = cms_mdless_signing(si->pkey)) != NULL) { size_t sig_len; if (!data) { @@ -1041,6 +1036,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, goto err; sig_len = siglen; + has_msg_update = EVP_SIGNATURE_has_message_update(sig_alg); if (cms_EVP_PKEY_sign(pctx, data, sig, &sig_len, has_msg_update) != 1) goto err; @@ -1337,8 +1333,7 @@ int CMS_SignerInfo_verify_ex(CMS_SignerInfo *si, BIO *chain, BIO *data) if (pkctx == NULL) goto err; - if ((algorithm = cms_mdless_signing(si->pkey, - &has_msg_update)) != NULL) { + if ((algorithm = cms_mdless_signing(si->pkey)) != NULL) { if (!data) { ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT); goto err; @@ -1350,6 +1345,7 @@ int CMS_SignerInfo_verify_ex(CMS_SignerInfo *si, BIO *chain, BIO *data) if (EVP_PKEY_verify_message_init(pkctx, sig_alg, NULL) != 1) goto err; + has_msg_update = EVP_SIGNATURE_has_message_update(sig_alg); r = cms_EVP_PKEY_verify(pkctx, data, si->signature->data, si->signature->length, has_msg_update); } else { diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index d01df3282fa..195d237802f 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -510,6 +510,12 @@ int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name) && evp_is_a(signature->prov, signature->name_id, NULL, name); } +int EVP_SIGNATURE_has_message_update(const EVP_SIGNATURE *signature) +{ + return signature->verify_message_update != NULL + && signature->sign_message_update != NULL; +} + int evp_signature_get_number(const EVP_SIGNATURE *signature) { return signature->name_id; diff --git a/doc/man3/EVP_SIGNATURE.pod b/doc/man3/EVP_SIGNATURE.pod index cf476d14531..8d3d61517b4 100644 --- a/doc/man3/EVP_SIGNATURE.pod +++ b/doc/man3/EVP_SIGNATURE.pod @@ -7,7 +7,8 @@ EVP_SIGNATURE_fetch, EVP_SIGNATURE_free, EVP_SIGNATURE_up_ref, EVP_SIGNATURE_is_a, EVP_SIGNATURE_get0_provider, EVP_SIGNATURE_do_all_provided, EVP_SIGNATURE_names_do_all, EVP_SIGNATURE_get0_name, EVP_SIGNATURE_get0_description, -EVP_SIGNATURE_gettable_ctx_params, EVP_SIGNATURE_settable_ctx_params +EVP_SIGNATURE_gettable_ctx_params, EVP_SIGNATURE_settable_ctx_params, +EVP_SIGNATURE_has_message_update - Functions to manage EVP_SIGNATURE algorithm objects =head1 SYNOPSIS @@ -34,6 +35,7 @@ EVP_SIGNATURE_gettable_ctx_params, EVP_SIGNATURE_settable_ctx_params const char *EVP_SIGNATURE_get0_description(const EVP_SIGNATURE *signature); const OSSL_PARAM *EVP_SIGNATURE_gettable_ctx_params(const EVP_SIGNATURE *sig); const OSSL_PARAM *EVP_SIGNATURE_settable_ctx_params(const EVP_SIGNATURE *sig); + int EVP_SIGNATURE_has_message_update(const EVP_SIGNATURE *sig); =head1 DESCRIPTION @@ -83,6 +85,9 @@ return a constant L array that describes the names and types of k parameters that can be retrieved or set by a signature algorithm using L and L. +EVP_SIGNATURE_has_message_update() checks whether EVP_PKEY_sign_message_update() +and EVP_PKEY_verify_message_update() are both supported. + =head1 RETURN VALUES EVP_SIGNATURE_fetch() returns a pointer to an B for success @@ -96,13 +101,17 @@ A return value of 0 means that the callback was not called for any names. EVP_SIGNATURE_gettable_ctx_params() and EVP_SIGNATURE_settable_ctx_params() return a constant L array or NULL on error. +EVP_SIGNATURE_has_message_update() returns 1 if EVP_PKEY_sign_message_update() +and EVP_PKEY_verify_message_update() are both supported, 0 otherwise. + =head1 SEE ALSO L, L =head1 HISTORY -The functions described here were added in OpenSSL 3.0. +Most functions described here were added in OpenSSL 3.0, except for +EVP_PKEY_verify_message_update(), which was added in OpenSSL 4.0. =head1 COPYRIGHT diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 61e50b266d6..ff82695c993 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1982,6 +1982,7 @@ int EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature, void *data); const OSSL_PARAM *EVP_SIGNATURE_gettable_ctx_params(const EVP_SIGNATURE *sig); const OSSL_PARAM *EVP_SIGNATURE_settable_ctx_params(const EVP_SIGNATURE *sig); +int EVP_SIGNATURE_has_message_update(const EVP_SIGNATURE *sig); void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher); int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher); diff --git a/util/libcrypto.num b/util/libcrypto.num index 67aa2cb5b9c..1cf60c7e848 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5945,3 +5945,4 @@ OPENSSL_timegm ? 4_0_0 EXIST::FUNCTION: OSSL_PARAM_clear_free ? 4_0_0 EXIST::FUNCTION: CMS_dataFinal_ex ? 4_0_0 EXIST::FUNCTION:CMS CMS_SignerInfo_verify_ex ? 4_0_0 EXIST::FUNCTION:CMS +EVP_SIGNATURE_has_message_update ? 4_0_0 EXIST::FUNCTION: -- 2.47.3