Message ID | 20220825142314.8406-3-jlee@suse.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Check codeSigning extended key usage extension | expand |
On Thu, Aug 25, 2022 at 10:23:12PM +0800, 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. Pretty much the same feedback as for 1/4. > > Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com> > --- > certs/blacklist.c | 5 ++-- > certs/system_keyring.c | 4 +-- > crypto/asymmetric_keys/Kconfig | 9 ++++++ > crypto/asymmetric_keys/pkcs7_trust.c | 43 ++++++++++++++++++++++++++-- > crypto/asymmetric_keys/selftest.c | 2 +- > include/crypto/pkcs7.h | 4 ++- > include/keys/system_keyring.h | 7 +++-- > 7 files changed, 63 insertions(+), 11 deletions(-) > > diff --git a/certs/blacklist.c b/certs/blacklist.c > index 41f10601cc72..fa41454055be 100644 > --- a/certs/blacklist.c > +++ b/certs/blacklist.c > @@ -282,11 +282,12 @@ int add_key_to_revocation_list(const char *data, size_t size) > * is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked > * @pkcs7: The PKCS#7 message to check > */ > -int is_key_on_revocation_list(struct pkcs7_message *pkcs7) > +int is_key_on_revocation_list(struct pkcs7_message *pkcs7, > + enum key_being_used_for usage) > { > int ret; > > - ret = pkcs7_validate_trust(pkcs7, blacklist_keyring); > + ret = pkcs7_validate_trust(pkcs7, blacklist_keyring, usage, false); > > if (ret == 0) > return -EKEYREJECTED; > diff --git a/certs/system_keyring.c b/certs/system_keyring.c > index 5042cc54fa5e..66737bfb26de 100644 > --- a/certs/system_keyring.c > +++ b/certs/system_keyring.c > @@ -263,13 +263,13 @@ int verify_pkcs7_message_sig(const void *data, size_t len, > goto error; > } > > - ret = is_key_on_revocation_list(pkcs7); > + ret = is_key_on_revocation_list(pkcs7, usage); > if (ret != -ENOKEY) { > pr_devel("PKCS#7 platform key is on revocation list\n"); > goto error; > } > } > - ret = pkcs7_validate_trust(pkcs7, trusted_keys); > + ret = pkcs7_validate_trust(pkcs7, trusted_keys, usage, true); > 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 3df3fe4ed95f..189536bd0f9a 100644 > --- a/crypto/asymmetric_keys/Kconfig > +++ b/crypto/asymmetric_keys/Kconfig > @@ -85,4 +85,13 @@ config FIPS_SIGNATURE_SELFTEST > depends on ASYMMETRIC_KEY_TYPE > depends on PKCS7_MESSAGE_PARSER > > +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 9a87c34ed173..087d3761d9a8 100644 > --- a/crypto/asymmetric_keys/pkcs7_trust.c > +++ b/crypto/asymmetric_keys/pkcs7_trust.c > @@ -16,12 +16,40 @@ > #include <crypto/public_key.h> > #include "pkcs7_parser.h" > > +#ifdef CONFIG_CHECK_CODESIGN_EKU > +static bool check_eku_by_usage(struct key *key, enum key_being_used_for usage) > +{ > + struct public_key *public_key = key->payload.data[asym_crypto]; > + bool ret = true; > + > + switch (usage) { > + case VERIFYING_MODULE_SIGNATURE: > + case VERIFYING_KEXEC_PE_SIGNATURE: > + ret = !!(public_key->ext_key_usage & EKU_codeSigning); > + if (!ret) > + pr_warn("The signer '%s' key is not CodeSigning\n", > + key->description); > + break; > + default: > + break; > + } > + return ret; > +} > +#else > +static bool check_eku_by_usage(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, > + bool check_eku) > { > struct public_key_signature *sig = sinfo->sig; > struct x509_certificate *x509, *last = NULL, *p; > @@ -112,6 +140,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, > return -ENOKEY; > > matched: > + if (check_eku && !check_eku_by_usage(key, usage)) { > + key_put(key); > + return -ENOKEY; > + } Why you don't just open code this to those rare call sites where it is needed? I counted that there is exactly one call site. > ret = verify_signature(key, sig); > key_put(key); > if (ret < 0) { > @@ -135,6 +167,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, > * pkcs7_validate_trust - Validate PKCS#7 trust chain > * @pkcs7: The PKCS#7 certificate to validate > * @trust_keyring: Signing certificates to use as starting points > + * @usage: The use to which the key is being put. > + * @check_eku: Check EKU (Extended Key Usage) > * > * Validate that the certificate chain inside the PKCS#7 message intersects > * keys we already know and trust. > @@ -156,7 +190,9 @@ 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, > + bool check_eku) > { > struct pkcs7_signed_info *sinfo; > struct x509_certificate *p; > @@ -167,7 +203,8 @@ 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, check_eku); > switch (ret) { > case -ENOKEY: > continue; > diff --git a/crypto/asymmetric_keys/selftest.c b/crypto/asymmetric_keys/selftest.c > index fa0bf7f24284..756e9f224d8a 100644 > --- a/crypto/asymmetric_keys/selftest.c > +++ b/crypto/asymmetric_keys/selftest.c > @@ -212,7 +212,7 @@ int __init fips_signature_selftest(void) > if (ret < 0) > panic("Certs selftest %d: pkcs7_verify() = %d\n", i, ret); > > - ret = pkcs7_validate_trust(pkcs7, keyring); > + ret = pkcs7_validate_trust(pkcs7, keyring, VERIFYING_MODULE_SIGNATURE, false); > if (ret < 0) > panic("Certs selftest %d: pkcs7_validate_trust() = %d\n", i, ret); > > diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h > index 38ec7f5f9041..5d87b8a02f79 100644 > --- a/include/crypto/pkcs7.h > +++ b/include/crypto/pkcs7.h > @@ -30,7 +30,9 @@ 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, > + bool check_eku); > > /* > * pkcs7_verify.c > diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h > index 91e080efb918..bb33b527240e 100644 > --- a/include/keys/system_keyring.h > +++ b/include/keys/system_keyring.h > @@ -9,6 +9,7 @@ > #define _KEYS_SYSTEM_KEYRING_H > > #include <linux/key.h> > +#include <keys/asymmetric-type.h> > > enum blacklist_hash_type { > /* TBSCertificate hash */ > @@ -81,13 +82,15 @@ static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len) > > #ifdef CONFIG_SYSTEM_REVOCATION_LIST > extern int add_key_to_revocation_list(const char *data, size_t size); > -extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7); > +extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7, > + enum key_being_used_for usage); > #else > static inline int add_key_to_revocation_list(const char *data, size_t size) > { > return 0; > } > -static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7) > +static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7, > + enum key_being_used_for usage) > { > return -ENOKEY; > } > -- > 2.26.2 > BR, Jarkko
Hi Jarkko, On Sun, Aug 28, 2022 at 06:34:26AM +0300, Jarkko Sakkinen wrote: > On Thu, Aug 25, 2022 at 10:23:12PM +0800, 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. > > Pretty much the same feedback as for 1/4. > I will also change this description. Thanks Joey Lee > > > > Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com> > > --- > > certs/blacklist.c | 5 ++-- > > certs/system_keyring.c | 4 +-- > > crypto/asymmetric_keys/Kconfig | 9 ++++++ > > crypto/asymmetric_keys/pkcs7_trust.c | 43 ++++++++++++++++++++++++++-- > > crypto/asymmetric_keys/selftest.c | 2 +- > > include/crypto/pkcs7.h | 4 ++- > > include/keys/system_keyring.h | 7 +++-- > > 7 files changed, 63 insertions(+), 11 deletions(-) > > > > diff --git a/certs/blacklist.c b/certs/blacklist.c > > index 41f10601cc72..fa41454055be 100644 > > --- a/certs/blacklist.c > > +++ b/certs/blacklist.c > > @@ -282,11 +282,12 @@ int add_key_to_revocation_list(const char *data, size_t size) > > * is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked > > * @pkcs7: The PKCS#7 message to check > > */ > > -int is_key_on_revocation_list(struct pkcs7_message *pkcs7) > > +int is_key_on_revocation_list(struct pkcs7_message *pkcs7, > > + enum key_being_used_for usage) > > { > > int ret; > > > > - ret = pkcs7_validate_trust(pkcs7, blacklist_keyring); > > + ret = pkcs7_validate_trust(pkcs7, blacklist_keyring, usage, false); > > > > if (ret == 0) > > return -EKEYREJECTED; > > diff --git a/certs/system_keyring.c b/certs/system_keyring.c > > index 5042cc54fa5e..66737bfb26de 100644 > > --- a/certs/system_keyring.c > > +++ b/certs/system_keyring.c > > @@ -263,13 +263,13 @@ int verify_pkcs7_message_sig(const void *data, size_t len, > > goto error; > > } > > > > - ret = is_key_on_revocation_list(pkcs7); > > + ret = is_key_on_revocation_list(pkcs7, usage); > > if (ret != -ENOKEY) { > > pr_devel("PKCS#7 platform key is on revocation list\n"); > > goto error; > > } > > } > > - ret = pkcs7_validate_trust(pkcs7, trusted_keys); > > + ret = pkcs7_validate_trust(pkcs7, trusted_keys, usage, true); > > 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 3df3fe4ed95f..189536bd0f9a 100644 > > --- a/crypto/asymmetric_keys/Kconfig > > +++ b/crypto/asymmetric_keys/Kconfig > > @@ -85,4 +85,13 @@ config FIPS_SIGNATURE_SELFTEST > > depends on ASYMMETRIC_KEY_TYPE > > depends on PKCS7_MESSAGE_PARSER > > > > +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 9a87c34ed173..087d3761d9a8 100644 > > --- a/crypto/asymmetric_keys/pkcs7_trust.c > > +++ b/crypto/asymmetric_keys/pkcs7_trust.c > > @@ -16,12 +16,40 @@ > > #include <crypto/public_key.h> > > #include "pkcs7_parser.h" > > > > +#ifdef CONFIG_CHECK_CODESIGN_EKU > > +static bool check_eku_by_usage(struct key *key, enum key_being_used_for usage) > > +{ > > + struct public_key *public_key = key->payload.data[asym_crypto]; > > + bool ret = true; > > + > > + switch (usage) { > > + case VERIFYING_MODULE_SIGNATURE: > > + case VERIFYING_KEXEC_PE_SIGNATURE: > > + ret = !!(public_key->ext_key_usage & EKU_codeSigning); > > + if (!ret) > > + pr_warn("The signer '%s' key is not CodeSigning\n", > > + key->description); > > + break; > > + default: > > + break; > > + } > > + return ret; > > +} > > +#else > > +static bool check_eku_by_usage(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, > > + bool check_eku) > > { > > struct public_key_signature *sig = sinfo->sig; > > struct x509_certificate *x509, *last = NULL, *p; > > @@ -112,6 +140,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, > > return -ENOKEY; > > > > matched: > > + if (check_eku && !check_eku_by_usage(key, usage)) { > > + key_put(key); > > + return -ENOKEY; > > + } > > Why you don't just open code this to those rare call > sites where it is needed? > > I counted that there is exactly one call site. > > > ret = verify_signature(key, sig); > > key_put(key); > > if (ret < 0) { > > @@ -135,6 +167,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, > > * pkcs7_validate_trust - Validate PKCS#7 trust chain > > * @pkcs7: The PKCS#7 certificate to validate > > * @trust_keyring: Signing certificates to use as starting points > > + * @usage: The use to which the key is being put. > > + * @check_eku: Check EKU (Extended Key Usage) > > * > > * Validate that the certificate chain inside the PKCS#7 message intersects > > * keys we already know and trust. > > @@ -156,7 +190,9 @@ 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, > > + bool check_eku) > > { > > struct pkcs7_signed_info *sinfo; > > struct x509_certificate *p; > > @@ -167,7 +203,8 @@ 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, check_eku); > > switch (ret) { > > case -ENOKEY: > > continue; > > diff --git a/crypto/asymmetric_keys/selftest.c b/crypto/asymmetric_keys/selftest.c > > index fa0bf7f24284..756e9f224d8a 100644 > > --- a/crypto/asymmetric_keys/selftest.c > > +++ b/crypto/asymmetric_keys/selftest.c > > @@ -212,7 +212,7 @@ int __init fips_signature_selftest(void) > > if (ret < 0) > > panic("Certs selftest %d: pkcs7_verify() = %d\n", i, ret); > > > > - ret = pkcs7_validate_trust(pkcs7, keyring); > > + ret = pkcs7_validate_trust(pkcs7, keyring, VERIFYING_MODULE_SIGNATURE, false); > > if (ret < 0) > > panic("Certs selftest %d: pkcs7_validate_trust() = %d\n", i, ret); > > > > diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h > > index 38ec7f5f9041..5d87b8a02f79 100644 > > --- a/include/crypto/pkcs7.h > > +++ b/include/crypto/pkcs7.h > > @@ -30,7 +30,9 @@ 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, > > + bool check_eku); > > > > /* > > * pkcs7_verify.c > > diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h > > index 91e080efb918..bb33b527240e 100644 > > --- a/include/keys/system_keyring.h > > +++ b/include/keys/system_keyring.h > > @@ -9,6 +9,7 @@ > > #define _KEYS_SYSTEM_KEYRING_H > > > > #include <linux/key.h> > > +#include <keys/asymmetric-type.h> > > > > enum blacklist_hash_type { > > /* TBSCertificate hash */ > > @@ -81,13 +82,15 @@ static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len) > > > > #ifdef CONFIG_SYSTEM_REVOCATION_LIST > > extern int add_key_to_revocation_list(const char *data, size_t size); > > -extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7); > > +extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7, > > + enum key_being_used_for usage); > > #else > > static inline int add_key_to_revocation_list(const char *data, size_t size) > > { > > return 0; > > } > > -static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7) > > +static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7, > > + enum key_being_used_for usage) > > { > > return -ENOKEY; > > } > > -- > > 2.26.2 > > > > BR, Jarkko
diff --git a/certs/blacklist.c b/certs/blacklist.c index 41f10601cc72..fa41454055be 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -282,11 +282,12 @@ int add_key_to_revocation_list(const char *data, size_t size) * is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked * @pkcs7: The PKCS#7 message to check */ -int is_key_on_revocation_list(struct pkcs7_message *pkcs7) +int is_key_on_revocation_list(struct pkcs7_message *pkcs7, + enum key_being_used_for usage) { int ret; - ret = pkcs7_validate_trust(pkcs7, blacklist_keyring); + ret = pkcs7_validate_trust(pkcs7, blacklist_keyring, usage, false); if (ret == 0) return -EKEYREJECTED; diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 5042cc54fa5e..66737bfb26de 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -263,13 +263,13 @@ int verify_pkcs7_message_sig(const void *data, size_t len, goto error; } - ret = is_key_on_revocation_list(pkcs7); + ret = is_key_on_revocation_list(pkcs7, usage); if (ret != -ENOKEY) { pr_devel("PKCS#7 platform key is on revocation list\n"); goto error; } } - ret = pkcs7_validate_trust(pkcs7, trusted_keys); + ret = pkcs7_validate_trust(pkcs7, trusted_keys, usage, true); 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 3df3fe4ed95f..189536bd0f9a 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -85,4 +85,13 @@ config FIPS_SIGNATURE_SELFTEST depends on ASYMMETRIC_KEY_TYPE depends on PKCS7_MESSAGE_PARSER +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 9a87c34ed173..087d3761d9a8 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -16,12 +16,40 @@ #include <crypto/public_key.h> #include "pkcs7_parser.h" +#ifdef CONFIG_CHECK_CODESIGN_EKU +static bool check_eku_by_usage(struct key *key, enum key_being_used_for usage) +{ + struct public_key *public_key = key->payload.data[asym_crypto]; + bool ret = true; + + switch (usage) { + case VERIFYING_MODULE_SIGNATURE: + case VERIFYING_KEXEC_PE_SIGNATURE: + ret = !!(public_key->ext_key_usage & EKU_codeSigning); + if (!ret) + pr_warn("The signer '%s' key is not CodeSigning\n", + key->description); + break; + default: + break; + } + return ret; +} +#else +static bool check_eku_by_usage(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, + bool check_eku) { struct public_key_signature *sig = sinfo->sig; struct x509_certificate *x509, *last = NULL, *p; @@ -112,6 +140,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, return -ENOKEY; matched: + if (check_eku && !check_eku_by_usage(key, usage)) { + key_put(key); + return -ENOKEY; + } ret = verify_signature(key, sig); key_put(key); if (ret < 0) { @@ -135,6 +167,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, * pkcs7_validate_trust - Validate PKCS#7 trust chain * @pkcs7: The PKCS#7 certificate to validate * @trust_keyring: Signing certificates to use as starting points + * @usage: The use to which the key is being put. + * @check_eku: Check EKU (Extended Key Usage) * * Validate that the certificate chain inside the PKCS#7 message intersects * keys we already know and trust. @@ -156,7 +190,9 @@ 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, + bool check_eku) { struct pkcs7_signed_info *sinfo; struct x509_certificate *p; @@ -167,7 +203,8 @@ 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, check_eku); switch (ret) { case -ENOKEY: continue; diff --git a/crypto/asymmetric_keys/selftest.c b/crypto/asymmetric_keys/selftest.c index fa0bf7f24284..756e9f224d8a 100644 --- a/crypto/asymmetric_keys/selftest.c +++ b/crypto/asymmetric_keys/selftest.c @@ -212,7 +212,7 @@ int __init fips_signature_selftest(void) if (ret < 0) panic("Certs selftest %d: pkcs7_verify() = %d\n", i, ret); - ret = pkcs7_validate_trust(pkcs7, keyring); + ret = pkcs7_validate_trust(pkcs7, keyring, VERIFYING_MODULE_SIGNATURE, false); if (ret < 0) panic("Certs selftest %d: pkcs7_validate_trust() = %d\n", i, ret); diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h index 38ec7f5f9041..5d87b8a02f79 100644 --- a/include/crypto/pkcs7.h +++ b/include/crypto/pkcs7.h @@ -30,7 +30,9 @@ 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, + bool check_eku); /* * pkcs7_verify.c diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index 91e080efb918..bb33b527240e 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -9,6 +9,7 @@ #define _KEYS_SYSTEM_KEYRING_H #include <linux/key.h> +#include <keys/asymmetric-type.h> enum blacklist_hash_type { /* TBSCertificate hash */ @@ -81,13 +82,15 @@ static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len) #ifdef CONFIG_SYSTEM_REVOCATION_LIST extern int add_key_to_revocation_list(const char *data, size_t size); -extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7); +extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7, + enum key_being_used_for usage); #else static inline int add_key_to_revocation_list(const char *data, size_t size) { return 0; } -static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7) +static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7, + enum key_being_used_for usage) { return -ENOKEY; }
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@suse.com> --- certs/blacklist.c | 5 ++-- certs/system_keyring.c | 4 +-- crypto/asymmetric_keys/Kconfig | 9 ++++++ crypto/asymmetric_keys/pkcs7_trust.c | 43 ++++++++++++++++++++++++++-- crypto/asymmetric_keys/selftest.c | 2 +- include/crypto/pkcs7.h | 4 ++- include/keys/system_keyring.h | 7 +++-- 7 files changed, 63 insertions(+), 11 deletions(-)