From d3bfe84129f65e0af2450743ebdab33d161d01c9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Apr 2016 16:14:27 +0100 Subject: certs: Add a secondary system keyring that can be added to dynamically Add a secondary system keyring that can be added to by root whilst the system is running - provided the key being added is vouched for by a key built into the kernel or already added to the secondary keyring. Rename .system_keyring to .builtin_trusted_keys to distinguish it more obviously from the new keyring (called .secondary_trusted_keys). The new keyring needs to be enabled with CONFIG_SECONDARY_TRUSTED_KEYRING. If the secondary keyring is enabled, a link is created from that to .builtin_trusted_keys so that the the latter will automatically be searched too if the secondary keyring is searched. Signed-off-by: David Howells --- certs/Kconfig | 8 +++++ certs/system_keyring.c | 87 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 16 deletions(-) (limited to 'certs') diff --git a/certs/Kconfig b/certs/Kconfig index 743d480..fc5955f 100644 --- a/certs/Kconfig +++ b/certs/Kconfig @@ -56,4 +56,12 @@ config SYSTEM_EXTRA_CERTIFICATE_SIZE This is the number of bytes reserved in the kernel image for a certificate to be inserted. +config SECONDARY_TRUSTED_KEYRING + bool "Provide a keyring to which extra trustable keys may be added" + depends on SYSTEM_TRUSTED_KEYRING + help + If set, provide a keyring to which extra keys may be added, provided + those keys are not blacklisted and are vouched for by a key built + into the kernel or already in the secondary trusted keyring. + endmenu diff --git a/certs/system_keyring.c b/certs/system_keyring.c index e460d00..50979d6 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -18,41 +18,88 @@ #include #include -static struct key *system_trusted_keyring; +static struct key *builtin_trusted_keys; +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +static struct key *secondary_trusted_keys; +#endif extern __initconst const u8 system_certificate_list[]; extern __initconst const unsigned long system_certificate_list_size; /** - * restrict_link_by_builtin_trusted - Restrict keyring addition by system CA + * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA * * Restrict the addition of keys into a keyring based on the key-to-be-added - * being vouched for by a key in the system keyring. + * being vouched for by a key in the built in system keyring. */ int restrict_link_by_builtin_trusted(struct key *keyring, const struct key_type *type, const union key_payload *payload) { - return restrict_link_by_signature(system_trusted_keyring, - type, payload); + return restrict_link_by_signature(builtin_trusted_keys, type, payload); } +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +/** + * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring + * addition by both builtin and secondary keyrings + * + * Restrict the addition of keys into a keyring based on the key-to-be-added + * being vouched for by a key in either the built-in or the secondary system + * keyrings. + */ +int restrict_link_by_builtin_and_secondary_trusted( + struct key *keyring, + const struct key_type *type, + const union key_payload *payload) +{ + /* If we have a secondary trusted keyring, then that contains a link + * through to the builtin keyring and the search will follow that link. + */ + if (type == &key_type_keyring && + keyring == secondary_trusted_keys && + payload == &builtin_trusted_keys->payload) + /* Allow the builtin keyring to be added to the secondary */ + return 0; + + return restrict_link_by_signature(secondary_trusted_keys, type, payload); +} +#endif + /* - * Load the compiled-in keys + * Create the trusted keyrings */ static __init int system_trusted_keyring_init(void) { - pr_notice("Initialise system trusted keyring\n"); + pr_notice("Initialise system trusted keyrings\n"); - system_trusted_keyring = - keyring_alloc(".system_keyring", + builtin_trusted_keys = + keyring_alloc(".builtin_trusted_keys", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, - restrict_link_by_builtin_trusted, NULL); - if (IS_ERR(system_trusted_keyring)) - panic("Can't allocate system trusted keyring\n"); + NULL, NULL); + if (IS_ERR(builtin_trusted_keys)) + panic("Can't allocate builtin trusted keyring\n"); + +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING + secondary_trusted_keys = + keyring_alloc(".secondary_trusted_keys", + KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH | + KEY_USR_WRITE), + KEY_ALLOC_NOT_IN_QUOTA, + restrict_link_by_builtin_and_secondary_trusted, + NULL); + if (IS_ERR(secondary_trusted_keys)) + panic("Can't allocate secondary trusted keyring\n"); + + if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0) + panic("Can't link trusted keyrings\n"); +#endif + return 0; } @@ -88,7 +135,7 @@ static __init int load_system_certificate_list(void) if (plen > end - p) goto dodgy_cert; - key = key_create_or_update(make_key_ref(system_trusted_keyring, 1), + key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1), "asymmetric", NULL, p, @@ -125,7 +172,8 @@ late_initcall(load_system_certificate_list); * @len: Size of @data. * @raw_pkcs7: The PKCS#7 message that is the signature. * @pkcs7_len: The size of @raw_pkcs7. - * @trusted_keys: Trusted keys to use (NULL for system_trusted_keyring). + * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only, + * (void *)1UL for all trusted keys). * @usage: The use to which the key is being put. * @view_content: Callback to gain access to content. * @ctx: Context for callback. @@ -157,8 +205,15 @@ int verify_pkcs7_signature(const void *data, size_t len, if (ret < 0) goto error; - if (!trusted_keys) - trusted_keys = system_trusted_keyring; + if (!trusted_keys) { + trusted_keys = builtin_trusted_keys; + } else if (trusted_keys == (void *)1UL) { +#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING + trusted_keys = secondary_trusted_keys; +#else + trusted_keys = builtin_trusted_keys; +#endif + } ret = pkcs7_validate_trust(pkcs7, trusted_keys); if (ret < 0) { if (ret == -ENOKEY) -- cgit v1.1