Message ID | 20210409024656.8083-3-jlee@suse.com |
---|---|
State | Superseded |
Headers | show |
Series | Check codeSigning extended key usage extension | expand |
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@suse.com> > --- > 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
Hi Varad, Thanks for your review! On Thu, Apr 15, 2021 at 02:08:32PM +0200, Varad Gautam wrote: > 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@suse.com> > > --- > > 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. > Because only codesign EKU be checked now. So I prefer to keep it as my current implementation until there have other EKU requirement. > > + 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 I will update it to the comment. Thanks! Joey Lee > > > { > > 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
Hi Varad, On Tue, Apr 20, 2021 at 02:22:28PM +0800, Joey Lee wrote: > Hi Varad, > > Thanks for your review! > > On Thu, Apr 15, 2021 at 02:08:32PM +0200, Varad Gautam wrote: > > 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@suse.com> > > > --- > > > 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(-) [...snip] > > > > > > 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. > > > > Because only codesign EKU be checked now. So I prefer to keep it > as my current implementation until there have other EKU requirement. I have reworked this patch for a bug be found by kernel test robot. I think that your suggestion is good. So I change the function name to a more generic name check_eku_by_usage() in my v7 patch set. Thanks a lot! Joey Lee
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)) { + 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) { 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
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/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(-)