Commit 89052b26 authored by Josh Boyer's avatar Josh Boyer Committed by Tim Gardner

UBUNTU: SAUCE: (noup) MODSIGN: Import certificates from UEFI Secure Boot

BugLink: http://bugs.launchpad.net/bugs/1571691
git://pkgs.fedoraproject.org/rpms/kernel.git

Secure Boot stores a list of allowed certificates in the 'db' variable.
This imports those certificates into the system trusted 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 system blacklist keyring and forbid any module
signed with those from loading.
Signed-off-by: default avatarJosh Boyer <jwboyer@fedoraproject.org>
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
Signed-off-by: default avatarAndy Whitcroft <andy.whitcroft@canonical.com>
Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
parent 66a4b159
......@@ -604,6 +604,12 @@ typedef struct {
u64 table;
} efi_config_table_64_t;
#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 {
efi_guid_t guid;
u32 table;
......
......@@ -1945,6 +1945,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
......
......@@ -47,6 +47,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
......@@ -104,6 +105,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
# config_data.h contains the same information as ikconfig.h but gzipped.
......
#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);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment