]> xenbits.xensource.com Git - people/royger/freebsd.git/commitdiff
Add support for getting early entropy from UEFI
authorColin Percival <cperciva@FreeBSD.org>
Thu, 17 Feb 2022 21:01:11 +0000 (13:01 -0800)
committerColin Percival <cperciva@FreeBSD.org>
Mon, 14 Mar 2022 21:26:33 +0000 (14:26 -0700)
UEFI provides a protocol for accessing randomness. This is a good way
to gather early entropy, especially when there's no driver for the RNG
on the platform (as is the case on the Marvell Armada8k (MACCHIATObin)
for now).

If the entropy_efi_seed option is enabled in loader.conf (default: YES)
obtain 2048 bytes of entropy from UEFI and pass is to the kernel as a
"module" of name "efi_rng_seed" and type "boot_entropy_platform"; if
present, ingest it into the kernel RNG.

Submitted by: Greg V
Reviewed by: markm, kevans
Approved by: csprng (markm), re (delphij)
Differential Revision: https://reviews.freebsd.org/D20780

stand/defaults/loader.conf
stand/efi/include/efirng.h [new file with mode: 0644]
stand/efi/loader/main.c
stand/lua/core.lua
sys/dev/random/random_harvestq.c
sys/sys/random.h

index 6feb909d708a21e944ce65afdcf5cf3e1c7fa68b..24a47e75c39a05a53014931ec6c05d4c6aacfe9b 100644 (file)
@@ -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 (file)
index 0000000..3d6c776
--- /dev/null
@@ -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 */
index ee55366e0c4425607bdf383b07084cad9e411c70..7752751efd0bac9a45ed2419d796106043bcb117 100644 (file)
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 #include <efi.h>
 #include <efilib.h>
 #include <efichar.h>
+#include <efirng.h>
 
 #include <uuid.h>
 
@@ -1180,6 +1181,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
index 67d51b992858a47d6b52b8b6c8711d948accfdb1..27e3c14de9ff27be0204aaf26e40c59f9cf23f41 100644 (file)
@@ -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
 
index 563ff73a3d38431d68d9975de3a8f00a1fb7bb81..ff5d6f70f8a0f4a12f3877e7f420069a4ae0a983 100644 (file)
@@ -494,6 +494,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);
 
index e2c4ab144d2a2577175feb30e15b452e866b3c65..2786cfad4b8fb4fb79357b20c6750c4090ad12b7 100644 (file)
@@ -108,6 +108,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);