Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-07-05 Thread Mimi Zohar
On Tue, 2017-07-04 at 23:22 -0300, Thiago Jung Bauermann wrote:
> Mimi Zohar  writes:
> 
> > On Wed, 2017-06-21 at 14:45 -0300, Thiago Jung Bauermann wrote:
> >> Mimi Zohar  writes:
> >> > On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> >> >> @@ -267,11 +276,18 @@ int ima_appraise_measurement(enum ima_hooks func,
> >> >> status = INTEGRITY_PASS;
> >> >> break;
> >> >> case EVM_IMA_XATTR_DIGSIG:
> >> >> +   case IMA_MODSIG:
> >> >> iint->flags |= IMA_DIGSIG;
> >> >> -   rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
> >> >> -(const char *)xattr_value, 
> >> >> rc,
> >> >> -iint->ima_hash->digest,
> >> >> -iint->ima_hash->length);
> >> >> +
> >> >> +   if (xattr_value->type == EVM_IMA_XATTR_DIGSIG)
> >> >> +   rc = 
> >> >> integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
> >> >> +(const char 
> >> >> *)xattr_value,
> >> >> +rc, 
> >> >> iint->ima_hash->digest,
> >> >> +
> >> >> iint->ima_hash->length);
> >> >> +   else
> >> >> +   rc = ima_modsig_verify(INTEGRITY_KEYRING_IMA,
> >> >> +  xattr_value);
> >> >> +
> >> >
> >> > Perhaps allowing IMA_MODSIG to flow into EVM_IMA_XATTR_DIGSIG on
> >> > failure, would help restore process_measurements() to the way it was.
> >> > Further explanation below.
> >> 
> >> It's not possible to simply flow into EVM_IMA_XATTR_DIGSIG on failure
> >> because after calling ima_read_xattr we need to run again all the logic
> >> before the switch statement. Instead, I'm currently testing the
> >> following change for v3, what do you think?
> >
> > I don't think we can assume that the same algorithm will be used for
> > signing the kernel image. Different entities would be signing the
> > kernel image with different requirements.
> >
> > Suppose for example a stock distro image comes signed using one
> > algorithm (appended signature), but the same kernel image is locally
> > signed using a different algorithm (xattr). Signature verification is
> > dependent on either the distro or local public key being loaded onto
> > the IMA keyring.
> 
> This example is good, but it raises one question: should the xattr
> signature cover the entire contents of the stock distro image (i.e.,
> also cover the appended signature), or should it ignore the appended
> signature and thus cover the same contents that the appended signature
> covers?
> 
> If the former, then we can't reuse the iint->ima_hash that was collected
> when trying to verify the appended signature because it doesn't cover
> the appended signature itself and won't match the hash expected by the
> xattr signature.
> 
> If the latter, then evmctl ima_sign needs to be modified to check
> whether there's an appended signature in the given file and ignore it
> when calculating the xattr signature.
> 
> Which is better?

I realize that having the same file hash for both the appended
signature and extended attribute would make things a lot easier, but
security.ima is a signature of the file as written to disk, meaning it
would include any appended signature

