From: Roberto Sassu <roberto.sassu@xxxxxxxxxx> 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@xxxxxxxxxx> --- crypto/asymmetric_keys/Makefile | 3 +- crypto/asymmetric_keys/uasym_key_preload.c | 102 +++++++++++++++++++++ include/crypto/uasym_keys_sigs.h | 9 ++ 3 files changed, 113 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 191b7fe8359..ffc6c7d6e65 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -82,4 +82,5 @@ $(obj)/mscode.asn1.o: $(obj)/mscode.asn1.c $(obj)/mscode.asn1.h # obj-$(CONFIG_UASYM_KEYS_SIGS) += uasym_keys_sigs.o uasym_keys_sigs-y := 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..039dbf64378 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_key_preload.c @@ -0,0 +1,102 @@ +// 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@xxxxxxxxxx> + * Roberto Sassu <roberto.sassu@xxxxxxxxxx> + * + * Load user asymmetric keys from a keyring blob. + */ + +#define pr_fmt(fmt) "UASYM PRELOAD: "fmt +#include <linux/module.h> +#include <linux/key.h> +#include <linux/err.h> +#include <linux/tlv_parser.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; + u64 data_type; + u64 num_fields; + u64 total_len; + int ret; + + kenter(""); + + while (data_ptr < data_end) { + ret = tlv_parse_hdr(&data_ptr, &data_len, &data_type, + &num_fields, &total_len, data_types_str, + TYPE__LAST); + 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 tlv_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 ac5bce6d081..a227d6d082e 100644 --- a/include/crypto/uasym_keys_sigs.h +++ b/include/crypto/uasym_keys_sigs.h @@ -29,6 +29,9 @@ int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, const u8 **buf, int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, struct key *keyring); 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) @@ -68,5 +71,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 */ -- 2.34.1