From: Nayna Jain nayna@linux.ibm.com
The patch refactors integrity_load_x509(), making it a wrapper for a new function named integrity_add_key(). This patch also defines a new function named integrity_load_cert() for loading the platform keys.
Signed-off-by: Nayna Jain nayna@linux.ibm.com Reviewed-by: Mimi Zohar zohar@linux.ibm.com Acked-by: Serge Hallyn serge@hallyn.com Reviewed-by: James Morris james.morris@microsoft.com Reviewed-by: Thiago Jung Bauermann bauerman@linux.ibm.com Signed-off-by: Mimi Zohar zohar@linux.ibm.com Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com --- security/integrity/digsig.c | 67 ++++++++++++------- security/integrity/integrity.h | 20 ++++++ .../platform_certs/platform_keyring.c | 23 +++++++ 3 files changed, 86 insertions(+), 24 deletions(-)
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 9902fe1973ff..9589192272d0 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -88,8 +88,7 @@ static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), KGIDT_INIT(0), cred, perm, - KEY_ALLOC_NOT_IN_QUOTA, - restriction, NULL); + KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL); if (IS_ERR(keyring[id])) { err = PTR_ERR(keyring[id]); pr_info("Can't allocate %s keyring (%d)\n", @@ -127,16 +126,38 @@ int __init integrity_init_keyring(const unsigned int id) return __integrity_init_keyring(id, perm, restriction); }
-int __init integrity_load_x509(const unsigned int id, const char *path) +int __init integrity_add_key(const unsigned int id, const void *data, + off_t size, key_perm_t perm) { key_ref_t key; - void *data; - loff_t size; - int rc; + int rc = 0;
if (!keyring[id]) return -EINVAL;
+ key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric", + NULL, data, size, perm, + KEY_ALLOC_NOT_IN_QUOTA); + if (IS_ERR(key)) { + rc = PTR_ERR(key); + pr_err("Problem loading X.509 certificate %d\n", rc); + } else { + pr_notice("Loaded X.509 cert '%s'\n", + key_ref_to_ptr(key)->description); + key_ref_put(key); + } + + return rc; + +} + +int __init integrity_load_x509(const unsigned int id, const char *path) +{ + void *data; + loff_t size; + int rc; + key_perm_t perm; + rc = kernel_read_file_from_path(path, &data, &size, 0, READING_X509_CERTIFICATE); if (rc < 0) { @@ -144,23 +165,21 @@ int __init integrity_load_x509(const unsigned int id, const char *path) return rc; }
- key = key_create_or_update(make_key_ref(keyring[id], 1), - "asymmetric", - NULL, - data, - size, - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA); - if (IS_ERR(key)) { - rc = PTR_ERR(key); - pr_err("Problem loading X.509 certificate (%d): %s\n", - rc, path); - } else { - pr_notice("Loaded X.509 cert '%s': %s\n", - key_ref_to_ptr(key)->description, path); - key_ref_put(key); - } + perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ; + + pr_info("Loading X.509 certificate: %s\n", path); + rc = integrity_add_key(id, (const void *)data, size, perm); + vfree(data); - return 0; + return rc; +} + +int __init integrity_load_cert(const unsigned int id, const char *source, + const void *data, size_t len, key_perm_t perm) +{ + if (!data) + return -EINVAL; + + pr_info("Loading X.509 certificate: %s\n", source); + return integrity_add_key(id, data, len, perm); } diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index be5acd395d5f..0750bab0dcf8 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -154,6 +154,8 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
int __init integrity_init_keyring(const unsigned int id); int __init integrity_load_x509(const unsigned int id, const char *path); +int __init integrity_load_cert(const unsigned int id, const char *source, + const void *data, size_t len, key_perm_t perm); #else
static inline int integrity_digsig_verify(const unsigned int id, @@ -167,6 +169,14 @@ static inline int integrity_init_keyring(const unsigned int id) { return 0; } + +static inline int __init integrity_load_cert(const unsigned int id, + const char *source, + const void *data, size_t len, + key_perm_t perm) +{ + return 0; +} #endif /* CONFIG_INTEGRITY_SIGNATURE */
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS @@ -223,3 +233,13 @@ integrity_audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type) }
#endif + +#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING +void __init add_to_platform_keyring(const char *source, const void *data, + size_t len); +#else +static inline void __init add_to_platform_keyring(const char *source, + const void *data, size_t len) +{ +} +#endif diff --git a/security/integrity/platform_certs/platform_keyring.c b/security/integrity/platform_certs/platform_keyring.c index 79f80af5b470..bcafd7387729 100644 --- a/security/integrity/platform_certs/platform_keyring.c +++ b/security/integrity/platform_certs/platform_keyring.c @@ -14,6 +14,29 @@ #include <linux/slab.h> #include "../integrity.h"
+/** + * add_to_platform_keyring - Add to platform keyring without validation. + * @source: Source of key + * @data: The blob holding the key + * @len: The length of the data blob + * + * Add a key to the platform keyring without checking its trust chain. This + * is available only during kernel initialisation. + */ +void __init add_to_platform_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_PLATFORM, source, data, len, + perm); + if (rc) + pr_info("Error adding keys to platform keyring %s\n", source); +} + /* * Create the trusted keyrings. */