> 
> >> >> @@ -226,30 +282,23 @@ static int process_measurement(struct file *file, 
> >> >> char *buf, loff_t size,
> >> >> goto out_digsig;
> >> >> }
> >> >> 
> >> >> -   template_desc = ima_template_desc_current();
> >> >> -   if ((action & IMA_APPRAISE_SUBMASK) ||
> >> >> -   strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) 
> >> >> != 0)
> >> >> -   /* read 'security.ima' */
> >> >> -   xattr_len = ima_read_xattr(file_dentry(file), 
> >> >> _value);
> >> >> -
> >> >> -   hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
> >> >> -
> >> >> -   rc = ima_collect_measurement(iint, file, buf, size, hash_algo);
> >> >> -   if (rc != 0) {
> >> >> -   if (file->f_flags & O_DIRECT)
> >> >> -   rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : 
> >> >> -EACCES;
> >> >> -   goto out_digsig;
> >> >> -   }
> >> >> -
> >> >
> >> > There are four stages: collect measurement, store measurement,
> >> > appraise measurement and audit measurement. "Collect" needs to be
> >> > done if any one of the other stages is needed.
> >> >
> >> >> if (!pathbuf)   /* ima_rdwr_violation possibly pre-fetched */
> >> >> pathname = ima_d_path(>f_path, , 
> >> >> filename);
> >> >> 
> >> >> +   if (iint->flags & IMA_MODSIG_ALLOWED)
> >> >> +   rc = measure_and_appraise(file, buf, size, func, 
> >> >> opened, 

Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-07-04 Thread Thiago Jung Bauermann

Mimi Zohar  writes:

> On Wed, 2017-06-21 at 14:45 -0300, Thiago Jung Bauermann wrote:
>> Mimi Zohar  writes:
>> > On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
>> >> @@ -267,11 +276,18 @@ int ima_appraise_measurement(enum ima_hooks func,
>> >>   status = INTEGRITY_PASS;
>> >>   break;
>> >>   case EVM_IMA_XATTR_DIGSIG:
>> >> + case IMA_MODSIG:
>> >>   iint->flags |= IMA_DIGSIG;
>> >> - rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
>> >> -  (const char *)xattr_value, rc,
>> >> -  iint->ima_hash->digest,
>> >> -  iint->ima_hash->length);
>> >> +
>> >> + if (xattr_value->type == EVM_IMA_XATTR_DIGSIG)
>> >> + rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
>> >> +  (const char *)xattr_value,
>> >> +  rc, iint->ima_hash->digest,
>> >> +  iint->ima_hash->length);
>> >> + else
>> >> + rc = ima_modsig_verify(INTEGRITY_KEYRING_IMA,
>> >> +xattr_value);
>> >> +
>> >
>> > Perhaps allowing IMA_MODSIG to flow into EVM_IMA_XATTR_DIGSIG on
>> > failure, would help restore process_measurements() to the way it was.
>> > Further explanation below.
>> 
>> It's not possible to simply flow into EVM_IMA_XATTR_DIGSIG on failure
>> because after calling ima_read_xattr we need to run again all the logic
>> before the switch statement. Instead, I'm currently testing the
>> following change for v3, what do you think?
>
> I don't think we can assume that the same algorithm will be used for
> signing the kernel image. Different entities would be signing the
> kernel image with different requirements.
>
> Suppose for example a stock distro image comes signed using one
> algorithm (appended signature), but the same kernel image is locally
> signed using a different algorithm (xattr). Signature verification is
> dependent on either the distro or local public key being loaded onto
> the IMA keyring.

This example is good, but it raises one question: should the xattr
signature cover the entire contents of the stock distro image (i.e.,
also cover the appended signature), or should it ignore the appended
signature and thus cover the same contents that the appended signature
covers?

If the former, then we can't reuse the iint->ima_hash that was collected
when trying to verify the appended signature because it doesn't cover
the appended signature itself and won't match the hash expected by the
xattr signature.

If the latter, then evmctl ima_sign needs to be modified to check
whether there's an appended signature in the given file and ignore it
when calculating the xattr signature.

Which is better?

