[PATCH 4/4] integrity: CA enforcement in machine keyring
From: Eric Snowberg <eric.snowberg@oracle.com>
Date: 2022-03-01 17:40:06
Also in:
keyrings, linux-crypto, lkml
Subsystem:
certificate handling, extended verification module (evm), integrity measurement architecture (ima), keys/keyrings, security subsystem, the rest · Maintainers:
David Howells, David Woodhouse, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Jarkko Sakkinen, Paul Moore, James Morris, "Serge E. Hallyn", Linus Torvalds
When INTEGRITY_MACHINE_KEYRING is set, all Machine Owner Keys (MOK) are loaded into the machine keyring. Add a new INTEGRITY_MACHINE_KEYRING_CA_ENFORCED option where only MOK CA keys are added. Set the restriction check to restrict_link_by_ca. This will only allow CA keys into the machine keyring. Unlike when INTEGRITY_MACHINE_KEYRING is enabled, IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY may also be enabled, allowing IMA to use keys in the machine keyring as another trust anchor. Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com> --- certs/system_keyring.c | 9 +++++--- include/keys/system_keyring.h | 3 ++- security/integrity/Kconfig | 21 +++++++++++++++++++ security/integrity/Makefile | 1 + security/integrity/digsig.c | 14 ++++++++++--- security/integrity/integrity.h | 3 ++- .../platform_certs/keyring_handler.c | 4 +++- 7 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 05b66ce9d1c9..0811b44cf3bf 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c@@ -22,7 +22,8 @@ static struct key *builtin_trusted_keys; #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING static struct key *secondary_trusted_keys; #endif -#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING +#if defined(CONFIG_INTEGRITY_MACHINE_KEYRING) || \ + defined(CONFIG_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED) static struct key *machine_trusted_keys; #endif #ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
@@ -89,7 +90,8 @@ static __init struct key_restriction *get_builtin_and_secondary_restriction(void if (!restriction) panic("Can't allocate secondary trusted keyring restriction\n"); - if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING)) + if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) || + IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED)) restriction->check = restrict_link_by_builtin_secondary_and_machine; else restriction->check = restrict_link_by_builtin_and_secondary_trusted;
@@ -97,7 +99,8 @@ static __init struct key_restriction *get_builtin_and_secondary_restriction(void return restriction; } #endif -#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING +#if defined(CONFIG_INTEGRITY_MACHINE_KEYRING) || \ + defined(CONFIG_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED) void __init set_machine_trusted_keys(struct key *keyring) { machine_trusted_keys = keyring;
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 91e080efb918..e4a6574bbcb6 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h@@ -45,7 +45,8 @@ extern int restrict_link_by_builtin_and_secondary_trusted( #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted #endif -#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING +#if defined(CONFIG_INTEGRITY_MACHINE_KEYRING) || \ + defined(CONFIG_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED) extern int restrict_link_by_builtin_secondary_and_machine( struct key *dest_keyring, const struct key_type *type,
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 599429f99f99..14c927eea5ee 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig@@ -62,6 +62,14 @@ config INTEGRITY_PLATFORM_KEYRING provided by the platform for verifying the kexec'ed kerned image and, possibly, the initramfs signature. + +choice + prompt "Machine keyring" + default INTEGRITY_MACHINE_NONE + +config INTEGRITY_MACHINE_NONE + bool "Do not enable the Machine Owner Keyring" + config INTEGRITY_MACHINE_KEYRING bool "Provide a keyring to which Machine Owner Keys may be added" depends on SECONDARY_TRUSTED_KEYRING
@@ -75,6 +83,19 @@ config INTEGRITY_MACHINE_KEYRING in the platform keyring, keys contained in the .machine keyring will be trusted within the kernel. +config INTEGRITY_MACHINE_KEYRING_CA_ENFORCED + bool "Provide a keyring to which Machine Owner CA Keys may be added" + depends on SECONDARY_TRUSTED_KEYRING + depends on INTEGRITY_ASYMMETRIC_KEYS + depends on SYSTEM_BLACKLIST_KEYRING + depends on LOAD_UEFI_KEYS + help + If set, provide a keyring to which CA Machine Owner Keys (MOK) may + be added. This keyring shall contain just CA MOK keys. Unlike keys + in the platform keyring, keys contained in the .machine keyring will + be trusted within the kernel. +endchoice + config LOAD_UEFI_KEYS depends on INTEGRITY_PLATFORM_KEYRING depends on EFI
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index d0ffe37dc1d6..370ee63774c3 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile@@ -11,6 +11,7 @@ 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_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED) += 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 c8c8a4a4e7a0..041edd9744db 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c@@ -34,7 +34,11 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = { }; #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY +#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED +#define restrict_link_to_ima restrict_link_by_builtin_secondary_and_machine +#else #define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted +#endif #else #define restrict_link_to_ima restrict_link_by_builtin_trusted #endif
@@ -130,19 +134,23 @@ int __init integrity_init_keyring(const unsigned int id) | KEY_USR_READ | KEY_USR_SEARCH; if (id == INTEGRITY_KEYRING_PLATFORM || - id == INTEGRITY_KEYRING_MACHINE) { + (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING))) { restriction = NULL; goto out; } - if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING)) + if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING) && + id != INTEGRITY_KEYRING_MACHINE) return 0; restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); if (!restriction) return -ENOMEM; - restriction->check = restrict_link_to_ima; + if (id == INTEGRITY_KEYRING_MACHINE) + restriction->check = restrict_link_by_ca; + else + restriction->check = restrict_link_to_ima; /* * MOK keys can only be added through a read-only runtime services
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 2e214c761158..ca4d72fbd045 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h@@ -285,7 +285,8 @@ static inline void __init add_to_platform_keyring(const char *source, } #endif -#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING +#if defined(CONFIG_INTEGRITY_MACHINE_KEYRING) || \ + defined(CONFIG_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED) void __init add_to_machine_keyring(const char *source, const void *data, size_t len); bool __init trust_moklist(void); #else
diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c
index a2464f3e66cc..9c456ad0ab67 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c@@ -61,7 +61,9 @@ __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type) __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()) + if ((IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) || + IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING_CA_ENFORCED)) && + trust_moklist()) return add_to_machine_keyring; else return add_to_platform_keyring;
--
2.27.0