From: Roberto Sassu roberto.sassu@huawei.com
Provide a function to load user asymmetric keys from a keyring blob to the keyring supplied:
int preload_uasym_keys(const u8 *data, size_t data_len, struct key *keyring);
Signed-off-by: Roberto Sassu roberto.sassu@huawei.com --- crypto/asymmetric_keys/Makefile | 3 +- crypto/asymmetric_keys/uasym_key_preload.c | 99 ++++++++++++++++++++++ include/crypto/uasym_keys_sigs.h | 9 ++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 crypto/asymmetric_keys/uasym_key_preload.c
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index cbaadab0c42..2cb4087f867 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -84,4 +84,5 @@ obj-$(CONFIG_UASYM_KEYS_SIGS) += uasym_keys_sigs.o uasym_keys_sigs-y := \ uasym_parser.o \ uasym_key_parser.o \ - uasym_sig_parser.o + uasym_sig_parser.o \ + uasym_key_preload.o diff --git a/crypto/asymmetric_keys/uasym_key_preload.c b/crypto/asymmetric_keys/uasym_key_preload.c new file mode 100644 index 00000000000..dfb3e79cf7d --- /dev/null +++ b/crypto/asymmetric_keys/uasym_key_preload.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Authors: + * David Howells dhowells@redhat.com + * Roberto Sassu roberto.sassu@huawei.com + * + * Load user asymmetric keys from a keyring blob. + */ + +#include <linux/module.h> +#include <linux/key.h> +#include <linux/err.h> + +#include "uasym_parser.h" + +/** + * create_uasym_key - Create a user asymmetric key + * @data_start: Where the user asymmetric key starts in the blob + * @data_end: Where the user asymmetric key ends in the blob + * @keyring: The keyring to add the new key to + * + * Create a user asymmetric key from the supplied buffer. + */ +static void __init create_uasym_key(const u8 *data_start, const u8 *data_end, + struct key *keyring) +{ + key_ref_t key; + + key = key_create_or_update(make_key_ref(keyring, 1), "asymmetric", NULL, + data_start, data_end - data_start, + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ), + KEY_ALLOC_NOT_IN_QUOTA | + KEY_ALLOC_BUILT_IN | + KEY_ALLOC_BYPASS_RESTRICTION); + if (IS_ERR(key)) { + pr_notice("Ignoring user asymmetric key, error: %ld\n", + PTR_ERR(key)); + return; + } + + pr_notice("Loaded user asymmetric key '%s'\n", + key_ref_to_ptr(key)->description); + + key_ref_put(key); +} + +/** + * preload_uasym_keys - Load user asymmetric keys from a keyring blob + * @data: The keyring blob containing the user asymmetric keys + * @data_len: The size of the @data blob + * @keyring: The keyring to add the new keys to + * + * Preload a pack of user_asymmetric keys from a keyring blob. + * + * The callers should override the current creds if they want the keys to be + * owned by someone other than the current process's owner. Keys will not be + * accounted towards the owner's quota. + * + * This function may only be called whilst the kernel is booting. + * + * Return: Zero on success, a negative value otherwise. + */ +int __init preload_uasym_keys(const u8 *data, size_t data_len, + struct key *keyring) +{ + const u8 *data_ptr = data, *data_end = data + data_len; + u8 data_type; + u16 num_fields; + u64 total_len; + int ret; + + kenter(""); + + while (data_ptr < data_end) { + ret = uasym_parse_hdr(&data_ptr, &data_len, &data_type, + &num_fields, &total_len); + if (ret < 0) { + pr_notice("Unable to parse keyring blob, ret: %d\n", + ret); + return ret; + } + + if (data_type != TYPE_KEY) { + data_ptr += total_len; + continue; + } + + create_uasym_key(data_ptr - sizeof(struct uasym_hdr), + data_ptr + total_len, keyring); + + data_ptr += total_len; + } + + return 0; +} diff --git a/include/crypto/uasym_keys_sigs.h b/include/crypto/uasym_keys_sigs.h index d594a387766..7270e38275f 100644 --- a/include/crypto/uasym_keys_sigs.h +++ b/include/crypto/uasym_keys_sigs.h @@ -30,6 +30,9 @@ extern int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, extern int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, struct key *keyring); extern void uasym_sig_free_message(struct uasym_sig_message *uasym_sig); + +int __init preload_uasym_keys(const u8 *data, size_t data_len, + struct key *keyring); #else static inline struct uasym_sig_message * uasym_sig_parse_message(const u8 *sig_data, size_t sig_len) @@ -69,5 +72,11 @@ static inline void uasym_sig_free_message(struct uasym_sig_message *uasym_sig) { }
+static inline int __init preload_uasym_keys(const u8 *data, size_t data_len, + struct key *keyring) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_UASYM_KEYS_SIGS */ #endif /* _CRYPTO_UASYM_KEYS_SIGS_H */