>> >> @@ -226,30 +282,23 @@ static int process_measurement(struct file *file, 
>> >> char *buf, loff_t size,
>> >>   goto out_digsig;
>> >>   }
>> >> 
>> >> - template_desc = ima_template_desc_current();
>> >> - if ((action & IMA_APPRAISE_SUBMASK) ||
>> >> - strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
>> >> - /* read 'security.ima' */
>> >> - xattr_len = ima_read_xattr(file_dentry(file), _value);
>> >> -
>> >> - hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
>> >> -
>> >> - rc = ima_collect_measurement(iint, file, buf, size, hash_algo);
>> >> - if (rc != 0) {
>> >> - if (file->f_flags & O_DIRECT)
>> >> - rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
>> >> - goto out_digsig;
>> >> - }
>> >> -
>> >
>> > There are four stages: collect measurement, store measurement,
>> > appraise measurement and audit measurement. "Collect" needs to be
>> > done if any one of the other stages is needed.
>> >
>> >>   if (!pathbuf)   /* ima_rdwr_violation possibly pre-fetched */
>> >>   pathname = ima_d_path(>f_path, , filename);
>> >> 
>> >> + if (iint->flags & IMA_MODSIG_ALLOWED)
>> >> + rc = measure_and_appraise(file, buf, size, func, opened, action,
>> >> +   iint, _value, _len,
>> >> +   pathname, true);
>> >> + if (!xattr_len)
>> >> + rc = measure_and_appraise(file, buf, size, func, opened, action,
>> >> +   iint, _value, _len,
>> >> +   pathname, false);
>> >
>> > I would rather see "collect" extended to support an appended signature
>> > rather than trying to combine "collect" and "appraise" together.
>> 
>> I'm not sure I understand what you mean by "extend collect to support an
>> appended signature", but the fundamental problem is that we don't know
>> whether we need to fallback to the xattr sig until the appraise step
>> because that's when we verify the signature, and by 

Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-06-21 Thread Mimi Zohar
On Wed, 2017-06-21 at 14:45 -0300, Thiago Jung Bauermann wrote:
> Hello Mimi,
> 
> Thanks for your review, and for queuing the other patches in this series.
> 
> Mimi Zohar  writes:
> > On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> >> This patch introduces the modsig keyword to the IMA policy syntax to
> >> specify that a given hook should expect the file to have the IMA signature
> >> appended to it.
> >
> > Thank you, Thiago. Appended signatures seem to be working proper now
> > with multiple keys on the IMA keyring.
> 
> Great news!
> 
> > The length of this patch description is a good indication that this
> > patch needs to be broken up for easier review. A few
> > comments/suggestions inline below.
> 
> Ok, I will try to break it up, and also patch 5 as you suggested.
> 
> >> diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
> >> index 06554c448dce..9190c9058f4f 100644
> >> --- a/security/integrity/digsig.c
> >> +++ b/security/integrity/digsig.c
> >> @@ -48,11 +48,10 @@ static bool init_keyring __initdata;
> >>  #define restrict_link_to_ima restrict_link_by_builtin_trusted
> >>  #endif
> >> 
> >> -int integrity_digsig_verify(const unsigned int id, const char *sig, int 
> >> siglen,
> >> -  const char *digest, int digestlen)
> >> +struct key *integrity_keyring_from_id(const unsigned int id)
> >>  {
> >> -  if (id >= INTEGRITY_KEYRING_MAX || siglen < 2)
> >> -  return -EINVAL;
> >> +  if (id >= INTEGRITY_KEYRING_MAX)
> >> +  return ERR_PTR(-EINVAL);
> >> 
> >
> > When splitting up this patch, the addition of this new function could
> > be a separate patch. The patch description would explain the need for
> > a new function.
> 
> Ok, will do for v3.
> 
> >> @@ -229,10 +234,14 @@ int ima_appraise_measurement(enum ima_hooks func,
> >>goto out;
> >>}
> >> 
> >> -  status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> >> -  if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
> >> -  if ((status == INTEGRITY_NOLABEL)
> >> -  || (status == INTEGRITY_NOXATTRS))
> >> +  /* Appended signatures aren't protected by EVM. */
> >> +  status = evm_verifyxattr(dentry, XATTR_NAME_IMA,
> >> +   xattr_value->type == IMA_MODSIG ?
> >> +   NULL : xattr_value, rc, iint);
> >> +  if (status != INTEGRITY_PASS && status != INTEGRITY_UNKNOWN &&
> >> +  !(xattr_value->type == IMA_MODSIG &&
> >> +(status == INTEGRITY_NOLABEL || status == INTEGRITY_NOXATTRS))) {
> >
> > This was messy to begin with, and now it is even more messy. For
> > appended signatures, we're only interested in INTEGRITY_FAIL. Maybe
> > leave the existing "if" clause alone and define a new "if" clause.
> 
> Ok, is this what you had in mind?
> 
> @@ -229,8 +237,14 @@ int ima_appraise_measurement(enum ima_hooks func,
>   goto out;
>   }
> 
> - status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> - if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
> + /* Appended signatures aren't protected by EVM. */
> + status = evm_verifyxattr(dentry, XATTR_NAME_IMA,
> +  xattr_value->type == IMA_MODSIG ?
> +  NULL : xattr_value, rc, iint);

Yes, maybe add a comment here indicating only verifying other security
xattrs, if they exist.

> + if (xattr_value->type == IMA_MODSIG && status == INTEGRITY_FAIL) {
> + cause = "invalid-HMAC";
> + goto out;
> + } else if (status != INTEGRITY_PASS && status != INTEGRITY_UNKNOWN) {
>   if ((status == INTEGRITY_NOLABEL)
>   || (status == INTEGRITY_NOXATTRS))
>   cause = "missing-HMAC";

> 
> >> @@ -267,11 +276,18 @@ int ima_appraise_measurement(enum ima_hooks func,
> >>status = INTEGRITY_PASS;
> >>break;
> >>case EVM_IMA_XATTR_DIGSIG:
> >> +  case IMA_MODSIG:
> >>iint->flags |= IMA_DIGSIG;
> >> -  rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
> >> -   (const char *)xattr_value, rc,
> >> -   iint->ima_hash->digest,
> >> -   iint->ima_hash->length);
> >> +
> >> +  if (xattr_value->type == EVM_IMA_XATTR_DIGSIG)
> >> +  rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
> >> +   (const char *)xattr_value,
> >> +   rc, iint->ima_hash->digest,
> >> +   iint->ima_hash->length);
> >> +  else
> >> +  rc = ima_modsig_verify(INTEGRITY_KEYRING_IMA,
> >> + xattr_value);
> >> +
> >
> > Perhaps allowing IMA_MODSIG to flow into EVM_IMA_XATTR_DIGSIG 

Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-06-21 Thread Thiago Jung Bauermann

Hello Mimi,

Thanks for your review, and for queuing the other patches in this series.

Mimi Zohar  writes:
> On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
>> This patch introduces the modsig keyword to the IMA policy syntax to
>> specify that a given hook should expect the file to have the IMA signature
>> appended to it.
>
> Thank you, Thiago. Appended signatures seem to be working proper now
> with multiple keys on the IMA keyring.

Great news!

> The length of this patch description is a good indication that this
> patch needs to be broken up for easier review. A few
> comments/suggestions inline below.

Ok, I will try to break it up, and also patch 5 as you suggested.

>> diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
>> index 06554c448dce..9190c9058f4f 100644
>> --- a/security/integrity/digsig.c
>> +++ b/security/integrity/digsig.c
>> @@ -48,11 +48,10 @@ static bool init_keyring __initdata;
>>  #define restrict_link_to_ima restrict_link_by_builtin_trusted
>>  #endif
>> 
>> -int integrity_digsig_verify(const unsigned int id, const char *sig, int 
>> siglen,
>> -const char *digest, int digestlen)
>> +struct key *integrity_keyring_from_id(const unsigned int id)
>>  {
>> -if (id >= INTEGRITY_KEYRING_MAX || siglen < 2)
>> -return -EINVAL;
>> +if (id >= INTEGRITY_KEYRING_MAX)
>> +return ERR_PTR(-EINVAL);
>> 
>
> When splitting up this patch, the addition of this new function could
> be a separate patch. The patch description would explain the need for
> a new function.

Ok, will do for v3.

>> @@ -229,10 +234,14 @@ int ima_appraise_measurement(enum ima_hooks func,
>>  goto out;
>>  }
>> 
>> -status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
>> -if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
>> -if ((status == INTEGRITY_NOLABEL)
>> -|| (status == INTEGRITY_NOXATTRS))
>> +/* Appended signatures aren't protected by EVM. */
>> +status = evm_verifyxattr(dentry, XATTR_NAME_IMA,
>> + xattr_value->type == IMA_MODSIG ?
>> + NULL : xattr_value, rc, iint);
>> +if (status != INTEGRITY_PASS && status != INTEGRITY_UNKNOWN &&
>> +!(xattr_value->type == IMA_MODSIG &&
>> +  (status == INTEGRITY_NOLABEL || status == INTEGRITY_NOXATTRS))) {
>
> This was messy to begin with, and now it is even more messy. For
> appended signatures, we're only interested in INTEGRITY_FAIL. Maybe
> leave the existing "if" clause alone and define a new "if" clause.

Ok, is this what you had in mind?

@@ -229,8 +237,14 @@ int ima_appraise_measurement(enum ima_hooks func,
goto out;
}
 
-   status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-   if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
+   /* Appended signatures aren't protected by EVM. */
+   status = evm_verifyxattr(dentry, XATTR_NAME_IMA,
+xattr_value->type == IMA_MODSIG ?
+NULL : xattr_value, rc, iint);
+   if (xattr_value->type == IMA_MODSIG && status == INTEGRITY_FAIL) {
+   cause = "invalid-HMAC";
+   goto out;
+   } else if (status != INTEGRITY_PASS && status != INTEGRITY_UNKNOWN) {
if ((status == INTEGRITY_NOLABEL)
|| (status == INTEGRITY_NOXATTRS))
cause = "missing-HMAC";

>> @@ -267,11 +276,18 @@ int ima_appraise_measurement(enum ima_hooks func,
>>  status = INTEGRITY_PASS;
>>  break;
>>  case EVM_IMA_XATTR_DIGSIG:
>> +case IMA_MODSIG:
>>  iint->flags |= IMA_DIGSIG;
>> -rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
>> - (const char *)xattr_value, rc,
>> - iint->ima_hash->digest,
>> - iint->ima_hash->length);
>> +
>> +if (xattr_value->type == EVM_IMA_XATTR_DIGSIG)
>> +rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
>> + (const char *)xattr_value,
>> + rc, iint->ima_hash->digest,
>> + iint->ima_hash->length);
>> +else
>> +rc = ima_modsig_verify(INTEGRITY_KEYRING_IMA,
>> +   xattr_value);
>> +
>
> Perhaps allowing IMA_MODSIG to flow into EVM_IMA_XATTR_DIGSIG on
> failure, would help restore process_measurements() to the way it was.
> Further explanation below.

It's not possible to simply flow into EVM_IMA_XATTR_DIGSIG on failure
because after calling ima_read_xattr we need to run again all the logic
before the switch 

Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-06-14 Thread Mimi Zohar
Hi Thiago,

On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> This patch introduces the modsig keyword to the IMA policy syntax to
> specify that a given hook should expect the file to have the IMA signature
> appended to it. Here is how it can be used in a rule:
> 
> appraise func=KEXEC_KERNEL_CHECK appraise_type=modsig|imasig
> 
> With this rule, IMA will accept either an appended signature or a signature
> stored in the extended attribute. In that case, it will first check whether
> there is an appended signature, and if not it will read it from the
> extended attribute.
> 
> The format of the appended signature is the same used for signed kernel
> modules. This means that the file can be signed with the scripts/sign-file
> tool, with a command line such as this:
> 
> $ sign-file sha256 privkey_ima.pem x509_ima.der vmlinux
> 
> This code only works for files that are hashed from a memory buffer, not
> for files that are read from disk at the time of hash calculation. In other
> words, only hooks that use kernel_read_file can support appended
> signatures. This means that only FIRMWARE_CHECK, KEXEC_KERNEL_CHECK,
> KEXEC_INITRAMFS_CHECK and POLICY_CHECK can be supported.
> 
> This feature warrants a separate config option because it depends on many
> other config options:
> 
>  ASYMMETRIC_KEY_TYPE n -> y
>  CRYPTO_RSA n -> y
>  INTEGRITY_SIGNATURE n -> y
>  MODULE_SIG_FORMAT n -> y
>  SYSTEM_DATA_VERIFICATION n -> y
> +ASN1 y
> +ASYMMETRIC_PUBLIC_KEY_SUBTYPE y
> +CLZ_TAB y
> +CRYPTO_AKCIPHER y
> +IMA_APPRAISE_MODSIG y
> +IMA_TRUSTED_KEYRING n
> +INTEGRITY_ASYMMETRIC_KEYS y
> +INTEGRITY_TRUSTED_KEYRING n
> +MPILIB y
> +OID_REGISTRY y
> +PKCS7_MESSAGE_PARSER y
> +PKCS7_TEST_KEY n
> +SECONDARY_TRUSTED_KEYRING n
> +SIGNATURE y
> +SIGNED_PE_FILE_VERIFICATION n
> +SYSTEM_EXTRA_CERTIFICATE n
> +SYSTEM_TRUSTED_KEYRING y
> +SYSTEM_TRUSTED_KEYS ""
> +X509_CERTIFICATE_PARSER y
> 
> The change in CONFIG_INTEGRITY_SIGNATURE to select CONFIG_KEYS instead of
> depending on it is to avoid a dependency recursion in
> CONFIG_IMA_APPRAISE_MODSIG, because CONFIG_MODULE_SIG_FORMAT selects
> CONFIG_KEYS and Kconfig complains that CONFIG_INTEGRITY_SIGNATURE depends
> on it.
> 
> Signed-off-by: Thiago Jung Bauermann 

Thank you, Thiago.  Appended signatures seem to be working proper now
with multiple keys on the IMA keyring.

The length of this patch description is a good indication that this
patch needs to be broken up for easier review.  A few
comments/suggestions inline below.

> ---
>  crypto/asymmetric_keys/pkcs7_parser.c |  12 +++
>  include/crypto/pkcs7.h|   3 +
>  security/integrity/Kconfig|   2 +-
>  security/integrity/digsig.c   |  28 +++--
>  security/integrity/ima/Kconfig|  13 +++
>  security/integrity/ima/Makefile   |   1 +
>  security/integrity/ima/ima.h  |  53 ++
>  security/integrity/ima/ima_api.c  |   2 +-
>  security/integrity/ima/ima_appraise.c |  41 ++--
>  security/integrity/ima/ima_main.c |  91 
>  security/integrity/ima/ima_modsig.c   | 167 
> ++
>  security/integrity/ima/ima_policy.c   |  26 +++--
>  security/integrity/ima/ima_template_lib.c |  14 ++-
>  security/integrity/integrity.h|   5 +-
>  14 files changed, 404 insertions(+), 54 deletions(-)
> 
> diff --git a/crypto/asymmetric_keys/pkcs7_parser.c 
> b/crypto/asymmetric_keys/pkcs7_parser.c
> index af4cd8649117..e41beda297a8 100644
> --- a/crypto/asymmetric_keys/pkcs7_parser.c
> +++ b/crypto/asymmetric_keys/pkcs7_parser.c
> @@ -673,3 +673,15 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
>   return -ENOMEM;
>   return 0;
>  }
> +
> +/**
> + * pkcs7_get_message_sig - get signature in @pkcs7
> + *
> + * This function doesn't meaningfully support messages with more than one
> + * signature. It will always return the first signature.
> + */
> +const struct public_key_signature *pkcs7_get_message_sig(
> + const struct pkcs7_message *pkcs7)
> +{
> + return pkcs7->signed_infos ? pkcs7->signed_infos->sig : NULL;
> +}
> diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
> index 583f199400a3..a05a0d7214e6 100644
> --- a/include/crypto/pkcs7.h
> +++ b/include/crypto/pkcs7.h
> @@ -29,6 +29,9 @@ extern int pkcs7_get_content_data(const struct 
> pkcs7_message *pkcs7,
> const void **_data, size_t *_datalen,
> size_t *_headerlen);
> 
> +extern const struct public_key_signature *pkcs7_get_message_sig(
> + const struct pkcs7_message *pkcs7);
> +
>  /*
>   * pkcs7_trust.c
>   */
> diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
> index da9565891738..0d642e0317c7 100644
> --- a/security/integrity/Kconfig
> +++ b/security/integrity/Kconfig
> @@ -17,8