diff options
Diffstat (limited to 'security/integrity')
| -rw-r--r-- | security/integrity/Kconfig | 13 | ||||
| -rw-r--r-- | security/integrity/Makefile | 1 | ||||
| -rw-r--r-- | security/integrity/digsig.c | 15 | ||||
| -rw-r--r-- | security/integrity/integrity.h | 17 | ||||
| -rw-r--r-- | security/integrity/platform_certs/keyring_handler.c | 18 | ||||
| -rw-r--r-- | security/integrity/platform_certs/keyring_handler.h | 5 | ||||
| -rw-r--r-- | security/integrity/platform_certs/load_uefi.c | 4 | ||||
| -rw-r--r-- | security/integrity/platform_certs/machine_keyring.c | 77 |
8 files changed, 144 insertions, 6 deletions
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 71f0177e8716..599429f99f99 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig @@ -62,6 +62,19 @@ config INTEGRITY_PLATFORM_KEYRING provided by the platform for verifying the kexec'ed kerned image and, possibly, the initramfs signature. +config INTEGRITY_MACHINE_KEYRING + bool "Provide a keyring to which Machine Owner Keys may be added" + depends on SECONDARY_TRUSTED_KEYRING + depends on INTEGRITY_ASYMMETRIC_KEYS + depends on SYSTEM_BLACKLIST_KEYRING + depends on LOAD_UEFI_KEYS + depends on !IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY + help + If set, provide a keyring to which Machine Owner Keys (MOK) may + be added. This keyring shall contain just MOK keys. Unlike keys + in the platform keyring, keys contained in the .machine keyring will + be trusted within the kernel. + config LOAD_UEFI_KEYS depends on INTEGRITY_PLATFORM_KEYRING depends on EFI diff --git a/security/integrity/Makefile b/security/integrity/Makefile index 7ee39d66cf16..d0ffe37dc1d6 100644 --- a/security/integrity/Makefile +++ b/security/integrity/Makefile @@ -10,6 +10,7 @@ integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += platform_certs/platform_keyring.o +integrity-$(CONFIG_INTEGRITY_MACHINE_KEYRING) += platform_certs/machine_keyring.o integrity-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/efi_parser.o \ platform_certs/load_uefi.o \ platform_certs/keyring_handler.o diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 3b06a01bd0fd..c8c8a4a4e7a0 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -30,6 +30,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = { ".ima", #endif ".platform", + ".machine", }; #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY @@ -111,6 +112,8 @@ static int __init __integrity_init_keyring(const unsigned int id, } else { if (id == INTEGRITY_KEYRING_PLATFORM) set_platform_trusted_keys(keyring[id]); + if (id == INTEGRITY_KEYRING_MACHINE && trust_moklist()) + set_machine_trusted_keys(keyring[id]); if (id == INTEGRITY_KEYRING_IMA) load_module_cert(keyring[id]); } @@ -126,7 +129,8 @@ int __init integrity_init_keyring(const unsigned int id) perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH; - if (id == INTEGRITY_KEYRING_PLATFORM) { + if (id == INTEGRITY_KEYRING_PLATFORM || + id == INTEGRITY_KEYRING_MACHINE) { restriction = NULL; goto out; } @@ -139,7 +143,14 @@ int __init integrity_init_keyring(const unsigned int id) return -ENOMEM; restriction->check = restrict_link_to_ima; - perm |= KEY_USR_WRITE; + + /* + * MOK keys can only be added through a read-only runtime services + * UEFI variable during boot. No additional keys shall be allowed to + * load into the machine keyring following init from userspace. + */ + if (id != INTEGRITY_KEYRING_MACHINE) + perm |= KEY_USR_WRITE; out: return __integrity_init_keyring(id, perm, restriction); diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 547425c20e11..2e214c761158 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -151,7 +151,8 @@ int integrity_kernel_read(struct file *file, loff_t offset, #define INTEGRITY_KEYRING_EVM 0 #define INTEGRITY_KEYRING_IMA 1 #define INTEGRITY_KEYRING_PLATFORM 2 -#define INTEGRITY_KEYRING_MAX 3 +#define INTEGRITY_KEYRING_MACHINE 3 +#define INTEGRITY_KEYRING_MAX 4 extern struct dentry *integrity_dir; @@ -283,3 +284,17 @@ static inline void __init add_to_platform_keyring(const char *source, { } #endif + +#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING +void __init add_to_machine_keyring(const char *source, const void *data, size_t len); +bool __init trust_moklist(void); +#else +static inline void __init add_to_machine_keyring(const char *source, + const void *data, size_t len) +{ +} +static inline bool __init trust_moklist(void) +{ + return false; +} +#endif diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c index 5604bd57c990..1db4d3b4356d 100644 --- a/security/integrity/platform_certs/keyring_handler.c +++ b/security/integrity/platform_certs/keyring_handler.c @@ -9,6 +9,7 @@ #include <keys/asymmetric-type.h> #include <keys/system_keyring.h> #include "../integrity.h" +#include "keyring_handler.h" static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID; static efi_guid_t efi_cert_x509_sha256_guid __initdata = @@ -66,7 +67,7 @@ static __init void uefi_revocation_list_x509(const char *source, /* * Return the appropriate handler for particular signature list types found in - * the UEFI db and MokListRT tables. + * the UEFI db tables. */ __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type) { @@ -77,6 +78,21 @@ __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type) /* * Return the appropriate handler for particular signature list types found in + * the MokListRT tables. + */ +__init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type) +{ + if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) { + if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) && trust_moklist()) + return add_to_machine_keyring; + else + return add_to_platform_keyring; + } + return 0; +} + +/* + * Return the appropriate handler for particular signature list types found in * the UEFI dbx and MokListXRT tables. */ __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type) diff --git a/security/integrity/platform_certs/keyring_handler.h b/security/integrity/platform_certs/keyring_handler.h index 2462bfa08fe3..284558f30411 100644 --- a/security/integrity/platform_certs/keyring_handler.h +++ b/security/integrity/platform_certs/keyring_handler.h @@ -25,6 +25,11 @@ void blacklist_binary(const char *source, const void *data, size_t len); efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type); /* + * Return the handler for particular signature list types found in the mok. + */ +efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type); + +/* * Return the handler for particular signature list types found in the dbx. */ efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type); diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c index 08b6d12f99b4..5f45c3c07dbd 100644 --- a/security/integrity/platform_certs/load_uefi.c +++ b/security/integrity/platform_certs/load_uefi.c @@ -95,7 +95,7 @@ static int __init load_moklist_certs(void) rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)", mokvar_entry->data, mokvar_entry->data_size, - get_handler_for_db); + get_handler_for_mok); /* All done if that worked. */ if (!rc) return rc; @@ -110,7 +110,7 @@ static int __init load_moklist_certs(void) mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status); if (mok) { rc = parse_efi_signature_list("UEFI:MokListRT", - mok, moksize, get_handler_for_db); + mok, moksize, get_handler_for_mok); kfree(mok); if (rc) pr_err("Couldn't parse MokListRT signatures: %d\n", rc); diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c new file mode 100644 index 000000000000..7aaed7950b6e --- /dev/null +++ b/security/integrity/platform_certs/machine_keyring.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Machine keyring routines. + * + * Copyright (c) 2021, Oracle and/or its affiliates. + */ + +#include <linux/efi.h> +#include "../integrity.h" + +static bool trust_mok; + +static __init int machine_keyring_init(void) +{ + int rc; + + rc = integrity_init_keyring(INTEGRITY_KEYRING_MACHINE); + if (rc) + return rc; + + pr_notice("Machine keyring initialized\n"); + return 0; +} +device_initcall(machine_keyring_init); + +void __init add_to_machine_keyring(const char *source, const void *data, size_t len) +{ + key_perm_t perm; + int rc; + + perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW; + rc = integrity_load_cert(INTEGRITY_KEYRING_MACHINE, source, data, len, perm); + + /* + * Some MOKList keys may not pass the machine keyring restrictions. + * If the restriction check does not pass and the platform keyring + * is configured, try to add it into that keyring instead. + */ + if (rc && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) + rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source, + data, len, perm); + + if (rc) + pr_info("Error adding keys to machine keyring %s\n", source); +} + +/* + * Try to load the MokListTrustedRT MOK variable to see if we should trust + * the MOK keys within the kernel. It is not an error if this variable + * does not exist. If it does not exist, MOK keys should not be trusted + * within the machine keyring. + */ +static __init bool uefi_check_trust_mok_keys(void) +{ + struct efi_mokvar_table_entry *mokvar_entry; + + mokvar_entry = efi_mokvar_entry_find("MokListTrustedRT"); + + if (mokvar_entry) + return true; + + return false; +} + +bool __init trust_moklist(void) +{ + static bool initialized; + + if (!initialized) { + initialized = true; + + if (uefi_check_trust_mok_keys()) + trust_mok = true; + } + + return trust_mok; +} |
