[PATCH 4/4] integrity: CA enforcement in machine keyring

From: Eric Snowberg
Date: Tue Mar 01 2022 - 12:40:06 EST


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@xxxxxxxxxx>
---
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