Hi Joey, On 4/9/21 4:46 AM, Lee, Chun-Yi wrote: > This patch adds the logic for checking the CodeSigning extended > key usage when verifying signature of kernel module or > kexec PE binary in PKCS#7. > > Signed-off-by: "Lee, Chun-Yi" <jlee@xxxxxxxx> > --- > certs/system_keyring.c | 2 +- > crypto/asymmetric_keys/Kconfig | 9 +++++++++ > crypto/asymmetric_keys/pkcs7_trust.c | 37 +++++++++++++++++++++++++++++++++--- > include/crypto/pkcs7.h | 3 ++- > 4 files changed, 46 insertions(+), 5 deletions(-) > > diff --git a/certs/system_keyring.c b/certs/system_keyring.c > index 4b693da488f1..c9f8bca0b0d3 100644 > --- a/certs/system_keyring.c > +++ b/certs/system_keyring.c > @@ -243,7 +243,7 @@ int verify_pkcs7_message_sig(const void *data, size_t len, > goto error; > } > } > - ret = pkcs7_validate_trust(pkcs7, trusted_keys); > + ret = pkcs7_validate_trust(pkcs7, trusted_keys, usage); > if (ret < 0) { > if (ret == -ENOKEY) > pr_devel("PKCS#7 signature not signed with a trusted key\n"); > diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig > index 1f1f004dc757..1754812df989 100644 > --- a/crypto/asymmetric_keys/Kconfig > +++ b/crypto/asymmetric_keys/Kconfig > @@ -96,4 +96,13 @@ config SIGNED_PE_FILE_VERIFICATION > This option provides support for verifying the signature(s) on a > signed PE binary. > > +config CHECK_CODESIGN_EKU > + bool "Check codeSigning extended key usage" > + depends on PKCS7_MESSAGE_PARSER=y > + depends on SYSTEM_DATA_VERIFICATION > + help > + This option provides support for checking the codeSigning extended > + key usage when verifying the signature in PKCS#7. It affects kernel > + module verification and kexec PE binary verification. > + > endif # ASYMMETRIC_KEY_TYPE > diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c > index b531df2013c4..077bfef928b6 100644 > --- a/crypto/asymmetric_keys/pkcs7_trust.c > +++ b/crypto/asymmetric_keys/pkcs7_trust.c > @@ -16,12 +16,36 @@ > #include <crypto/public_key.h> > #include "pkcs7_parser.h" > > +#ifdef CONFIG_CHECK_CODESIGN_EKU > +static bool check_codesign_eku(struct key *key, > + enum key_being_used_for usage) > +{ > + struct public_key *public_key = key->payload.data[asym_crypto]; > + > + switch (usage) { > + case VERIFYING_MODULE_SIGNATURE: > + case VERIFYING_KEXEC_PE_SIGNATURE: > + return !!(public_key->eku & EKU_codeSigning); > + default: > + break; > + } > + return true; > +} > +#else > +static bool check_codesign_eku(struct key *key, > + enum key_being_used_for usage) > +{ > + return true; > +} > +#endif > + > /* > * Check the trust on one PKCS#7 SignedInfo block. > */ > static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, > struct pkcs7_signed_info *sinfo, > - struct key *trust_keyring) > + struct key *trust_keyring, > + enum key_being_used_for usage) > { > struct public_key_signature *sig = sinfo->sig; > struct x509_certificate *x509, *last = NULL, *p; > @@ -112,6 +136,12 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, > return -ENOKEY; > > matched: > + if (!check_codesign_eku(key, usage)) { Perhaps this can be a generic check_eku_usage() call, with codesigning as one of the things it can check for. > + pr_warn("sinfo %u: The signer %x key is not CodeSigning\n", > + sinfo->index, key_serial(key)); > + key_put(key); > + return -ENOKEY; > + } > ret = verify_signature(key, sig); > key_put(key); > if (ret < 0) { > @@ -156,7 +186,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, > * May also return -ENOMEM. > */ > int pkcs7_validate_trust(struct pkcs7_message *pkcs7, > - struct key *trust_keyring) > + struct key *trust_keyring, > + enum key_being_used_for usage) Please also update the comment above to mention the `usage` parameter. Regards, Varad > { > struct pkcs7_signed_info *sinfo; > struct x509_certificate *p; > @@ -167,7 +198,7 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7, > p->seen = false; > > for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { > - ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring); > + ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring, usage); > switch (ret) { > case -ENOKEY: > continue; > diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h > index 38ec7f5f9041..b3b48240ba73 100644 > --- a/include/crypto/pkcs7.h > +++ b/include/crypto/pkcs7.h > @@ -30,7 +30,8 @@ extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, > * pkcs7_trust.c > */ > extern int pkcs7_validate_trust(struct pkcs7_message *pkcs7, > - struct key *trust_keyring); > + struct key *trust_keyring, > + enum key_being_used_for usage); > > /* > * pkcs7_verify.c > -- SUSE Software Solutions Germany GmbH Maxfeldstr. 5 90409 Nürnberg Germany HRB 36809, AG Nürnberg Geschäftsführer: Felix Imendörffer