From eb92ab48517ba4c6a793e8c9cecf6d6c027cd664 Mon Sep 17 00:00:00 2001 From: Greg V Date: Thu, 27 Jun 2019 17:39:22 +0300 Subject: [PATCH] loader: Add support for getting early entropy from the UEFI RNG protocol This is most useful on architectures like aarch64 that don't yet have a HW RNG instruction that's as ubiquitous as AES-NI is on amd64. Differential Revision: https://reviews.freebsd.org/D20780 --- stand/defaults/loader.conf | 4 ++- stand/efi/include/efirng.h | 50 ++++++++++++++++++++++++++++++++ stand/efi/loader/main.c | 42 +++++++++++++++++++++++++++ stand/lua/core.lua | 10 +++++++ sys/dev/random/random_harvestq.c | 8 +++++ sys/sys/random.h | 1 + 6 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 stand/efi/include/efirng.h diff --git a/stand/defaults/loader.conf b/stand/defaults/loader.conf index 6feb909d708..24a47e75c39 100644 --- a/stand/defaults/loader.conf +++ b/stand/defaults/loader.conf @@ -42,12 +42,14 @@ hostuuid_type="hostuuid" # See rc.conf(5). The entropy_boot_file config variable must agree with the # settings below. entropy_cache_load="YES" # Set this to NO to disable loading - # entropy at boot time + # cached entropy at boot time entropy_cache_name="/boot/entropy" # Set this to the name of the file entropy_cache_type="boot_entropy_cache" # Required for the kernel to find # the boot-time entropy cache. This # must not change value even if the # _name above does change! +entropy_efi_seed="YES" # Set this to NO to disable loading + # entropy from the UEFI hardware random number generator API ### RAM Blacklist configuration ############################ ram_blacklist_load="NO" # Set this to YES to load a file diff --git a/stand/efi/include/efirng.h b/stand/efi/include/efirng.h new file mode 100644 index 00000000000..3d6c7767798 --- /dev/null +++ b/stand/efi/include/efirng.h @@ -0,0 +1,50 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2006 - 2016 Unified EFI, Inc.
+ * Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + */ + +#ifndef _EFIRNG_H +#define _EFIRNG_H + +#define EFI_RNG_PROTOCOL_GUID \ + { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44} } + +INTERFACE_DECL(_EFI_RNG_PROTOCOL); + +typedef EFI_GUID EFI_RNG_ALGORITHM; + +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_INFO) ( + IN struct _EFI_RNG_PROTOCOL *This, + IN OUT UINTN *RNGAlgorithmListSize, + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_RNG) ( + IN struct _EFI_RNG_PROTOCOL *This, + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue + ); + +typedef struct _EFI_RNG_PROTOCOL { + EFI_RNG_GET_INFO GetInfo; + EFI_RNG_GET_RNG GetRNG; +} EFI_RNG_PROTOCOL; + +static EFI_GUID rng_guid = EFI_RNG_PROTOCOL_GUID; + +#endif /* _EFIRNG_H */ diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index 7b78f94eb36..eb143989190 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -1204,6 +1205,47 @@ main(int argc, CHAR16 *argv[]) return (EFI_SUCCESS); /* keep compiler happy */ } +COMMAND_SET(efi_seed_entropy, "efi-seed-entropy", "try to get entropy from the EFI RNG", command_seed_entropy); + +static int +command_seed_entropy(int argc, char *argv[]) +{ + EFI_STATUS status; + EFI_RNG_PROTOCOL *rng; + unsigned int size = 2048; + void *buf; + + if (argc > 1) { + size = strtol(argv[1], NULL, 0); + } + + status = BS->LocateProtocol(&rng_guid, NULL, (VOID **)&rng); + if (status != EFI_SUCCESS) { + command_errmsg = "RNG protocol not found"; + return (CMD_ERROR); + } + + if ((buf = malloc(size)) == NULL) { + command_errmsg = "out of memory"; + return (CMD_ERROR); + } + + status = rng->GetRNG(rng, NULL, size, (UINT8 *)buf); + if (status != EFI_SUCCESS) { + free(buf); + command_errmsg = "GetRNG failed"; + return (CMD_ERROR); + } + + if (file_addbuf("efi_rng_seed", "boot_entropy_platform", size, buf) != 0) { + free(buf); + return (CMD_ERROR); + } + + free(buf); + return (CMD_OK); +} + COMMAND_SET(poweroff, "poweroff", "power off the system", command_poweroff); static int diff --git a/stand/lua/core.lua b/stand/lua/core.lua index 67d51b99285..27e3c14de9f 100644 --- a/stand/lua/core.lua +++ b/stand/lua/core.lua @@ -351,6 +351,14 @@ function core.changeRewindCheckpoint() end end +function core.loadEntropy() + if core.isUEFIBoot() then + if (loader.getenv("entropy_efi_seed") or "no"):lower() == "yes" then + loader.perform("efi-seed-entropy") + end + end +end + function core.setDefaults() core.setACPI(core.getACPIPresent(true)) core.setSafeMode(default_safe_mode) @@ -363,6 +371,7 @@ function core.autoboot(argstr) if loader.getenv("kernelname") == nil then config.loadelf() end + core.loadEntropy() loader.perform(composeLoaderCmd("autoboot", argstr)) end @@ -371,6 +380,7 @@ function core.boot(argstr) if loader.getenv("kernelname") == nil then config.loadelf() end + core.loadEntropy() loader.perform(composeLoaderCmd("boot", argstr)) end diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c index 46c06912694..e868c1fe3c5 100644 --- a/sys/dev/random/random_harvestq.c +++ b/sys/dev/random/random_harvestq.c @@ -487,6 +487,14 @@ random_harvestq_prime(void *unused __unused) else printf("random: no preloaded entropy cache\n"); } + size = random_prime_loader_file(RANDOM_PLATFORM_BOOT_ENTROPY_MODULE); + if (bootverbose) { + if (size > 0) + printf("random: read %zu bytes from platform bootloader\n", + size); + else + printf("random: no platform bootloader entropy\n"); + } } SYSINIT(random_device_prime, SI_SUB_RANDOM, SI_ORDER_MIDDLE, random_harvestq_prime, NULL); diff --git a/sys/sys/random.h b/sys/sys/random.h index cfcf4b30e69..02cb409cd99 100644 --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -109,6 +109,7 @@ _Static_assert(ENTROPYSOURCE <= 32, "hardcoded assumption that values fit in a typical word-sized bitset"); #define RANDOM_CACHED_BOOT_ENTROPY_MODULE "boot_entropy_cache" +#define RANDOM_PLATFORM_BOOT_ENTROPY_MODULE "boot_entropy_platform" extern u_int hc_source_mask; void random_harvest_queue_(const void *, u_int, enum random_entropy_source); -- 2.30.0