Skip to content

Commit 56c5812

Browse files
esnowbergdhowells
authored andcommitted
certs: Add EFI_CERT_X509_GUID support for dbx entries
This fixes CVE-2020-26541. The Secure Boot Forbidden Signature Database, dbx, contains a list of now revoked signatures and keys previously approved to boot with UEFI Secure Boot enabled. The dbx is capable of containing any number of EFI_CERT_X509_SHA256_GUID, EFI_CERT_SHA256_GUID, and EFI_CERT_X509_GUID entries. Currently when EFI_CERT_X509_GUID are contained in the dbx, the entries are skipped. Add support for EFI_CERT_X509_GUID dbx entries. When a EFI_CERT_X509_GUID is found, it is added as an asymmetrical key to the .blacklist keyring. Anytime the .platform keyring is used, the keys in the .blacklist keyring are referenced, if a matching key is found, the key will be rejected. [DH: Made the following changes: - Added to have a config option to enable the facility. This allows a Kconfig solution to make sure that pkcs7_validate_trust() is enabled.[1][2] - Moved the functions out from the middle of the blacklist functions. - Added kerneldoc comments.] Signed-off-by: Eric Snowberg <[email protected]> Signed-off-by: David Howells <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> cc: Randy Dunlap <[email protected]> cc: Mickaël Salaün <[email protected]> cc: Arnd Bergmann <[email protected]> cc: [email protected] Link: https://lore.kernel.org/r/[email protected]/ # rfc Link: https://lore.kernel.org/r/[email protected]/ # v2 Link: https://lore.kernel.org/r/[email protected]/ # v3 Link: https://lore.kernel.org/r/[email protected]/ # v4 Link: https://lore.kernel.org/r/[email protected]/ # v5 Link: https://lore.kernel.org/r/161428672051.677100.11064981943343605138.stgit@warthog.procyon.org.uk/ Link: https://lore.kernel.org/r/161433310942.902181.4901864302675874242.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/161529605075.163428.14625520893961300757.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/[email protected]/ [1] Link: https://lore.kernel.org/r/[email protected]/ [2]
1 parent 8f0bfc2 commit 56c5812

File tree

6 files changed

+86
-0
lines changed

6 files changed

+86
-0
lines changed

certs/Kconfig

+9
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,13 @@ config SYSTEM_BLACKLIST_HASH_LIST
8383
wrapper to incorporate the list into the kernel. Each <hash> should
8484
be a string of hex digits.
8585

86+
config SYSTEM_REVOCATION_LIST
87+
bool "Provide system-wide ring of revocation certificates"
88+
depends on SYSTEM_BLACKLIST_KEYRING
89+
depends on PKCS7_MESSAGE_PARSER=y
90+
help
91+
If set, this allows revocation certificates to be stored in the
92+
blacklist keyring and implements a hook whereby a PKCS#7 message can
93+
be checked to see if it matches such a certificate.
94+
8695
endmenu

certs/blacklist.c

+43
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,49 @@ int is_binary_blacklisted(const u8 *hash, size_t hash_len)
145145
}
146146
EXPORT_SYMBOL_GPL(is_binary_blacklisted);
147147

148+
#ifdef CONFIG_SYSTEM_REVOCATION_LIST
149+
/**
150+
* add_key_to_revocation_list - Add a revocation certificate to the blacklist
151+
* @data: The data blob containing the certificate
152+
* @size: The size of data blob
153+
*/
154+
int add_key_to_revocation_list(const char *data, size_t size)
155+
{
156+
key_ref_t key;
157+
158+
key = key_create_or_update(make_key_ref(blacklist_keyring, true),
159+
"asymmetric",
160+
NULL,
161+
data,
162+
size,
163+
((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW),
164+
KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN);
165+
166+
if (IS_ERR(key)) {
167+
pr_err("Problem with revocation key (%ld)\n", PTR_ERR(key));
168+
return PTR_ERR(key);
169+
}
170+
171+
return 0;
172+
}
173+
174+
/**
175+
* is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked
176+
* @pkcs7: The PKCS#7 message to check
177+
*/
178+
int is_key_on_revocation_list(struct pkcs7_message *pkcs7)
179+
{
180+
int ret;
181+
182+
ret = pkcs7_validate_trust(pkcs7, blacklist_keyring);
183+
184+
if (ret == 0)
185+
return -EKEYREJECTED;
186+
187+
return -ENOKEY;
188+
}
189+
#endif
190+
148191
/*
149192
* Initialise the blacklist
150193
*/

certs/blacklist.h

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
#include <linux/kernel.h>
2+
#include <linux/errno.h>
3+
#include <crypto/pkcs7.h>
24

35
extern const char __initconst *const blacklist_hashes[];

certs/system_keyring.c

+6
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ int verify_pkcs7_message_sig(const void *data, size_t len,
242242
pr_devel("PKCS#7 platform keyring is not available\n");
243243
goto error;
244244
}
245+
246+
ret = is_key_on_revocation_list(pkcs7);
247+
if (ret != -ENOKEY) {
248+
pr_devel("PKCS#7 platform key is on revocation list\n");
249+
goto error;
250+
}
245251
}
246252
ret = pkcs7_validate_trust(pkcs7, trusted_keys);
247253
if (ret < 0) {

include/keys/system_keyring.h

+15
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
3131
#define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted
3232
#endif
3333

34+
extern struct pkcs7_message *pkcs7;
3435
#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
3536
extern int mark_hash_blacklisted(const char *hash);
3637
extern int is_hash_blacklisted(const u8 *hash, size_t hash_len,
@@ -49,6 +50,20 @@ static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len)
4950
}
5051
#endif
5152

53+
#ifdef CONFIG_SYSTEM_REVOCATION_LIST
54+
extern int add_key_to_revocation_list(const char *data, size_t size);
55+
extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7);
56+
#else
57+
static inline int add_key_to_revocation_list(const char *data, size_t size)
58+
{
59+
return 0;
60+
}
61+
static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7)
62+
{
63+
return -ENOKEY;
64+
}
65+
#endif
66+
5267
#ifdef CONFIG_IMA_BLACKLIST_KEYRING
5368
extern struct key *ima_blacklist_keyring;
5469

security/integrity/platform_certs/keyring_handler.c

+11
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ static __init void uefi_blacklist_binary(const char *source,
5555
uefi_blacklist_hash(source, data, len, "bin:", 4);
5656
}
5757

58+
/*
59+
* Add an X509 cert to the revocation list.
60+
*/
61+
static __init void uefi_revocation_list_x509(const char *source,
62+
const void *data, size_t len)
63+
{
64+
add_key_to_revocation_list(data, len);
65+
}
66+
5867
/*
5968
* Return the appropriate handler for particular signature list types found in
6069
* the UEFI db and MokListRT tables.
@@ -76,5 +85,7 @@ __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
7685
return uefi_blacklist_x509_tbs;
7786
if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
7887
return uefi_blacklist_binary;
88+
if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
89+
return uefi_revocation_list_x509;
7990
return 0;
8091
}

0 commit comments

Comments
 (0)