9d22d5
From 0a5e59dd7a921f20d77b13aa4e01392086ddbd12 Mon Sep 17 00:00:00 2001
Josh Boyer c9d9c5
From: Dave Howells <dhowells@redhat.com>
Josh Boyer c9d9c5
Date: Tue, 23 Oct 2012 09:30:54 -0400
9d22d5
Subject: [PATCH 1/5] Add EFI signature data types
Josh Boyer c9d9c5
Josh Boyer c9d9c5
Add the data types that are used for containing hashes, keys and certificates
Josh Boyer c9d9c5
for cryptographic verification.
Josh Boyer c9d9c5
Josh Boyer c9d9c5
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c9d9c5
---
Josh Boyer c9d9c5
 include/linux/efi.h | 20 ++++++++++++++++++++
Josh Boyer c9d9c5
 1 file changed, 20 insertions(+)
Josh Boyer c9d9c5
Josh Boyer c9d9c5
diff --git a/include/linux/efi.h b/include/linux/efi.h
Josh Boyer c9d9c5
index eed2202..1da1b3c 100644
Josh Boyer c9d9c5
--- a/include/linux/efi.h
Josh Boyer c9d9c5
+++ b/include/linux/efi.h
Josh Boyer c9d9c5
@@ -389,6 +389,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
Josh Boyer c9d9c5
 #define EFI_FILE_SYSTEM_GUID \
Josh Boyer c9d9c5
     EFI_GUID(  0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
+#define EFI_CERT_SHA256_GUID \
Josh Boyer c9d9c5
+    EFI_GUID(  0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 )
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+#define EFI_CERT_X509_GUID \
Josh Boyer c9d9c5
+    EFI_GUID(  0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
 typedef struct {
Josh Boyer c9d9c5
 	efi_guid_t guid;
Josh Boyer c9d9c5
 	u64 table;
Josh Boyer c9d9c5
@@ -524,6 +530,20 @@ typedef struct {
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
 #define EFI_INVALID_TABLE_ADDR		(~0UL)
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
+typedef struct  {
Josh Boyer c9d9c5
+	efi_guid_t signature_owner;
Josh Boyer c9d9c5
+	u8 signature_data[];
Josh Boyer c9d9c5
+} efi_signature_data_t;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+typedef struct {
Josh Boyer c9d9c5
+	efi_guid_t signature_type;
Josh Boyer c9d9c5
+	u32 signature_list_size;
Josh Boyer c9d9c5
+	u32 signature_header_size;
Josh Boyer c9d9c5
+	u32 signature_size;
Josh Boyer c9d9c5
+	u8 signature_header[];
Josh Boyer c9d9c5
+	/* efi_signature_data_t signatures[][] */
Josh Boyer c9d9c5
+} efi_signature_list_t;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
 /*
Josh Boyer c9d9c5
  * All runtime access to EFI goes through this structure:
Josh Boyer c9d9c5
  */
Josh Boyer c9d9c5
-- 
Josh Boyer c9d9c5
1.8.3.1
Josh Boyer c9d9c5
Josh Boyer c9d9c5
9d22d5
From 8b75428a7e1813cd3bc225a959e63d67898e4808 Mon Sep 17 00:00:00 2001
Josh Boyer c9d9c5
From: Dave Howells <dhowells@redhat.com>
Josh Boyer c9d9c5
Date: Tue, 23 Oct 2012 09:36:28 -0400
9d22d5
Subject: [PATCH 2/5] Add an EFI signature blob parser and key loader.
Josh Boyer c9d9c5
Josh Boyer c9d9c5
X.509 certificates are loaded into the specified keyring as asymmetric type
Josh Boyer c9d9c5
keys.
Josh Boyer c9d9c5
Josh Boyer c9d9c5
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c9d9c5
---
Josh Boyer c9d9c5
 crypto/asymmetric_keys/Kconfig      |   8 +++
Josh Boyer c9d9c5
 crypto/asymmetric_keys/Makefile     |   1 +
Josh Boyer d7ee6f
 crypto/asymmetric_keys/efi_parser.c | 109 ++++++++++++++++++++++++++++++++++++
Josh Boyer c9d9c5
 include/linux/efi.h                 |   4 ++
Josh Boyer d7ee6f
 4 files changed, 122 insertions(+)
Josh Boyer c9d9c5
 create mode 100644 crypto/asymmetric_keys/efi_parser.c
Josh Boyer c9d9c5
Josh Boyer c9d9c5
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
Josh Boyer c9d9c5
index 6d2c2ea..ace9c30 100644
Josh Boyer c9d9c5
--- a/crypto/asymmetric_keys/Kconfig
Josh Boyer c9d9c5
+++ b/crypto/asymmetric_keys/Kconfig
Josh Boyer c9d9c5
@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER
Josh Boyer c9d9c5
 	  data and provides the ability to instantiate a crypto key from a
Josh Boyer c9d9c5
 	  public key packet found inside the certificate.
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
+config EFI_SIGNATURE_LIST_PARSER
Josh Boyer c9d9c5
+	bool "EFI signature list parser"
Josh Boyer c9d9c5
+	depends on EFI
Josh Boyer c9d9c5
+	select X509_CERTIFICATE_PARSER
Josh Boyer c9d9c5
+	help
Josh Boyer c9d9c5
+	  This option provides support for parsing EFI signature lists for
Josh Boyer c9d9c5
+	  X.509 certificates and turning them into keys.
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
 endif # ASYMMETRIC_KEY_TYPE
Josh Boyer c9d9c5
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
Josh Boyer c9d9c5
index 0727204..cd8388e 100644
Josh Boyer c9d9c5
--- a/crypto/asymmetric_keys/Makefile
Josh Boyer c9d9c5
+++ b/crypto/asymmetric_keys/Makefile
Josh Boyer c9d9c5
@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
 obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
Josh Boyer c9d9c5
 obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
Josh Boyer c9d9c5
+obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
 #
Josh Boyer c9d9c5
 # X.509 Certificate handling
Josh Boyer c9d9c5
diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c
Josh Boyer c9d9c5
new file mode 100644
Josh Boyer d7ee6f
index 0000000..424896a
Josh Boyer c9d9c5
--- /dev/null
Josh Boyer c9d9c5
+++ b/crypto/asymmetric_keys/efi_parser.c
Josh Boyer d7ee6f
@@ -0,0 +1,109 @@
Josh Boyer c9d9c5
+/* EFI signature/key/certificate list parser
Josh Boyer c9d9c5
+ *
Josh Boyer c9d9c5
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
Josh Boyer c9d9c5
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c9d9c5
+ *
Josh Boyer c9d9c5
+ * This program is free software; you can redistribute it and/or
Josh Boyer c9d9c5
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c9d9c5
+ * as published by the Free Software Foundation; either version
Josh Boyer c9d9c5
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c9d9c5
+ */
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+#define pr_fmt(fmt) "EFI: "fmt
Josh Boyer c9d9c5
+#include <linux/module.h>
Josh Boyer c9d9c5
+#include <linux/printk.h>
Josh Boyer c9d9c5
+#include <linux/err.h>
Josh Boyer c9d9c5
+#include <linux/efi.h>
Josh Boyer c9d9c5
+#include <keys/asymmetric-type.h>
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+/**
Josh Boyer c9d9c5
+ * parse_efi_signature_list - Parse an EFI signature list for certificates
Josh Boyer c9d9c5
+ * @data: The data blob to parse
Josh Boyer c9d9c5
+ * @size: The size of the data blob
Josh Boyer c9d9c5
+ * @keyring: The keyring to add extracted keys to
Josh Boyer c9d9c5
+ */
Josh Boyer c9d9c5
+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring)
Josh Boyer c9d9c5
+{
Josh Boyer c9d9c5
+	unsigned offs = 0;
Josh Boyer c9d9c5
+	size_t lsize, esize, hsize, elsize;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	pr_devel("-->%s(,%zu)\n", __func__, size);
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	while (size > 0) {
Josh Boyer c9d9c5
+		efi_signature_list_t list;
Josh Boyer c9d9c5
+		const efi_signature_data_t *elem;
Josh Boyer c9d9c5
+		key_ref_t key;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+		if (size < sizeof(list))
Josh Boyer c9d9c5
+			return -EBADMSG;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+		memcpy(&list, data, sizeof(list));
Josh Boyer c9d9c5
+		pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
Josh Boyer c9d9c5
+			 offs,
Josh Boyer c9d9c5
+			 list.signature_type.b, list.signature_list_size,
Josh Boyer c9d9c5
+			 list.signature_header_size, list.signature_size);
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+		lsize = list.signature_list_size;
Josh Boyer c9d9c5
+		hsize = list.signature_header_size;
Josh Boyer c9d9c5
+		esize = list.signature_size;
Josh Boyer c9d9c5
+		elsize = lsize - sizeof(list) - hsize;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+		if (lsize > size) {
Josh Boyer c9d9c5
+			pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
Josh Boyer c9d9c5
+				 __func__, offs);
Josh Boyer c9d9c5
+			return -EBADMSG;
Josh Boyer c9d9c5
+		}
Josh Boyer c9d9c5
+		if (lsize < sizeof(list) ||
Josh Boyer c9d9c5
+		    lsize - sizeof(list) < hsize ||
Josh Boyer c9d9c5
+		    esize < sizeof(*elem) ||
Josh Boyer c9d9c5
+		    elsize < esize ||
Josh Boyer c9d9c5
+		    elsize % esize != 0) {
Josh Boyer c9d9c5
+			pr_devel("- bad size combo @%x\n", offs);
Josh Boyer c9d9c5
+			return -EBADMSG;
Josh Boyer c9d9c5
+		}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+		if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) {
Josh Boyer c9d9c5
+			data += lsize;
Josh Boyer c9d9c5
+			size -= lsize;
Josh Boyer c9d9c5
+			offs += lsize;
Josh Boyer c9d9c5
+			continue;
Josh Boyer c9d9c5
+		}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+		data += sizeof(list) + hsize;
Josh Boyer c9d9c5
+		size -= sizeof(list) + hsize;
Josh Boyer c9d9c5
+		offs += sizeof(list) + hsize;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+		for (; elsize > 0; elsize -= esize) {
Josh Boyer c9d9c5
+			elem = data;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+			pr_devel("ELEM[%04x]\n", offs);
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+			key = key_create_or_update(
Josh Boyer c9d9c5
+				make_key_ref(keyring, 1),
Josh Boyer c9d9c5
+				"asymmetric",
Josh Boyer c9d9c5
+				NULL,
Josh Boyer c9d9c5
+				&elem->signature_data,
Josh Boyer c9d9c5
+				esize - sizeof(*elem),
Josh Boyer c9d9c5
+				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
Josh Boyer c9d9c5
+				KEY_USR_VIEW,
Josh Boyer d7ee6f
+				KEY_ALLOC_NOT_IN_QUOTA |
Josh Boyer d7ee6f
+				KEY_ALLOC_TRUSTED);
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+			if (IS_ERR(key))
Josh Boyer c9d9c5
+				pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
Josh Boyer c9d9c5
+				       PTR_ERR(key));
Josh Boyer c9d9c5
+			else
Josh Boyer c9d9c5
+				pr_notice("Loaded cert '%s' linked to '%s'\n",
Josh Boyer c9d9c5
+					  key_ref_to_ptr(key)->description,
Josh Boyer c9d9c5
+					  keyring->description);
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+			data += esize;
Josh Boyer c9d9c5
+			size -= esize;
Josh Boyer c9d9c5
+			offs += esize;
Josh Boyer c9d9c5
+		}
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	return 0;
Josh Boyer c9d9c5
+}
Josh Boyer c9d9c5
diff --git a/include/linux/efi.h b/include/linux/efi.h
Josh Boyer c9d9c5
index 1da1b3c..42a1d25 100644
Josh Boyer c9d9c5
--- a/include/linux/efi.h
Josh Boyer c9d9c5
+++ b/include/linux/efi.h
Josh Boyer c9d9c5
@@ -619,6 +619,10 @@ extern int efi_set_rtc_mmss(const struct timespec *now);
Josh Boyer c9d9c5
 extern void efi_reserve_boot_services(void);
Josh Boyer c9d9c5
 extern struct efi_memory_map memmap;
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
+struct key;
Josh Boyer c9d9c5
+extern int __init parse_efi_signature_list(const void *data, size_t size,
Josh Boyer c9d9c5
+					   struct key *keyring);
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
 /**
Josh Boyer c9d9c5
  * efi_range_is_wc - check the WC bit on an address range
Josh Boyer c9d9c5
  * @start: starting kvirt address
Josh Boyer c9d9c5
-- 
Josh Boyer c9d9c5
1.8.3.1
Josh Boyer c9d9c5
Josh Boyer c9d9c5
9d22d5
From 920108c0f9cc5854dd329a5dfc904e91d40a4b26 Mon Sep 17 00:00:00 2001
Josh Boyer c9d9c5
From: Josh Boyer <jwboyer@fedoraproject.org>
Josh Boyer c9d9c5
Date: Fri, 26 Oct 2012 12:36:24 -0400
9d22d5
Subject: [PATCH 3/5] KEYS: Add a system blacklist keyring
Josh Boyer c9d9c5
Josh Boyer c9d9c5
This adds an additional keyring that is used to store certificates that
Josh Boyer c9d9c5
are blacklisted.  This keyring is searched first when loading signed modules
Josh Boyer c9d9c5
and if the module's certificate is found, it will refuse to load.  This is
Josh Boyer c9d9c5
useful in cases where third party certificates are used for module signing.
Josh Boyer c9d9c5
Josh Boyer c9d9c5
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
Josh Boyer c9d9c5
---
Josh Boyer d7ee6f
 include/keys/system_keyring.h |  4 ++++
Josh Boyer d7ee6f
 init/Kconfig                  |  9 +++++++++
Josh Boyer d7ee6f
 kernel/module_signing.c       | 12 ++++++++++++
Josh Boyer d7ee6f
 kernel/system_keyring.c       | 17 +++++++++++++++++
Josh Boyer d7ee6f
 4 files changed, 42 insertions(+)
Josh Boyer c9d9c5
Josh Boyer d7ee6f
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
Josh Boyer d7ee6f
index 8dabc39..e466de1 100644
Josh Boyer d7ee6f
--- a/include/keys/system_keyring.h
Josh Boyer d7ee6f
+++ b/include/keys/system_keyring.h
Josh Boyer d7ee6f
@@ -18,6 +18,10 @@
Josh Boyer c9d9c5
 
Josh Boyer d7ee6f
 extern struct key *system_trusted_keyring;
Josh Boyer c9d9c5
 
Josh Boyer d7ee6f
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
Josh Boyer d7ee6f
+extern struct key *system_blacklist_keyring;
Josh Boyer c9d9c5
+#endif
Josh Boyer c9d9c5
+
Josh Boyer d7ee6f
 #endif
Josh Boyer c9d9c5
 
Josh Boyer d7ee6f
 #endif /* _KEYS_SYSTEM_KEYRING_H */
Josh Boyer d7ee6f
diff --git a/init/Kconfig b/init/Kconfig
9d22d5
index 0ff5407..ba76e57 100644
Josh Boyer d7ee6f
--- a/init/Kconfig
Josh Boyer d7ee6f
+++ b/init/Kconfig
9d22d5
@@ -1680,6 +1680,15 @@ config SYSTEM_TRUSTED_KEYRING
Josh Boyer c9d9c5
 
Josh Boyer d7ee6f
 	  Keys in this keyring are used by module signature checking.
Josh Boyer c9d9c5
 
Josh Boyer d7ee6f
+config SYSTEM_BLACKLIST_KEYRING
Josh Boyer d7ee6f
+	bool "Provide system-wide ring of blacklisted keys"
Josh Boyer d7ee6f
+	depends on KEYS
Josh Boyer d7ee6f
+	help
Josh Boyer d7ee6f
+	  Provide a system keyring to which blacklisted keys can be added.  Keys
Josh Boyer d7ee6f
+	  in the keyring are considered entirely untrusted.  Keys in this keyring
Josh Boyer d7ee6f
+	  are used by the module signature checking to reject loading of modules
Josh Boyer d7ee6f
+	  signed with a blacklisted key.
Josh Boyer d7ee6f
+
Josh Boyer d7ee6f
 menuconfig MODULES
Josh Boyer d7ee6f
 	bool "Enable loadable module support"
9d22d5
 	option modules
Josh Boyer c9d9c5
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
Josh Boyer d7ee6f
index 0b6b870..0a29b40 100644
Josh Boyer c9d9c5
--- a/kernel/module_signing.c
Josh Boyer c9d9c5
+++ b/kernel/module_signing.c
Josh Boyer d7ee6f
@@ -158,6 +158,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
 	pr_debug("Look up: \"%s\"\n", id);
Josh Boyer c9d9c5
 
