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