Page MenuHomeFreeBSD
Paste P536

D20780 format-patch
ActivePublic

Authored by greg_unrelenting.technology on Jan 28 2022, 11:56 AM.
From eb92ab48517ba4c6a793e8c9cecf6d6c027cd664 Mon Sep 17 00:00:00 2001
From: Greg V <greg@unrelenting.technology>
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.<BR>
+ * Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+ * 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 <efi.h>
#include <efilib.h>
#include <efichar.h>
+#include <efirng.h>
#include <uuid.h>
@@ -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