On Wed, Jan 21, 2026 at 10:36:05PM +, David Howells wrote:
> Allow the data to be verified in a PKCS#7 or CMS message to be passed
> directly to an asymmetric cipher algorithm (e.g. ML-DSA) if it wants to do
> whatever passes for hashing/digestion itself. The normal digestion of the
> data is then skipped as that would be ignored unless another signed info in
> the message has some other algorithm that needs it.
>
> The 'data to be verified' may be the content of the PKCS#7 message or it
> will be the authenticatedAttributes (signedAttrs if CMS), modified, if
> those are present.
>
> This is done by:
>
> (1) Rename ->digest and ->digest_len to ->m and ->m_size to represent the
> input to the signature verification algorithm, reflecting that
> ->digest may no longer actually *be* a digest.
>
> (2) Make ->m and ->m_size point to the data to be verified rather than
> making public_key_verify_signature() access the data directly. This
> is so that keyctl(KEYCTL_PKEY_VERIFY) will still work.
These renames emit enough noise to be split into a separate patch.
>
> (3) Add a flag, ->algo_takes_data, to indicate that the verification
> algorithm wants to access the data to be verified directly rather than
> having it digested first.
>
> (4) If the PKCS#7 message has authenticatedAttributes (or CMS signedAtts),
> then the digest contained therein will be validated as now, and the
> modified attrs blob will either be digested or assigned to ->m as
> appropriate.
>
> (5) For ML-DSA, point ->m to the TBSCertificate instead of digesting it
> and using the digest.
>
> Note that whilst ML-DSA does allow for an "external mu", CMS doesn't yet
> have that standardised.
>
> Signed-off-by: David Howells
> cc: Lukas Wunner
> cc: Ignat Korchagin
> cc: Stephan Mueller
> cc: Eric Biggers
> cc: Herbert Xu
> cc: [email protected]
> cc: [email protected]
> ---
> crypto/asymmetric_keys/asymmetric_type.c | 4 +-
> crypto/asymmetric_keys/pkcs7_parser.c| 4 +-
> crypto/asymmetric_keys/pkcs7_verify.c| 79
> crypto/asymmetric_keys/public_key.c | 3 +-
> crypto/asymmetric_keys/signature.c | 3 +-
> crypto/asymmetric_keys/x509_public_key.c | 19 --
> include/crypto/public_key.h | 6 +-
> security/integrity/digsig_asymmetric.c | 4 +-
> 8 files changed, 79 insertions(+), 43 deletions(-)
>
> diff --git a/crypto/asymmetric_keys/asymmetric_type.c
> b/crypto/asymmetric_keys/asymmetric_type.c
> index 348966ea2175..2326743310b1 100644
> --- a/crypto/asymmetric_keys/asymmetric_type.c
> +++ b/crypto/asymmetric_keys/asymmetric_type.c
> @@ -593,10 +593,10 @@ static int asymmetric_key_verify_signature(struct
> kernel_pkey_params *params,
> {
> struct public_key_signature sig = {
> .s_size = params->in2_len,
> - .digest_size= params->in_len,
> + .m_size = params->in_len,
> .encoding = params->encoding,
> .hash_algo = params->hash_algo,
> - .digest = (void *)in,
> + .m = (void *)in,
> .s = (void *)in2,
> };
>
> diff --git a/crypto/asymmetric_keys/pkcs7_parser.c
> b/crypto/asymmetric_keys/pkcs7_parser.c
> index 423d13c47545..3cdbab3b9f50 100644
> --- a/crypto/asymmetric_keys/pkcs7_parser.c
> +++ b/crypto/asymmetric_keys/pkcs7_parser.c
> @@ -599,8 +599,8 @@ int pkcs7_sig_note_set_of_authattrs(void *context, size_t
> hdrlen,
> }
>
> /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
> - sinfo->authattrs = value - (hdrlen - 1);
> - sinfo->authattrs_len = vlen + (hdrlen - 1);
> + sinfo->authattrs = value - hdrlen;
> + sinfo->authattrs_len = vlen + hdrlen;
> return 0;
> }
>
> diff --git a/crypto/asymmetric_keys/pkcs7_verify.c
> b/crypto/asymmetric_keys/pkcs7_verify.c
> index 6d6475e3a9bf..a5b2ed4d53fd 100644
> --- a/crypto/asymmetric_keys/pkcs7_verify.c
> +++ b/crypto/asymmetric_keys/pkcs7_verify.c
> @@ -30,8 +30,18 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
>
> kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
>
> + if (!sinfo->authattrs && sig->algo_takes_data) {
> + /* There's no intermediate digest and the signature algo
> + * doesn't want the data prehashing.
> + */
> + sig->m = (void *)pkcs7->data;
> + sig->m_size = pkcs7->data_len;
> + sig->m_free = false;
> + return 0;
> + }
> +
> /* The digest was calculated already. */
> - if (sig->digest)
> + if (sig->m)
> return 0;
>
> if (!sinfo->sig->hash_algo)
> @@ -45,12 +55,13 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
> return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
>
> desc_size = crypto_shash_descsize(tfm)