]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
MODSIGN: Import certificates from UEFI Secure Boot
authorJosh Boyer <jwboyer at fedoraproject.org>
Fri, 26 Oct 2012 16:36:24 +0000 (12:36 -0400)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Mon, 10 Aug 2015 16:24:05 +0000 (09:24 -0700)
Orabug: 21539498

Secure Boot stores a list of allowed certificates in the 'db' variable.
This imports those certificates into the module signing keyring.  This
allows for a third party signing certificate to be used in conjunction
with signed modules.  By importing the public certificate into the 'db'
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 module blacklist keyring and forbid any module
signed with those from loading.

Signed-off-by: Josh Boyer <jwboyer at fedoraproject.org>
Signed-off-by: Guangyu Sun <guangyu.sun@oracle.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
include/linux/efi.h
init/Kconfig
kernel/Makefile
kernel/modsign_uefi.c [new file with mode: 0644]
kernel/module_signing.c

index 2642082f3b008282e14d68a20301859b83756466..d2ca9263c1ffd414507a9428cad7d35afbef059a 100644 (file)
@@ -390,6 +390,12 @@ typedef struct {
 #define EFI_CERT_X509_GUID \
     EFI_GUID(  0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
 
+#define EFI_IMAGE_SECURITY_DATABASE_GUID \
+    EFI_GUID(  0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f )
+
+#define EFI_SHIM_LOCK_GUID \
+    EFI_GUID(  0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 )
+
 typedef struct {
        void *poll_mem;
        void *poll_io;
index c64710f45b619ed41f7bf2b6ca9485c1a8cf55c7..9f49a995c007889bdf403409c9788fbb2c419105 100644 (file)
@@ -1912,6 +1912,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
index 60c302cfb4d3cbb976f0b2d69f28a96899b1d4ce..3de3ba7b98e49186919fed1ca966c47d8bccd82d 100644 (file)
@@ -48,6 +48,7 @@ obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.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) += kexec.o
@@ -101,6 +102,8 @@ obj-$(CONFIG_TORTURE_TEST) += torture.o
 
 $(obj)/configs.o: $(obj)/config_data.h
 
+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar
+
 # config_data.h contains the same information as ikconfig.h but gzipped.
 # Info from config_data can be extracted from /proc/config*
 targets += config_data.gz
diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c
new file mode 100644 (file)
index 0000000..94b0eb3
--- /dev/null
@@ -0,0 +1,92 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
+#include <linux/err.h>
+#include <linux/efi.h>
+#include <linux/slab.h>
+#include <keys/asymmetric-type.h>
+#include <keys/system_keyring.h>
+#include "module-internal.h"
+
+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;
+
+       status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
+       if (status != EFI_BUFFER_TOO_SMALL) {
+               pr_err("Couldn't get size: 0x%lx\n", status);
+               return NULL;
+       }
+
+       db = kmalloc(lsize, GFP_KERNEL);
+       if (!db) {
+               pr_err("Couldn't allocate memory for uefi cert list\n");
+               goto out;
+       }
+
+       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);
+       }
+out:
+       *size = lsize;
+       return db;
+}
+
+/*
+ *  * 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;
+       efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
+       void *db = NULL, *dbx = NULL, *mok = NULL;
+       unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
+       int rc = 0;
+
+       /* Check if SB is enabled and just return if not */
+       if (!efi_enabled(EFI_SECURE_BOOT))
+               return 0;
+
+       /* Get db, MokListRT, and dbx.  They might not exist, so it isn't
+        * an error if we can't get them.
+        */
+       db = get_cert_list(L"db", &secure_var, &dbsize);
+       if (!db) {
+               pr_err("MODSIGN: Couldn't get UEFI db list\n");
+       } else {
+               rc = parse_efi_signature_list(db, dbsize, system_trusted_keyring);
+               if (rc)
+                       pr_err("Couldn't parse db signatures: %d\n", rc);
+               kfree(db);
+       }
+
+       mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
+       if (!mok) {
+               pr_info("MODSIGN: Couldn't get UEFI MokListRT\n");
+       } else {
+               rc = parse_efi_signature_list(mok, moksize, system_trusted_keyring);
+               if (rc)
+                       pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
+               kfree(mok);
+       }
+
+       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,
+                       system_blacklist_keyring);
+               if (rc)
+                       pr_err("Couldn't parse dbx signatures: %d\n", rc);
+               kfree(dbx);
+       }
+
+       return rc;
+}
+late_initcall(load_uefi_certs);
index ddcfdca90f19d48ad10fba2cdaac9f8205faa092..fed815fcdaf2a65fed4cb2d3b74b3429fb56fa08 100644 (file)
@@ -159,7 +159,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
        pr_debug("Look up: \"%s\"\n", id);
 
 #ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
-       key = keyring_search(make_key_ref(system_blacklist_keyring,, 1),
+       key = keyring_search(make_key_ref(system_blacklist_keyring, 1),
                                   &key_type_asymmetric, id);
        if (!IS_ERR(key)) {
                /* module is signed with a cert in the blacklist.  reject */