Add a crypto module loader mechanism that loads a precompiled crypto kernel module that is embedded in vmlinux image directly from memory (whose address stored in _binary_fips140_ko_start/end) during early boot.
This is built based on Vegard Nossum <[email protected]> and Saeed Mirzamohammadi <[email protected]>, the fips_loader_init is picked up. But different from them, such loader is not executed as arch_initcall_sync(), but rather as a thread along main kernel init to ensure proper initialization sequencing (Details are in later patch). Signed-off-by: Jay Wang <[email protected]> --- crypto/fips140/fips140-loader.c | 55 +++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 crypto/fips140/fips140-loader.c diff --git a/crypto/fips140/fips140-loader.c b/crypto/fips140/fips140-loader.c new file mode 100644 index 000000000000..cbf5ff59eb2e --- /dev/null +++ b/crypto/fips140/fips140-loader.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FIPS 140 Early Loader + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/printk.h> +#include <linux/vmalloc.h> +#include <linux/string.h> +#include <linux/elf.h> +#include <linux/kthread.h> +#include <linux/wait.h> + +extern const u8 _binary_fips140_ko_start[]; +extern const u8 _binary_fips140_ko_end[]; +const u8 *_binary_crypto_ko_start; +EXPORT_SYMBOL_GPL(_binary_crypto_ko_start); +const u8 *_binary_crypto_ko_end; +EXPORT_SYMBOL_GPL(_binary_crypto_ko_end); + +/* Function to load crypto module from memory */ +extern int load_crypto_module_mem(const char *mem, size_t size); + +static void load_prepare(void) +{ + _binary_crypto_ko_start = _binary_fips140_ko_start; + _binary_crypto_ko_end = _binary_fips140_ko_end; +} + +static int __init fips_loader_init(void) +{ + load_prepare(); + + const void *ko_mem = _binary_crypto_ko_start; + size_t ko_size = _binary_crypto_ko_end - _binary_crypto_ko_start; + void *vmalloc_mem; + int ret; + + // Copy to vmalloc'd memory since load_module expects to free it + vmalloc_mem = vmalloc(ko_size); + if (!vmalloc_mem) { + pr_err("FIPS140 loader: failed to allocate memory\n"); + return -ENOMEM; + } + + memcpy(vmalloc_mem, ko_mem, ko_size); + + ret = load_crypto_module_mem(vmalloc_mem, ko_size); // Skip signature check + if (ret) + panic("FIPS140 loader: module loading error\n"); + + vfree(vmalloc_mem); // Free after successful module loading + return ret; +} -- 2.47.3
