Re: [PATCH v14 3/5] pkcs7: Allow the signing algo to do whatever digestion it wants itself

2026-01-26 Thread David Howells
Jarkko Sakkinen  wrote:

> >  (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.
> ...
> These renames emit enough noise to be split into a separate patch.

Yeah, I had considered that, so I've now done that.

> > +   if (sig->algo_takes_data) {
> > +   sig->m_size = sinfo->authattrs_len;
> > +   memcpy(sig->m, sinfo->authattrs, sinfo->authattrs_len);
> > +   sig->m[0] = ASN1_CONS_BIT | ASN1_SET;
> > +   ret = 0;
> > +   } else {
> > +   u8 tag = ASN1_CONS_BIT | ASN1_SET;
> > +
> > +   ret = crypto_shash_init(desc);
> > +   if (ret < 0)
> > +   goto error;
> > +   ret = crypto_shash_update(desc, &tag, 1);
> > +   if (ret < 0)
> > +   goto error;
> > +   ret = crypto_shash_finup(desc, sinfo->authattrs + 1,
> > +sinfo->authattrs_len - 1,
> > +sig->m);
> > +   if (ret < 0)
> > +   goto error;
> > +   }

Thinking further on this, I think it's better just to do the copy and modify
unconditionally and then in the second case here just call
crypto_hash_digest().  That means we end up doing a single crypto call on an
aligned buffer.  It's not like expect the authattrs to be particularly big for
an RSA signature.

David




Re: [PATCH v14 3/5] pkcs7: Allow the signing algo to do whatever digestion it wants itself

2026-01-25 Thread Jarkko Sakkinen
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)