Josh Boyer d7ee6f
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
Josh Boyer d7ee6f
+	key = keyring_search(make_key_ref(system_blacklist_keyring, 1),
Josh Boyer c9d9c5
+				   &key_type_asymmetric, id);
Josh Boyer c9d9c5
+	if (!IS_ERR(key)) {
Josh Boyer c9d9c5
+		/* module is signed with a cert in the blacklist.  reject */
Josh Boyer c9d9c5
+		pr_err("Module key '%s' is in blacklist\n", id);
Josh Boyer c9d9c5
+		key_ref_put(key);
Josh Boyer c9d9c5
+		kfree(id);
Josh Boyer c9d9c5
+		return ERR_PTR(-EKEYREJECTED);
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+#endif
Josh Boyer c9d9c5
+
Josh Boyer d7ee6f
 	key = keyring_search(make_key_ref(system_trusted_keyring, 1),
Josh Boyer c9d9c5
 			     &key_type_asymmetric, id);
Josh Boyer c9d9c5
 	if (IS_ERR(key))
Josh Boyer d7ee6f
diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
9d22d5
index 564dd93..389b50d 100644
Josh Boyer d7ee6f
--- a/kernel/system_keyring.c
Josh Boyer d7ee6f
+++ b/kernel/system_keyring.c
Josh Boyer d7ee6f
@@ -20,6 +20,9 @@
Josh Boyer d7ee6f
 
Josh Boyer d7ee6f
 struct key *system_trusted_keyring;
Josh Boyer d7ee6f
 EXPORT_SYMBOL_GPL(system_trusted_keyring);
Josh Boyer d7ee6f
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
Josh Boyer d7ee6f
+struct key *system_blacklist_keyring;
Josh Boyer d7ee6f
+#endif
Josh Boyer d7ee6f
 
356f0c
 extern __initconst const u8 system_certificate_list[];
356f0c
 extern __initconst const u8 system_certificate_list_end[];
Josh Boyer d7ee6f
@@ -41,6 +44,20 @@ static __init int system_trusted_keyring_init(void)
Josh Boyer d7ee6f
 		panic("Can't allocate system trusted keyring\n");
Josh Boyer d7ee6f
 
Josh Boyer d7ee6f
 	set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
Josh Boyer d7ee6f
+
Josh Boyer d7ee6f
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
Josh Boyer d7ee6f
+	system_blacklist_keyring = keyring_alloc(".system_blacklist_keyring",
Josh Boyer d7ee6f
+				    KUIDT_INIT(0), KGIDT_INIT(0),
Josh Boyer d7ee6f
+				    current_cred(),
Josh Boyer d7ee6f
+				    (KEY_POS_ALL & ~KEY_POS_SETATTR) |
Josh Boyer d7ee6f
+				    KEY_USR_VIEW | KEY_USR_READ,
Josh Boyer d7ee6f
+				    KEY_ALLOC_NOT_IN_QUOTA, NULL);
Josh Boyer d7ee6f
+	if (IS_ERR(system_blacklist_keyring))
Josh Boyer d7ee6f
+		panic("Can't allocate system blacklist keyring\n");
Josh Boyer d7ee6f
+
Josh Boyer d7ee6f
+	set_bit(KEY_FLAG_TRUSTED_ONLY, &system_blacklist_keyring->flags);
Josh Boyer d7ee6f
+#endif
Josh Boyer d7ee6f
+
Josh Boyer d7ee6f
 	return 0;
Josh Boyer d7ee6f
 }
Josh Boyer d7ee6f
 
Josh Boyer c9d9c5
-- 
Josh Boyer c9d9c5
1.8.3.1
Josh Boyer c9d9c5
Josh Boyer c9d9c5
9d22d5
From 69dca9998380c1931227a01205cdf23c34509753 Mon Sep 17 00:00:00 2001
Josh Boyer c9d9c5
From: Josh Boyer <jwboyer@fedoraproject.org>
Josh Boyer c9d9c5
Date: Fri, 26 Oct 2012 12:42:16 -0400
9d22d5
Subject: [PATCH 4/5] MODSIGN: Import certificates from UEFI Secure Boot
Josh Boyer c9d9c5
Josh Boyer c9d9c5
Secure Boot stores a list of allowed certificates in the 'db' variable.
Josh Boyer d7ee6f
This imports those certificates into the system trusted keyring.  This
Josh Boyer c9d9c5
allows for a third party signing certificate to be used in conjunction
Josh Boyer c9d9c5
with signed modules.  By importing the public certificate into the 'db'
Josh Boyer c9d9c5
variable, a user can allow a module signed with that certificate to
Josh Boyer c9d9c5
load.  The shim UEFI bootloader has a similar certificate list stored
Josh Boyer c9d9c5
in the 'MokListRT' variable.  We import those as well.
Josh Boyer c9d9c5
Josh Boyer c9d9c5
In the opposite case, Secure Boot maintains a list of disallowed
Josh Boyer c9d9c5
certificates in the 'dbx' variable.  We load those certificates into
Josh Boyer d7ee6f
the newly introduced system blacklist keyring and forbid any module
Josh Boyer c9d9c5
signed with those from loading.
Josh Boyer c9d9c5
Josh Boyer c9d9c5
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
Josh Boyer c9d9c5
---
Josh Boyer c9d9c5
 include/linux/efi.h   |  6 ++++
Josh Boyer c9d9c5
 init/Kconfig          |  9 +++++
Josh Boyer c9d9c5
 kernel/Makefile       |  3 ++
Josh Boyer d7ee6f
 kernel/modsign_uefi.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
Josh Boyer d7ee6f
 4 files changed, 110 insertions(+)
