]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Implement EVP_SIGNATURE_hash_message_update() and use it
authorStefan Berger <stefanb@linux.ibm.com>
Thu, 6 Nov 2025 22:16:01 +0000 (16:16 -0600)
committerTomas Mraz <tomas@openssl.org>
Tue, 18 Nov 2025 17:03:24 +0000 (18:03 +0100)
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 <stefanb@linux.ibm.com>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28923)

crypto/cms/cms_sd.c
crypto/evp/signature.c
doc/man3/EVP_SIGNATURE.pod
include/openssl/evp.h
util/libcrypto.num

index 1eb8dca646c33b75ffa3c9248939f20c154ffb08..b7134711256227c99776a09faf090d764150dce7 100644 (file)
@@ -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 {
index d01df3282fa41d694e689804ac0486396d5b32ee..195d237802ff5c1d7cba2fbe8425355f2174f722 100644 (file)
@@ -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;
index cf476d1453152b2ec652f441b06e3f5683233eb6..8d3d61517b4edc0db88c124aba7b33e3d450e3d0 100644 (file)
@@ -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<OSSL_PARAM(3)> array that describes the names and types of k
 parameters that can be retrieved or set by a signature algorithm using
 L<EVP_PKEY_CTX_get_params(3)> and L<EVP_PKEY_CTX_set_params(3)>.
 
+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<EVP_SIGNATURE> 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<OSSL_PARAM(3)> 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<crypto(7)/ALGORITHM FETCHING>, L<OSSL_PROVIDER(3)>
 
 =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
 
index 61e50b266d62dbd7c9d55ae2f4e458c78396832b..ff82695c993c03856dcb67ac22990f34017a237d 100644 (file)
@@ -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);
index 67aa2cb5b9ca1e740985efd6011b6893c9337a35..1cf60c7e848b22509a3e2b3f275b78e64d9bea09 100644 (file)
@@ -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: