diff --git a/stand/defaults/loader.conf b/stand/defaults/loader.conf
index 6feb909d708a..24a47e75c39a 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 000000000000..3d6c77677981
--- /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 7b78f94eb368..eb143989190d 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 67d51b992858..27e3c14de9ff 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 aae8ec9172d7..6d3e9534e15b 100644
--- a/sys/dev/random/random_harvestq.c
+++ b/sys/dev/random/random_harvestq.c
@@ -488,6 +488,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 6f4f90c9de98..81d2a40c72dd 100644
--- a/sys/sys/random.h
+++ b/sys/sys/random.h
@@ -110,6 +110,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);