From patchwork Wed Nov 16 16:16:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 625239 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8109CC4167E for ; Wed, 16 Nov 2022 16:17:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234309AbiKPQRW (ORCPT ); Wed, 16 Nov 2022 11:17:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234848AbiKPQRE (ORCPT ); Wed, 16 Nov 2022 11:17:04 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9DAD057B4F; Wed, 16 Nov 2022 08:17:02 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 507A5B81DD9; Wed, 16 Nov 2022 16:17:01 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 59EDDC433C1; Wed, 16 Nov 2022 16:16:59 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="mHUvawIZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1668615418; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=W1wAtKaY05W2lIvCkJNGSoOGC/DQ2aQIlUV6cSqpewY=; b=mHUvawIZManIDNWJYkDAZ1LyUU64eJuoithPe85vkWTE8glRz2J/80l6AjIgn+rpBYe/dW VOFfazhVy5argg5xGDFuAYRISePB5qvxVEFpQgS5cmA6mwErH/Jp9kSSlhm8WpsZv8GEC7 jesrA94tBbgHa+1qpqrzQ0zEQElW6DM= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id b05e0581 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Wed, 16 Nov 2022 16:16:57 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-efi@vger.kernel.org, linux-crypto@vger.kernel.org Cc: "Jason A. Donenfeld" , Ard Biesheuvel , Lennart Poettering Subject: [PATCH RFC v1 1/6] random: add back async readiness notifier Date: Wed, 16 Nov 2022 17:16:37 +0100 Message-Id: <20221116161642.1670235-2-Jason@zx2c4.com> In-Reply-To: <20221116161642.1670235-1-Jason@zx2c4.com> References: <20221116161642.1670235-1-Jason@zx2c4.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org This is required by vsprint, because it can't do things synchronously from hardirq context, and it will be useful for an EFI notifier as well. Signed-off-by: Jason A. Donenfeld --- drivers/char/random.c | 30 ++++++++++++++++++++++++++++++ include/linux/random.h | 1 + 2 files changed, 31 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index 6b7aca683b81..b3cad16ec567 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -84,6 +84,8 @@ static DEFINE_STATIC_KEY_FALSE(crng_is_ready); /* Various types of waiters for crng_init->CRNG_READY transition. */ static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait); static struct fasync_struct *fasync; +static DEFINE_SPINLOCK(random_ready_chain_lock); +static RAW_NOTIFIER_HEAD(random_ready_chain); /* Control how we warn userspace. */ static struct ratelimit_state urandom_warning = @@ -140,6 +142,33 @@ int wait_for_random_bytes(void) } EXPORT_SYMBOL(wait_for_random_bytes); +/* + * Add a callback function that will be invoked when the crng is initialised, + * or immediately if it already has been. + */ +int __cold notify_on_rng_initialized(struct notifier_block *nb) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&random_ready_chain_lock, flags); + if (crng_ready()) + nb->notifier_call(nb, 0, NULL); + else + ret = raw_notifier_chain_register(&random_ready_chain, nb); + spin_unlock_irqrestore(&random_ready_chain_lock, flags); + return ret; +} + +static void __cold process_random_ready_list(void) +{ + unsigned long flags; + + spin_lock_irqsave(&random_ready_chain_lock, flags); + raw_notifier_call_chain(&random_ready_chain, 0, NULL); + spin_unlock_irqrestore(&random_ready_chain_lock, flags); +} + #define warn_unseeded_randomness() \ if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \ printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \ @@ -685,6 +714,7 @@ static void __cold _credit_init_bits(size_t bits) crng_reseed(); /* Sets crng_init to CRNG_READY under base_crng.lock. */ if (static_key_initialized) execute_in_process_context(crng_set_ready, &set_ready); + process_random_ready_list(); wake_up_interruptible(&crng_init_wait); kill_fasync(&fasync, SIGIO, POLL_IN); pr_notice("crng init done\n"); diff --git a/include/linux/random.h b/include/linux/random.h index acaa328fb34d..566ffc3ab80d 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -119,6 +119,7 @@ void __init random_init_early(const char *command_line); void __init random_init(void); bool rng_is_initialized(void); int wait_for_random_bytes(void); +int notify_on_rng_initialized(struct notifier_block *nb); /* Calls wait_for_random_bytes() and then calls get_random_bytes(buf, nbytes). * Returns the result of the call to wait_for_random_bytes. */ From patchwork Wed Nov 16 16:16:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 625830 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16D29C43219 for ; Wed, 16 Nov 2022 16:17:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233296AbiKPQRU (ORCPT ); Wed, 16 Nov 2022 11:17:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54140 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234897AbiKPQRH (ORCPT ); Wed, 16 Nov 2022 11:17:07 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B5DD156EDD; Wed, 16 Nov 2022 08:17:06 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 7550DB81DA7; Wed, 16 Nov 2022 16:17:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4B540C433C1; Wed, 16 Nov 2022 16:17:03 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="BnW7RkGC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1668615421; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=v24y1wfuWLq5Cu92sfEtPK6DD/spL3fwX1JCpyFIa2M=; b=BnW7RkGC9Fcq2ZG1RT/d/CIyFvNnzxI+y3tkfmX8qqtcxb7VHTah3KU6Df9TGBZnCjZL2h 0CUAvsVt5vYzI7yOSV8tJkqq+2g8cFt4djJoqXUmtnOVb/wACoUWpyZt3MGKLIMK91kcRG YJqSKfBTQd6IdUnDbhvx9XW3ApqlwBA= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id fb4bb795 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Wed, 16 Nov 2022 16:17:01 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-efi@vger.kernel.org, linux-crypto@vger.kernel.org Cc: "Jason A. Donenfeld" , Ard Biesheuvel , Lennart Poettering , Mike Galbraith , Sebastian Andrzej Siewior , Petr Mladek Subject: [PATCH RFC v1 2/6] vsprintf: initialize siphash key using notifier Date: Wed, 16 Nov 2022 17:16:38 +0100 Message-Id: <20221116161642.1670235-3-Jason@zx2c4.com> In-Reply-To: <20221116161642.1670235-1-Jason@zx2c4.com> References: <20221116161642.1670235-1-Jason@zx2c4.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org Rather than polling every second, use the new notifier to do this at exactly the right moment. Cc: Mike Galbraith Cc: Sebastian Andrzej Siewior Cc: Petr Mladek Signed-off-by: Jason A. Donenfeld Reviewed-by: Petr Mladek --- lib/vsprintf.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 24f37bab8bc1..70aa5de3c330 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef CONFIG_BLOCK #include #endif @@ -752,26 +753,21 @@ early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable); static bool filled_random_ptr_key __read_mostly; static siphash_key_t ptr_key __read_mostly; -static void fill_ptr_key_workfn(struct work_struct *work); -static DECLARE_DELAYED_WORK(fill_ptr_key_work, fill_ptr_key_workfn); -static void fill_ptr_key_workfn(struct work_struct *work) +static int fill_ptr_key(struct notifier_block *nb, unsigned long action, void *data) { - if (!rng_is_initialized()) { - queue_delayed_work(system_unbound_wq, &fill_ptr_key_work, HZ * 2); - return; - } - get_random_bytes(&ptr_key, sizeof(ptr_key)); /* Pairs with smp_rmb() before reading ptr_key. */ smp_wmb(); WRITE_ONCE(filled_random_ptr_key, true); + return 0; } static int __init vsprintf_init_hashval(void) { - fill_ptr_key_workfn(NULL); + static struct notifier_block fill_ptr_key_nb = { .notifier_call = fill_ptr_key }; + notify_on_rng_initialized(&fill_ptr_key_nb); return 0; } subsys_initcall(vsprintf_init_hashval) From patchwork Wed Nov 16 16:16:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 625238 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BB438C433FE for ; Wed, 16 Nov 2022 16:17:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234332AbiKPQRY (ORCPT ); Wed, 16 Nov 2022 11:17:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54072 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237236AbiKPQRK (ORCPT ); Wed, 16 Nov 2022 11:17:10 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C20557B4D; Wed, 16 Nov 2022 08:17:09 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id BFDCC61EA1; Wed, 16 Nov 2022 16:17:08 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 73977C433D6; Wed, 16 Nov 2022 16:17:07 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="RZkhCM0L" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1668615426; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4Od8YDuyhTgJbG1EHETqselbA6gas5EfTyFqSv7a58c=; b=RZkhCM0LogyN/TTzBoOeDcubZ2FyU42L9I2wf/KfPVfXXeziJVtBAd+C4lGS7zjWNkqPEj v90PJadTJOz05uzqEVs6qjZkK02uDErWGQqTYmYtiV1PXHcqMl6AAsSpIxsb4920Hh/wnN khRVqHmjJV1h0y6qFo1sNrLZIM9ZhvY= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id 2f137fb2 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Wed, 16 Nov 2022 16:17:05 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-efi@vger.kernel.org, linux-crypto@vger.kernel.org Cc: "Jason A. Donenfeld" , Ard Biesheuvel , Lennart Poettering Subject: [PATCH RFC v1 3/6] efi: random: combine bootloader provided RNG seed with RNG protocol output Date: Wed, 16 Nov 2022 17:16:39 +0100 Message-Id: <20221116161642.1670235-4-Jason@zx2c4.com> In-Reply-To: <20221116161642.1670235-1-Jason@zx2c4.com> References: <20221116161642.1670235-1-Jason@zx2c4.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org From: Ard Biesheuvel Instead of blindly creating the EFI random seed configuration table if the RNG protocol is implemented and works, check whether such a EFI configuration table was provided by an earlier boot stage and if so, concatenate the existing and the new seeds, leaving it up to the core code to mix it in and credit it the way it sees fit. This can be used for, e.g., systemd-boot, to pass an additional seed to Linux in a way that can be consumed by the kernel very early. In that case, the following definitions should be used to pass the seed to the EFI stub: struct linux_efi_random_seed { u32 size; // of the 'seed' array in bytes u8 seed[]; }; The memory for the struct must be allocated as EFI_ACPI_RECLAIM_MEMORY pool memory, and the address of the struct in memory should be installed as a EFI configuration table using the following GUID: LINUX_EFI_RANDOM_SEED_TABLE_GUID 1ce1e5bc-7ceb-42f2-81e5-8aadf180f57b Note that doing so is safe even on kernels that were built without this patch applied, but the seed will simply be overwritten with a seed derived from the EFI RNG protocol, if available. The recommended seed size is 32 bytes, and seeds larger than 512 bytes are considered corrupted and ignored entirely. In order to preserve forward secrecy, seeds from previous bootloaders are memzero'd out, and in order to preserve memory, those older seeds are also freed from memory. Freeing from memory without first memzeroing is not safe to do, as it's possible that nothing else will ever overwrite those pages used by EFI. Signed-off-by: Ard Biesheuvel Reviewed-by: Jason A. Donenfeld Signed-off-by: Jason A. Donenfeld --- drivers/firmware/efi/libstub/efistub.h | 2 ++ drivers/firmware/efi/libstub/random.c | 42 ++++++++++++++++++++++---- include/linux/efi.h | 2 -- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index eb03d5a9aac8..900df67a2078 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -882,6 +882,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); efi_status_t efi_random_alloc(unsigned long size, unsigned long align, unsigned long *addr, unsigned long random_seed); +efi_status_t efi_random_get_seed(void); + efi_status_t check_platform_features(void); void *get_efi_config_table(efi_guid_t guid); diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c index 33ab56769595..f85d2c066877 100644 --- a/drivers/firmware/efi/libstub/random.c +++ b/drivers/firmware/efi/libstub/random.c @@ -67,27 +67,43 @@ efi_status_t efi_random_get_seed(void) efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID; efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW; efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID; + struct linux_efi_random_seed *prev_seed, *seed = NULL; + int prev_seed_size = 0, seed_size = EFI_RANDOM_SEED_SIZE; efi_rng_protocol_t *rng = NULL; - struct linux_efi_random_seed *seed = NULL; efi_status_t status; status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng); if (status != EFI_SUCCESS) return status; + /* + * Check whether a seed was provided by a prior boot stage. In that + * case, instead of overwriting it, let's create a new buffer that can + * hold both, and concatenate the existing and the new seeds. + * Note that we should read the seed size with caution, in case the + * table got corrupted in memory somehow. + */ + prev_seed = get_efi_config_table(LINUX_EFI_RANDOM_SEED_TABLE_GUID); + if (prev_seed && prev_seed->size <= 512U) { + prev_seed_size = prev_seed->size; + seed_size += prev_seed_size; + } + /* * Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the * allocation will survive a kexec reboot (although we refresh the seed * beforehand) */ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, - sizeof(*seed) + EFI_RANDOM_SEED_SIZE, + struct_size(seed, bits, seed_size), (void **)&seed); - if (status != EFI_SUCCESS) - return status; + if (status != EFI_SUCCESS) { + efi_warn("Failed to allocate memory for RNG seed.\n"); + goto err_warn; + } status = efi_call_proto(rng, get_rng, &rng_algo_raw, - EFI_RANDOM_SEED_SIZE, seed->bits); + EFI_RANDOM_SEED_SIZE, seed->bits); if (status == EFI_UNSUPPORTED) /* @@ -100,14 +116,28 @@ efi_status_t efi_random_get_seed(void) if (status != EFI_SUCCESS) goto err_freepool; - seed->size = EFI_RANDOM_SEED_SIZE; + seed->size = seed_size; + if (prev_seed_size) + memcpy(seed->bits + EFI_RANDOM_SEED_SIZE, prev_seed->bits, + prev_seed_size); + status = efi_bs_call(install_configuration_table, &rng_table_guid, seed); if (status != EFI_SUCCESS) goto err_freepool; + if (prev_seed_size) { + /* wipe and free the old seed if we managed to install the new one */ + memzero_explicit(prev_seed->bits, prev_seed_size); + efi_bs_call(free_pool, prev_seed); + } return EFI_SUCCESS; err_freepool: + memzero_explicit(seed, struct_size(seed, bits, seed_size)); efi_bs_call(free_pool, seed); + efi_warn("Failed to obtain seed from EFI_RNG_PROTOCOL\n"); +err_warn: + if (prev_seed) + efi_warn("Retaining bootloader-supplied seed only"); return status; } diff --git a/include/linux/efi.h b/include/linux/efi.h index 7603fc58c47c..4aa1dbc7b064 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1170,8 +1170,6 @@ void efi_check_for_embedded_firmwares(void); static inline void efi_check_for_embedded_firmwares(void) { } #endif -efi_status_t efi_random_get_seed(void); - #define arch_efi_call_virt(p, f, args...) ((p)->f(args)) /* From patchwork Wed Nov 16 16:16:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 625829 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E3AF0C433FE for ; Wed, 16 Nov 2022 16:17:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233608AbiKPQRU (ORCPT ); Wed, 16 Nov 2022 11:17:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237798AbiKPQRM (ORCPT ); Wed, 16 Nov 2022 11:17:12 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 188F556ED6; Wed, 16 Nov 2022 08:17:12 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id AC68161EA1; Wed, 16 Nov 2022 16:17:11 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71899C433D6; Wed, 16 Nov 2022 16:17:10 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="LMtT5g0j" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1668615429; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CtDPiLK4h3/qHxrwQ4LOLbCxpSziESOZ1KCyGGtwumM=; b=LMtT5g0jbC2n+YnsJpCMOismh75conFLfg9ZfXbF3B4K+4Cdpx+P3xEycUSpeDoIb3L1+f PaDeZDIuBn2qmyEaYUzK/TP6VWZuLGyCGF46Q8ZJABCXgPm0ZeLbYiPAceevFmxQGaICQP 80fKEVsVLBK/swJSk1z8LnuUnUIGcw0= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id 99e58ae7 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Wed, 16 Nov 2022 16:17:09 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-efi@vger.kernel.org, linux-crypto@vger.kernel.org Cc: "Jason A. Donenfeld" , Ard Biesheuvel , Lennart Poettering Subject: [PATCH RFC v1 4/6] efi: stub: use random seed from EFI variable Date: Wed, 16 Nov 2022 17:16:40 +0100 Message-Id: <20221116161642.1670235-5-Jason@zx2c4.com> In-Reply-To: <20221116161642.1670235-1-Jason@zx2c4.com> References: <20221116161642.1670235-1-Jason@zx2c4.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org Since we have some storage, we can manage non-volatile seeds directly from EFISTUB. This commit passes the contents of an EFI variable to the kernel via the existing configuration table. Signed-off-by: Jason A. Donenfeld --- drivers/firmware/efi/libstub/random.c | 59 +++++++++++++++++++++------ include/linux/efi.h | 1 + 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c index f85d2c066877..1e72013a6457 100644 --- a/drivers/firmware/efi/libstub/random.c +++ b/drivers/firmware/efi/libstub/random.c @@ -67,14 +67,25 @@ efi_status_t efi_random_get_seed(void) efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID; efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW; efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID; + efi_char16_t rng_nv_seed_var[] = LINUX_EFI_RANDOM_NV_SEED_VAR; struct linux_efi_random_seed *prev_seed, *seed = NULL; - int prev_seed_size = 0, seed_size = EFI_RANDOM_SEED_SIZE; + u8 nv_seed[EFI_RANDOM_SEED_SIZE]; + unsigned long prev_seed_size = 0, nv_seed_size = sizeof(nv_seed), seed_size = 0, offset = 0; efi_rng_protocol_t *rng = NULL; efi_status_t status; status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng); - if (status != EFI_SUCCESS) - return status; + if (status == EFI_SUCCESS) + seed_size += EFI_RANDOM_SEED_SIZE; + + status = get_efi_var(rng_nv_seed_var, &rng_table_guid, NULL, &nv_seed_size, nv_seed); + if (status == EFI_SUCCESS) + seed_size += nv_seed_size; + else + nv_seed_size = 0; + + if (!seed_size) + return EFI_NOT_FOUND; /* * Check whether a seed was provided by a prior boot stage. In that @@ -83,7 +94,7 @@ efi_status_t efi_random_get_seed(void) * Note that we should read the seed size with caution, in case the * table got corrupted in memory somehow. */ - prev_seed = get_efi_config_table(LINUX_EFI_RANDOM_SEED_TABLE_GUID); + prev_seed = get_efi_config_table(rng_table_guid); if (prev_seed && prev_seed->size <= 512U) { prev_seed_size = prev_seed->size; seed_size += prev_seed_size; @@ -103,7 +114,7 @@ efi_status_t efi_random_get_seed(void) } status = efi_call_proto(rng, get_rng, &rng_algo_raw, - EFI_RANDOM_SEED_SIZE, seed->bits); + EFI_RANDOM_SEED_SIZE, seed->bits + offset); if (status == EFI_UNSUPPORTED) /* @@ -111,16 +122,40 @@ efi_status_t efi_random_get_seed(void) * is not implemented. */ status = efi_call_proto(rng, get_rng, NULL, - EFI_RANDOM_SEED_SIZE, seed->bits); + EFI_RANDOM_SEED_SIZE, seed->bits + offset); - if (status != EFI_SUCCESS) + if (status == EFI_SUCCESS) + offset += EFI_RANDOM_SEED_SIZE; + + if (nv_seed_size) { + memcpy(seed->bits + offset, nv_seed, nv_seed_size); + memzero_explicit(nv_seed, nv_seed_size); + /* + * Zero it out before committing to using it. TODO: in the + * future, maybe we can hash it forward instead, which is + * better and also reduces the amount of writes here. + */ + status = set_efi_var(rng_nv_seed_var, &rng_table_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, nv_seed_size, nv_seed); + if (status == EFI_SUCCESS) + status = set_efi_var(rng_nv_seed_var, &rng_table_guid, 0, 0, NULL); + if (status == EFI_SUCCESS) + offset += nv_seed_size; + else + memzero_explicit(seed->bits + offset, nv_seed_size); + } + + if (!offset) goto err_freepool; - seed->size = seed_size; - if (prev_seed_size) - memcpy(seed->bits + EFI_RANDOM_SEED_SIZE, prev_seed->bits, - prev_seed_size); + if (prev_seed_size) { + memcpy(seed->bits + offset, prev_seed->bits, prev_seed_size); + offset += prev_seed_size; + } + seed->size = offset; status = efi_bs_call(install_configuration_table, &rng_table_guid, seed); if (status != EFI_SUCCESS) goto err_freepool; @@ -135,7 +170,7 @@ efi_status_t efi_random_get_seed(void) err_freepool: memzero_explicit(seed, struct_size(seed, bits, seed_size)); efi_bs_call(free_pool, seed); - efi_warn("Failed to obtain seed from EFI_RNG_PROTOCOL\n"); + efi_warn("Failed to obtain seed from EFI_RNG_PROTOCOL and EFI variable\n"); err_warn: if (prev_seed) efi_warn("Retaining bootloader-supplied seed only"); diff --git a/include/linux/efi.h b/include/linux/efi.h index 4aa1dbc7b064..0e93510b23b5 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -408,6 +408,7 @@ void efi_native_runtime_setup(void); #define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989, 0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2) #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) #define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b) +#define LINUX_EFI_RANDOM_NV_SEED_VAR L"RandomNVSeed" #define LINUX_EFI_TPM_EVENT_LOG_GUID EFI_GUID(0xb7799cb0, 0xeca2, 0x4943, 0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa) #define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) From patchwork Wed Nov 16 16:16:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 625240 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BE1AC4167D for ; Wed, 16 Nov 2022 16:17:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234223AbiKPQRV (ORCPT ); Wed, 16 Nov 2022 11:17:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54268 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238085AbiKPQRR (ORCPT ); Wed, 16 Nov 2022 11:17:17 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8514BD135; Wed, 16 Nov 2022 08:17:16 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 42997B81DD9; Wed, 16 Nov 2022 16:17:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5CD32C433D6; Wed, 16 Nov 2022 16:17:13 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="DO7/xtKp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1668615433; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SutN9URRaDRkoRI4sfbAAJPIQ0pLYtrJHZUE/tUAx5Q=; b=DO7/xtKpmJ+qbHUkvjOiJl95LOYlJrLNXrCH1BXJ5r/WuFITUd9HEjZ/RqdSLzoGooTmYc gfHssY9a8mQGQCUu90xJOpKx3QeILTHlt5an1KxtzQ2WBAcZ4bsfucAykgwEOaq44uGweW bOC9xpFA89pnO1UW3k8kh5xasxnPH/E= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id 8e977426 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Wed, 16 Nov 2022 16:17:12 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-efi@vger.kernel.org, linux-crypto@vger.kernel.org Cc: "Jason A. Donenfeld" , Ard Biesheuvel , Lennart Poettering Subject: [PATCH RFC v1 5/6] efi: efivarfs: prohibit reading random seed variables Date: Wed, 16 Nov 2022 17:16:41 +0100 Message-Id: <20221116161642.1670235-6-Jason@zx2c4.com> In-Reply-To: <20221116161642.1670235-1-Jason@zx2c4.com> References: <20221116161642.1670235-1-Jason@zx2c4.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org Variables in the random seed GUID must remain secret, so deny all reads to them. Signed-off-by: Jason A. Donenfeld --- fs/efivarfs/file.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c index d57ee15874f9..08996ba3a373 100644 --- a/fs/efivarfs/file.c +++ b/fs/efivarfs/file.c @@ -76,6 +76,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, while (!__ratelimit(&file->f_cred->user->ratelimit)) msleep(50); + if (guid_equal(&var->var.VendorGuid, &LINUX_EFI_RANDOM_SEED_TABLE_GUID)) + return -EPERM; + err = efivar_entry_size(var, &datasize); /* From patchwork Wed Nov 16 16:16:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 625827 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CAC49C43219 for ; Wed, 16 Nov 2022 16:17:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233896AbiKPQRZ (ORCPT ); Wed, 16 Nov 2022 11:17:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54324 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232506AbiKPQRT (ORCPT ); Wed, 16 Nov 2022 11:17:19 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6C1257B4A; Wed, 16 Nov 2022 08:17:18 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5D66761EA1; Wed, 16 Nov 2022 16:17:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 380C4C433C1; Wed, 16 Nov 2022 16:17:17 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="gP8ZSBvF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1668615436; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=T8rpk19kPkTtPMi5LUcmORLt2HUDUjWWv1DWoYLEx0I=; b=gP8ZSBvFYttV9FkdX6gi6A9SgRb4YQWPgyka74GC2aO+WXfMXjyb8bfOjzxLhH8q1nNS8p u0qnicPF58AhsnY8+ODg1ml+iE0X15khp7H6L4Ko6TuBx1+bDiXW8urDyukGhGAK+Bdc/a Y6w76zi4j/dcPbLRZd8EnDy3EyjWw9Q= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id 2e2b34f2 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Wed, 16 Nov 2022 16:17:15 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-efi@vger.kernel.org, linux-crypto@vger.kernel.org Cc: "Jason A. Donenfeld" , Ard Biesheuvel , Lennart Poettering Subject: [PATCH RFC v1 6/6] efi: refresh non-volatile random seed when RNG is initialized Date: Wed, 16 Nov 2022 17:16:42 +0100 Message-Id: <20221116161642.1670235-7-Jason@zx2c4.com> In-Reply-To: <20221116161642.1670235-1-Jason@zx2c4.com> References: <20221116161642.1670235-1-Jason@zx2c4.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org Register a notifier so that when the RNG is initialized, the EFI variable containing the random seed can be refreshed. Signed-off-by: Jason A. Donenfeld --- drivers/firmware/efi/efi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index a46df5d1d094..db247a52d3c2 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -337,6 +337,19 @@ static void __init efi_debugfs_init(void) static inline void efi_debugfs_init(void) {} #endif +static int refresh_nv_rng_seed(struct notifier_block *nb, unsigned long action, void *data) +{ + u8 seed[EFI_RANDOM_SEED_SIZE]; + + get_random_bytes(seed, sizeof(seed)); + efi.set_variable(LINUX_EFI_RANDOM_NV_SEED_VAR, &LINUX_EFI_RANDOM_SEED_TABLE_GUID, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, sizeof(seed), seed); + memzero_explicit(seed, sizeof(seed)); + return 0; +} +static struct notifier_block refresh_nv_rng_seed_nb = { .notifier_call = refresh_nv_rng_seed }; + /* * We register the efi subsystem with the firmware subsystem and the * efivars subsystem with the efi subsystem, if the system was booted with @@ -413,6 +426,7 @@ static int __init efisubsys_init(void) platform_device_register_simple("efi_secret", 0, NULL, 0); #endif + notify_on_rng_initialized(&refresh_nv_rng_seed_nb); return 0; err_remove_group: