Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Sep 2024 15:25:18 GMT
From:      Colin Percival <cperciva@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: f470543a65b1 - stable/14 - loader: Expand EFI entropy if < 2048 bytes
Message-ID:  <202409291525.48TFPI2c030558@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by cperciva:

URL: https://cgit.FreeBSD.org/src/commit/?id=f470543a65b14cbf2fec4e69b924d66068e182f4

commit f470543a65b14cbf2fec4e69b924d66068e182f4
Author:     Colin Percival <cperciva@FreeBSD.org>
AuthorDate: 2024-09-18 11:02:12 +0000
Commit:     Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2024-09-29 15:24:52 +0000

    loader: Expand EFI entropy if < 2048 bytes
    
    The EFI RNG on some platforms takes a long time if we request 2048
    bytes of entropy, so we would like to request less; but our kernel
    Fortuna RNG needs to be fed 2048 bytes in order to consider itself
    "fully seeded".  If we have between 64 bytes (the size of a single
    Fortuna pool and enough to guarantee cryptographic security) and
    2048 bytes (what Fortuna wants) then the boot process will hang
    waiting for more entropy despite in fact having enough to operate
    securely.
    
    Since 64 bytes of entropy is plenty to be cryptographically secure
    (an attack of cost ~ 2^128 is infeasible, which implies a mere 16
    bytes of entropy), use PBKDF2 (aka pkcs5v2_genkey_raw) to spread
    the entropy across 2048 bytes.  This is secure since PBKDF2 has
    the property that every subset of output bytes has within O(1) of
    the maximum possible amount of entropy.
    
    Reviewed by:    pjd
    MFC after:      1 week
    Sponsored by:   Amazon
    Differential Revision:  https://reviews.freebsd.org/D46635
    
    (cherry picked from commit c8ebbd28aa91705aea3a67b06018ea6aef5aa6e4)
---
 stand/efi/loader/main.c | 39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c
index 27fdb3bfefc9..324150f7c8c7 100644
--- a/stand/efi/loader/main.c
+++ b/stand/efi/loader/main.c
@@ -56,6 +56,9 @@
 #include <bootstrap.h>
 #include <smbios.h>
 
+#include <dev/random/fortuna.h>
+#include <geom/eli/pkcs5v2.h>
+
 #include "efizfs.h"
 #include "framebuffer.h"
 
@@ -1249,11 +1252,27 @@ command_seed_entropy(int argc, char *argv[])
 {
 	EFI_STATUS status;
 	EFI_RNG_PROTOCOL *rng;
-	unsigned int size = 2048;
+	unsigned int size_efi = RANDOM_FORTUNA_DEFPOOLSIZE * RANDOM_FORTUNA_NPOOLS;
+	unsigned int size = RANDOM_FORTUNA_DEFPOOLSIZE * RANDOM_FORTUNA_NPOOLS;
+	void *buf_efi;
 	void *buf;
 
 	if (argc > 1) {
-		size = strtol(argv[1], NULL, 0);
+		size_efi = strtol(argv[1], NULL, 0);
+
+		/* Don't *compress* the entropy we get from EFI. */
+		if (size_efi > size)
+			size = size_efi;
+
+		/*
+		 * If the amount of entropy we get from EFI is less than the
+		 * size of a single Fortuna pool -- i.e. not enough to ensure
+		 * that Fortuna is safely seeded -- don't expand it since we
+		 * don't want to trick Fortuna into thinking that it has been
+		 * safely seeded when it has not.
+		 */
+		if (size_efi < RANDOM_FORTUNA_DEFPOOLSIZE)
+			size = size_efi;
 	}
 
 	status = BS->LocateProtocol(&rng_guid, NULL, (VOID **)&rng);
@@ -1267,20 +1286,34 @@ command_seed_entropy(int argc, char *argv[])
 		return (CMD_ERROR);
 	}
 
+	if ((buf_efi = malloc(size_efi)) == NULL) {
+		free(buf);
+		command_errmsg = "out of memory";
+		return (CMD_ERROR);
+	}
+
 	TSENTER2("rng->GetRNG");
-	status = rng->GetRNG(rng, NULL, size, (UINT8 *)buf);
+	status = rng->GetRNG(rng, NULL, size_efi, (UINT8 *)buf_efi);
 	TSEXIT();
 	if (status != EFI_SUCCESS) {
+		free(buf_efi);
 		free(buf);
 		command_errmsg = "GetRNG failed";
 		return (CMD_ERROR);
 	}
+	if (size_efi < size)
+		pkcs5v2_genkey_raw(buf, size, "", 0, buf_efi, size_efi, 1);
+	else
+		memcpy(buf, buf_efi, size);
 
 	if (file_addbuf("efi_rng_seed", "boot_entropy_platform", size, buf) != 0) {
+		free(buf_efi);
 		free(buf);
 		return (CMD_ERROR);
 	}
 
+	explicit_bzero(buf_efi, size_efi);
+	free(buf_efi);
 	free(buf);
 	return (CMD_OK);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202409291525.48TFPI2c030558>