summaryrefslogtreecommitdiffstats
path: root/MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch
diff options
context:
space:
mode:
authorJustin M. Forbes <jforbes@fedoraproject.org>2017-05-05 13:07:47 -0500
committerJustin M. Forbes <jforbes@fedoraproject.org>2017-05-05 13:07:47 -0500
commitcddccb28e0722d522faf5967d1a83c8595e66242 (patch)
tree55be5837f6b8fce794075c22c3248f5897299f38 /MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch
parentb88f18484ea4501304fcc597456eb789d884871a (diff)
downloadkernel-cddccb28e0722d522faf5967d1a83c8595e66242.tar.gz
kernel-cddccb28e0722d522faf5967d1a83c8595e66242.tar.xz
kernel-cddccb28e0722d522faf5967d1a83c8595e66242.zip
Linux v4.11-8539-gaf82455
Diffstat (limited to 'MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch')
-rw-r--r--MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch294
1 files changed, 147 insertions, 147 deletions
diff --git a/MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch b/MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch
index 5ff792c3c..08195ff4e 100644
--- a/MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch
+++ b/MODSIGN-Import-certificates-from-UEFI-Secure-Boot.patch
@@ -1,7 +1,7 @@
-From 8a4535bcfe24d317be675e53cdc8c61d22fdc7f3 Mon Sep 17 00:00:00 2001
+From 90dc66270b02981b19a085c6a9184e3452b7b3e8 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
-Date: Fri, 26 Oct 2012 12:42:16 -0400
-Subject: [PATCH 18/20] MODSIGN: Import certificates from UEFI Secure Boot
+Date: Fri, 5 May 2017 08:21:59 +0100
+Subject: [PATCH 3/4] MODSIGN: Import certificates from UEFI Secure Boot
Secure Boot stores a list of allowed certificates in the 'db' variable.
This imports those certificates into the system trusted keyring. This
@@ -11,123 +11,68 @@ variable, a user can allow a module signed with that certificate to
load. The shim UEFI bootloader has a similar certificate list stored
in the 'MokListRT' variable. We import those as well.
-In the opposite case, Secure Boot maintains a list of disallowed
-certificates in the 'dbx' variable. We load those certificates into
-the newly introduced system blacklist keyring and forbid any module
-signed with those from loading.
+Secure Boot also maintains a list of disallowed certificates in the 'dbx'
+variable. We load those certificates into the newly introduced system
+blacklist keyring and forbid any module signed with those from loading and
+forbid the use within the kernel of any key with a matching hash.
+
+This facility is enabled by setting CONFIG_LOAD_UEFI_KEYS.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
---
- certs/system_keyring.c | 13 ++++++
- include/keys/system_keyring.h | 1 +
- init/Kconfig | 9 ++++
- kernel/Makefile | 3 ++
- kernel/modsign_uefi.c | 99 +++++++++++++++++++++++++++++++++++++++++++
- 5 files changed, 125 insertions(+)
- create mode 100644 kernel/modsign_uefi.c
+ certs/Kconfig | 16 ++++++
+ certs/Makefile | 4 ++
+ certs/load_uefi.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 188 insertions(+)
+ create mode 100644 certs/load_uefi.c
-diff --git a/certs/system_keyring.c b/certs/system_keyring.c
-index 787eeead2f57..4d9123ed5c07 100644
---- a/certs/system_keyring.c
-+++ b/certs/system_keyring.c
-@@ -30,6 +30,19 @@ extern __initconst const u8 system_certificate_list[];
- extern __initconst const unsigned long system_certificate_list_size;
-
- /**
-+ * get_system_keyring - Return a pointer to the system keyring
-+ *
-+ */
-+struct key *get_system_keyring(void)
-+{
-+ struct key *system_keyring = NULL;
-+
-+ system_keyring = builtin_trusted_keys;
-+ return system_keyring;
-+}
-+EXPORT_SYMBOL_GPL(get_system_keyring);
-+
-+/**
- * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
- *
- * Restrict the addition of keys into a keyring based on the key-to-be-added
-diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
-index 359c2f9..e7160a6 100644
---- a/include/keys/system_keyring.h
-+++ b/include/keys/system_keyring.h
-@@ -39,14 +39,26 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
- extern int mark_hash_blacklisted(const char *hash);
- extern int is_hash_blacklisted(const u8 *hash, size_t hash_len,
- const char *type);
-+extern struct key *blacklist_keyring;
-+
-+static inline struct key *get_blacklist_keyring(void)
-+{
-+ return blacklist_keyring;
-+}
- #else
- static inline int is_hash_blacklisted(const u8 *hash, size_t hash_len,
- const char *type)
- {
- return 0;
- }
-+static inline struct key *get_blacklist_keyring(void)
-+{
-+ return NULL;
-+}
- #endif
+diff --git a/certs/Kconfig b/certs/Kconfig
+index 630ae09..edf9f75 100644
+--- a/certs/Kconfig
++++ b/certs/Kconfig
+@@ -90,4 +90,20 @@ config EFI_SIGNATURE_LIST_PARSER
+ This option provides support for parsing EFI signature lists for
+ X.509 certificates and turning them into keys.
+
++config LOAD_UEFI_KEYS
++ bool "Load certs and blacklist from UEFI db for module checking"
++ depends on SYSTEM_BLACKLIST_KEYRING
++ depends on SECONDARY_TRUSTED_KEYRING
++ depends on EFI
++ depends on EFI_SIGNATURE_LIST_PARSER
++ help
++ If the kernel is booted in secure boot mode, this option will cause
++ the kernel to load the certificates from the UEFI db and MokListRT
++ into the secondary trusted keyring. It will also load any X.509
++ SHA256 hashes in the dbx list into the blacklist.
++
++ The effect of this is that, if the kernel is booted in secure boot
++ mode, modules signed with UEFI-stored keys will be permitted to be
++ loaded and keys that match the blacklist will be rejected.
++
+ endmenu
+diff --git a/certs/Makefile b/certs/Makefile
+index 738151a..a5e057a 100644
+--- a/certs/Makefile
++++ b/certs/Makefile
+@@ -11,6 +11,10 @@ obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o
+ endif
+ obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o
-+extern struct key *get_system_keyring(void);
++obj-$(CONFIG_LOAD_UEFI_KEYS) += load_uefi.o
++$(obj)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
+
- #ifdef CONFIG_IMA_BLACKLIST_KEYRING
- extern struct key *ima_blacklist_keyring;
++
+ ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
-diff --git a/init/Kconfig b/init/Kconfig
-index 461ad575a608..93646fd7b1c8 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -2009,6 +2009,15 @@ config MODULE_SIG_ALL
- comment "Do not forget to sign required modules with scripts/sign-file"
- depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL
-
-+config MODULE_SIG_UEFI
-+ bool "Allow modules signed with certs stored in UEFI"
-+ depends on MODULE_SIG && SYSTEM_BLACKLIST_KEYRING && EFI
-+ select EFI_SIGNATURE_LIST_PARSER
-+ help
-+ This will import certificates stored in UEFI and allow modules
-+ signed with those to be loaded. It will also disallow loading
-+ of modules stored in the UEFI dbx variable.
-+
- choice
- prompt "Which hash algorithm should modules be signed with?"
- depends on MODULE_SIG
-diff --git a/kernel/Makefile b/kernel/Makefile
-index eb26e12c6c2a..e0c2268cb97e 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -57,6 +57,7 @@ endif
- obj-$(CONFIG_UID16) += uid16.o
- obj-$(CONFIG_MODULES) += module.o
- obj-$(CONFIG_MODULE_SIG) += module_signing.o
-+obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o
- obj-$(CONFIG_KALLSYMS) += kallsyms.o
- obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
- obj-$(CONFIG_KEXEC_CORE) += kexec_core.o
-@@ -113,6 +114,8 @@ obj-$(CONFIG_MEMBARRIER) += membarrier.o
-
- obj-$(CONFIG_HAS_IOMEM) += memremap.o
-
-+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar
-+
- $(obj)/configs.o: $(obj)/config_data.h
-
- targets += config_data.gz
-diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c
+ $(eval $(call config_filename,SYSTEM_TRUSTED_KEYS))
+diff --git a/certs/load_uefi.c b/certs/load_uefi.c
new file mode 100644
-index 000000000000..fe4a6f2bf10a
+index 0000000..b44e464
--- /dev/null
-+++ b/kernel/modsign_uefi.c
-@@ -0,0 +1,101 @@
++++ b/certs/load_uefi.c
+@@ -0,0 +1,168 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
@@ -136,14 +81,22 @@ index 000000000000..fe4a6f2bf10a
+#include <linux/slab.h>
+#include <keys/asymmetric-type.h>
+#include <keys/system_keyring.h>
-+#include "module-internal.h"
++#include "internal.h"
++
++static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID;
++static __initdata efi_guid_t efi_cert_x509_sha256_guid = EFI_CERT_X509_SHA256_GUID;
++static __initdata efi_guid_t efi_cert_sha256_guid = EFI_CERT_SHA256_GUID;
+
-+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size)
++/*
++ * Get a certificate list blob from the named EFI variable.
++ */
++static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
++ unsigned long *size)
+{
+ efi_status_t status;
+ unsigned long lsize = 4;
+ unsigned long tmpdb[4];
-+ void *db = NULL;
++ void *db;
+
+ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
+ if (status != EFI_BUFFER_TOO_SMALL) {
@@ -154,23 +107,89 @@ index 000000000000..fe4a6f2bf10a
+ db = kmalloc(lsize, GFP_KERNEL);
+ if (!db) {
+ pr_err("Couldn't allocate memory for uefi cert list\n");
-+ goto out;
++ return NULL;
+ }
+
+ status = efi.get_variable(name, guid, NULL, &lsize, db);
+ if (status != EFI_SUCCESS) {
+ kfree(db);
-+ db = NULL;
+ pr_err("Error reading db var: 0x%lx\n", status);
++ return NULL;
+ }
-+out:
++
+ *size = lsize;
+ return db;
+}
+
+/*
-+ * * Load the certs contained in the UEFI databases
-+ * */
++ * Blacklist an X509 TBS hash.
++ */
++static __init void uefi_blacklist_x509_tbs(const char *source,
++ const void *data, size_t len)
++{
++ char *hash, *p;
++
++ hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
++ if (!hash)
++ return;
++ p = memcpy(hash, "tbs:", 4);
++ p += 4;
++ bin2hex(p, data, len);
++ p += len * 2;
++ *p = 0;
++
++ mark_hash_blacklisted(hash);
++ kfree(hash);
++}
++
++/*
++ * Blacklist the hash of an executable.
++ */
++static __init void uefi_blacklist_binary(const char *source,
++ const void *data, size_t len)
++{
++ char *hash, *p;
++
++ hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
++ if (!hash)
++ return;
++ p = memcpy(hash, "bin:", 4);
++ p += 4;
++ bin2hex(p, data, len);
++ p += len * 2;
++ *p = 0;
++
++ mark_hash_blacklisted(hash);
++ kfree(hash);
++}
++
++/*
++ * Return the appropriate handler for particular signature list types found in
++ * the UEFI db and MokListRT tables.
++ */
++static __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
++{
++ if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
++ return add_trusted_secondary_key;
++ return 0;
++}
++
++/*
++ * Return the appropriate handler for particular signature list types found in
++ * the UEFI dbx and MokListXRT tables.
++ */
++static __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
++{
++ if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
++ return uefi_blacklist_x509_tbs;
++ if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
++ return uefi_blacklist_binary;
++ return 0;
++}
++
++/*
++ * Load the certs contained in the UEFI databases
++ */
+static int __init load_uefi_certs(void)
+{
+ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
@@ -178,18 +197,9 @@ index 000000000000..fe4a6f2bf10a
+ void *db = NULL, *dbx = NULL, *mok = NULL;
+ unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
+ int rc = 0;
-+ struct key *keyring = NULL;
-+ struct key *blacklist = NULL;
+
-+ /* Check if SB is enabled and just return if not */
-+ if (!efi_enabled(EFI_SECURE_BOOT))
-+ return 0;
-+
-+ keyring = get_system_keyring();
-+ if (!keyring) {
-+ pr_err("MODSIGN: Couldn't get system keyring\n");
-+ return -EINVAL;
-+ }
++ if (!efi.get_variable)
++ return false;
+
+ /* Get db, MokListRT, and dbx. They might not exist, so it isn't
+ * an error if we can't get them.
@@ -198,7 +208,8 @@ index 000000000000..fe4a6f2bf10a
+ if (!db) {
+ pr_err("MODSIGN: Couldn't get UEFI db list\n");
+ } else {
-+ rc = parse_efi_signature_list(db, dbsize, keyring);
++ rc = parse_efi_signature_list("UEFI:db",
++ db, dbsize, get_handler_for_db);
+ if (rc)
+ pr_err("Couldn't parse db signatures: %d\n", rc);
+ kfree(db);
@@ -208,19 +219,20 @@ index 000000000000..fe4a6f2bf10a
+ if (!mok) {
+ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n");
+ } else {
-+ rc = parse_efi_signature_list(mok, moksize, keyring);
++ rc = parse_efi_signature_list("UEFI:MokListRT",
++ mok, moksize, get_handler_for_db);
+ if (rc)
+ pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
+ kfree(mok);
+ }
+
-+ blacklist = get_blacklist_keyring();
+ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
+ if (!dbx) {
+ pr_info("MODSIGN: Couldn't get UEFI dbx list\n");
+ } else {
-+ rc = parse_efi_signature_list(dbx, dbxsize,
-+ blacklist);
++ rc = parse_efi_signature_list("UEFI:dbx",
++ dbx, dbxsize,
++ get_handler_for_dbx);
+ if (rc)
+ pr_err("Couldn't parse dbx signatures: %d\n", rc);
+ kfree(dbx);
@@ -231,16 +243,4 @@ index 000000000000..fe4a6f2bf10a
+late_initcall(load_uefi_certs);
--
2.9.3
-diff --git a/certs/blacklist.c b/certs/blacklist.c
-index 3eddce0..bd9324c 100644
---- a/certs/blacklist.c
-+++ b/certs/blacklist.c
-@@ -21,7 +21,7 @@
- #include <keys/system_keyring.h>
- #include "blacklist.h"
-
--static struct key *blacklist_keyring;
-+struct key *blacklist_keyring;
- /*
- * The description must be a type prefix, a colon and then an even number of