Josh Boyer c9d9c5
 create mode 100644 kernel/modsign_uefi.c
Josh Boyer c9d9c5
Josh Boyer c9d9c5
diff --git a/include/linux/efi.h b/include/linux/efi.h
Josh Boyer c9d9c5
index 42a1d25..d3e6036 100644
Josh Boyer c9d9c5
--- a/include/linux/efi.h
Josh Boyer c9d9c5
+++ b/include/linux/efi.h
Josh Boyer c9d9c5
@@ -395,6 +395,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
Josh Boyer c9d9c5
 #define EFI_CERT_X509_GUID \
Josh Boyer c9d9c5
     EFI_GUID(  0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
+#define EFI_IMAGE_SECURITY_DATABASE_GUID \
Josh Boyer c9d9c5
+    EFI_GUID(  0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f )
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+#define EFI_SHIM_LOCK_GUID \
Josh Boyer c9d9c5
+    EFI_GUID(  0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 )
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
 typedef struct {
Josh Boyer c9d9c5
 	efi_guid_t guid;
Josh Boyer c9d9c5
 	u64 table;
Josh Boyer c9d9c5
diff --git a/init/Kconfig b/init/Kconfig
9d22d5
index ba76e57..b09cd98 100644
Josh Boyer c9d9c5
--- a/init/Kconfig
Josh Boyer c9d9c5
+++ b/init/Kconfig
9d22d5
@@ -1799,6 +1799,15 @@ config MODULE_SIG_ALL
Josh Boyer d7ee6f
 comment "Do not forget to sign required modules with scripts/sign-file"
Josh Boyer d7ee6f
 	depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
+config MODULE_SIG_UEFI
Josh Boyer c9d9c5
+	bool "Allow modules signed with certs stored in UEFI"
Josh Boyer d7ee6f
+	depends on MODULE_SIG && SYSTEM_BLACKLIST_KEYRING && EFI
Josh Boyer c9d9c5
+	select EFI_SIGNATURE_LIST_PARSER
Josh Boyer c9d9c5
+	help
Josh Boyer c9d9c5
+	  This will import certificates stored in UEFI and allow modules
Josh Boyer c9d9c5
+	  signed with those to be loaded.  It will also disallow loading
Josh Boyer c9d9c5
+	  of modules stored in the UEFI dbx variable.
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
 choice
Josh Boyer c9d9c5
 	prompt "Which hash algorithm should modules be signed with?"
Josh Boyer c9d9c5
 	depends on MODULE_SIG
Josh Boyer c9d9c5
diff --git a/kernel/Makefile b/kernel/Makefile
9d22d5
index 6313698..cb35a89 100644
Josh Boyer c9d9c5
--- a/kernel/Makefile
Josh Boyer c9d9c5
+++ b/kernel/Makefile
9d22d5
@@ -57,6 +57,7 @@ obj-$(CONFIG_UID16) += uid16.o
Josh Boyer d7ee6f
 obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
Josh Boyer c9d9c5
 obj-$(CONFIG_MODULES) += module.o
Josh Boyer d7ee6f
 obj-$(CONFIG_MODULE_SIG) += module_signing.o
Josh Boyer c9d9c5
+obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o
Josh Boyer c9d9c5
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
Josh Boyer c9d9c5
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
Josh Boyer c9d9c5
 obj-$(CONFIG_KEXEC) += kexec.o
Josh Boyer d7ee6f
@@ -115,6 +116,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
 $(obj)/configs.o: $(obj)/config_data.h
Josh Boyer c9d9c5
 
Josh Boyer c9d9c5
+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
 # config_data.h contains the same information as ikconfig.h but gzipped.
Josh Boyer c9d9c5
 # Info from config_data can be extracted from /proc/config*
Josh Boyer c9d9c5
 targets += config_data.gz
Josh Boyer c9d9c5
diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c
Josh Boyer c9d9c5
new file mode 100644
Josh Boyer d7ee6f
index 0000000..94b0eb3
Josh Boyer c9d9c5
--- /dev/null
Josh Boyer c9d9c5
+++ b/kernel/modsign_uefi.c
Josh Boyer d7ee6f
@@ -0,0 +1,92 @@
Josh Boyer c9d9c5
+#include <linux/kernel.h>
Josh Boyer c9d9c5
+#include <linux/sched.h>
Josh Boyer c9d9c5
+#include <linux/cred.h>
Josh Boyer c9d9c5
+#include <linux/err.h>
Josh Boyer c9d9c5
+#include <linux/efi.h>
Josh Boyer c9d9c5
+#include <linux/slab.h>
Josh Boyer c9d9c5
+#include <keys/asymmetric-type.h>
Josh Boyer d7ee6f
+#include <keys/system_keyring.h>
Josh Boyer c9d9c5
+#include "module-internal.h"
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size)
Josh Boyer c9d9c5
+{
Josh Boyer c9d9c5
+	efi_status_t status;
Josh Boyer c9d9c5
+	unsigned long lsize = 4;
Josh Boyer c9d9c5
+	unsigned long tmpdb[4];
Josh Boyer c9d9c5
+	void *db = NULL;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
Josh Boyer c9d9c5
+	if (status != EFI_BUFFER_TOO_SMALL) {
Josh Boyer c9d9c5
+		pr_err("Couldn't get size: 0x%lx\n", status);
Josh Boyer c9d9c5
+		return NULL;
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	db = kmalloc(lsize, GFP_KERNEL);
Josh Boyer c9d9c5
+	if (!db) {
Josh Boyer c9d9c5
+		pr_err("Couldn't allocate memory for uefi cert list\n");
Josh Boyer c9d9c5
+		goto out;
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	status = efi.get_variable(name, guid, NULL, &lsize, db);
Josh Boyer c9d9c5
+	if (status != EFI_SUCCESS) {
Josh Boyer c9d9c5
+		kfree(db);
Josh Boyer c9d9c5
+		db = NULL;
Josh Boyer c9d9c5
+		pr_err("Error reading db var: 0x%lx\n", status);
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+out:
Josh Boyer c9d9c5
+	*size = lsize;
Josh Boyer c9d9c5
+	return db;
Josh Boyer c9d9c5
+}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+/*
Josh Boyer c9d9c5
+ *  * Load the certs contained in the UEFI databases
Josh Boyer c9d9c5
+ *   */
Josh Boyer c9d9c5
+static int __init load_uefi_certs(void)
Josh Boyer c9d9c5
+{
Josh Boyer c9d9c5
+	efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
Josh Boyer c9d9c5
+	efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
Josh Boyer c9d9c5
+	void *db = NULL, *dbx = NULL, *mok = NULL;
Josh Boyer c9d9c5
+	unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
Josh Boyer c9d9c5
+	int rc = 0;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	/* Check if SB is enabled and just return if not */
Josh Boyer c9d9c5
+	if (!efi_enabled(EFI_SECURE_BOOT))
Josh Boyer c9d9c5
+		return 0;
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	/* Get db, MokListRT, and dbx.  They might not exist, so it isn't
Josh Boyer c9d9c5
+	 * an error if we can't get them.
Josh Boyer c9d9c5
+	 */
Josh Boyer c9d9c5
+	db = get_cert_list(L"db", &secure_var, &dbsize);
Josh Boyer c9d9c5
+	if (!db) {
Josh Boyer c9d9c5
+		pr_err("MODSIGN: Couldn't get UEFI db list\n");
Josh Boyer c9d9c5
+	} else {
Josh Boyer d7ee6f
+		rc = parse_efi_signature_list(db, dbsize, system_trusted_keyring);
Josh Boyer c9d9c5
+		if (rc)
Josh Boyer c9d9c5
+			pr_err("Couldn't parse db signatures: %d\n", rc);
Josh Boyer c9d9c5
+		kfree(db);
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
Josh Boyer c9d9c5
+	if (!mok) {
Josh Boyer c9d9c5
+		pr_info("MODSIGN: Couldn't get UEFI MokListRT\n");
Josh Boyer c9d9c5
+	} else {
Josh Boyer d7ee6f
+		rc = parse_efi_signature_list(mok, moksize, system_trusted_keyring);
Josh Boyer c9d9c5
+		if (rc)
Josh Boyer c9d9c5
+			pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
Josh Boyer c9d9c5
+		kfree(mok);
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
Josh Boyer c9d9c5
+	if (!dbx) {
Josh Boyer c9d9c5
+		pr_info("MODSIGN: Couldn't get UEFI dbx list\n");
Josh Boyer c9d9c5
+	} else {
Josh Boyer c9d9c5
+		rc = parse_efi_signature_list(dbx, dbxsize,
Josh Boyer d7ee6f
+			system_blacklist_keyring);
Josh Boyer c9d9c5
+		if (rc)
Josh Boyer c9d9c5
+			pr_err("Couldn't parse dbx signatures: %d\n", rc);
Josh Boyer c9d9c5
+		kfree(dbx);
Josh Boyer c9d9c5
+	}
Josh Boyer c9d9c5
+
Josh Boyer c9d9c5
+	return rc;
Josh Boyer c9d9c5
+}
Josh Boyer c9d9c5
+late_initcall(load_uefi_certs);
Josh Boyer c9d9c5
-- 
Josh Boyer c9d9c5
1.8.3.1
Josh Boyer c9d9c5
9d22d5
9d22d5
From c8e6d256ddfa2182d5b011a4ab70f8c5c9b2b590 Mon Sep 17 00:00:00 2001
9d22d5
From: Josh Boyer <jwboyer@fedoraproject.org>
9d22d5
Date: Thu, 3 Oct 2013 10:14:23 -0400
9d22d5
Subject: [PATCH 5/5] MODSIGN: Support not importing certs from db
9d22d5
9d22d5
If a user tells shim to not use the certs/hashes in the UEFI db variable
9d22d5
for verification purposes, shim will set a UEFI variable called MokIgnoreDB.
9d22d5
Have the uefi import code look for this and not import things from the db
9d22d5
variable.
9d22d5
9d22d5
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
9d22d5
---
9d22d5
 kernel/modsign_uefi.c | 40 +++++++++++++++++++++++++++++++---------
9d22d5
 1 file changed, 31 insertions(+), 9 deletions(-)
9d22d5
9d22d5
diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c
9d22d5
index 94b0eb3..ae28b97 100644
9d22d5
--- a/kernel/modsign_uefi.c
9d22d5
+++ b/kernel/modsign_uefi.c
9d22d5
@@ -8,6 +8,23 @@
9d22d5
 #include <keys/system_keyring.h>
9d22d5
 #include "module-internal.h"
9d22d5
 
9d22d5
+static __init int check_ignore_db(void)
9d22d5
+{
9d22d5
+	efi_status_t status;
9d22d5
+	unsigned int db = 0;
9d22d5
+	unsigned long size = sizeof(db);
9d22d5
+	efi_guid_t guid = EFI_SHIM_LOCK_GUID;
9d22d5
+
9d22d5
+	/* Check and see if the MokIgnoreDB variable exists.  If that fails
9d22d5
+	 * then we don't ignore DB.  If it succeeds, we do.
9d22d5
+	 */
9d22d5
+	status = efi.get_variable(L"MokIgnoreDB", &guid, NULL, &size, &db);
9d22d5
+	if (status != EFI_SUCCESS)
9d22d5
+		return 0;
9d22d5
+
9d22d5
+	return 1;
9d22d5
+}
9d22d5
+
9d22d5
 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size)
9d22d5
 {
9d22d5
 	efi_status_t status;
9d22d5
@@ -47,23 +64,28 @@ static int __init load_uefi_certs(void)
9d22d5
 	efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
9d22d5
 	void *db = NULL, *dbx = NULL, *mok = NULL;
9d22d5
 	unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
9d22d5
-	int rc = 0;
9d22d5
+	int ignore_db, rc = 0;
9d22d5
 
9d22d5
 	/* Check if SB is enabled and just return if not */
9d22d5
 	if (!efi_enabled(EFI_SECURE_BOOT))
9d22d5
 		return 0;
9d22d5
 
9d22d5
+	/* See if the user has setup Ignore DB mode */
9d22d5
+	ignore_db = check_ignore_db();
9d22d5
+
9d22d5
 	/* Get db, MokListRT, and dbx.  They might not exist, so it isn't
9d22d5
 	 * an error if we can't get them.
9d22d5
 	 */
9d22d5
-	db = get_cert_list(L"db", &secure_var, &dbsize);
9d22d5
-	if (!db) {
9d22d5
-		pr_err("MODSIGN: Couldn't get UEFI db list\n");
9d22d5
-	} else {
9d22d5
-		rc = parse_efi_signature_list(db, dbsize, system_trusted_keyring);
9d22d5
-		if (rc)
9d22d5
-			pr_err("Couldn't parse db signatures: %d\n", rc);
9d22d5
-		kfree(db);
9d22d5
+	if (!ignore_db) {
9d22d5
+		db = get_cert_list(L"db", &secure_var, &dbsize);
9d22d5
+		if (!db) {
9d22d5
+			pr_err("MODSIGN: Couldn't get UEFI db list\n");
9d22d5
+		} else {
9d22d5
+			rc = parse_efi_signature_list(db, dbsize, system_trusted_keyring);
9d22d5
+			if (rc)
9d22d5
+				pr_err("Couldn't parse db signatures: %d\n", rc);
9d22d5
+			kfree(db);
9d22d5
+		}
9d22d5
 	}
9d22d5
 
9d22d5
 	mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
9d22d5
-- 
9d22d5
1.8.3.1
9d22d5