351 lines
12 KiB
Diff
351 lines
12 KiB
Diff
|
From ff9baf5bf0ef960b9f1bb9668cfe6f3d66b288d0 Mon Sep 17 00:00:00 2001
|
||
|
From: Oliver Steffen <osteffen@redhat.com>
|
||
|
Date: Mon, 4 Nov 2024 12:40:12 +0100
|
||
|
Subject: [PATCH] OvmfPkg: Add a Fallback RNG (RH only)
|
||
|
|
||
|
RH-Author: Oliver Steffen <osteffen@redhat.com>
|
||
|
RH-MergeRequest: 80: OvmfPkg: Add a Fallback RNG (RH only)
|
||
|
RH-Jira: RHEL-65725
|
||
|
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
|
||
|
RH-Commit: [1/1] 2865ef247c476418c88ba988449841aee4a93bea (osteffen/edk2)
|
||
|
|
||
|
Since the pixiefail CVE fix, the network stack requires a random number
|
||
|
generator.
|
||
|
In case there is no hardware random number generator available,
|
||
|
have the Platform Boot Manager install a pseudo RNG to ensure
|
||
|
the network can be used.
|
||
|
|
||
|
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
|
||
|
---
|
||
|
.../PlatformBootManagerLib/BdsPlatform.c | 7 +
|
||
|
.../PlatformBootManagerLib/FallbackRng.c | 222 ++++++++++++++++++
|
||
|
.../PlatformBootManagerLib/FallbackRng.h | 20 ++
|
||
|
.../PlatformBootManagerLib.inf | 5 +
|
||
|
4 files changed, 254 insertions(+)
|
||
|
create mode 100644 OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.c
|
||
|
create mode 100644 OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.h
|
||
|
|
||
|
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
|
||
|
index d9f61757cf..87d1ac3142 100644
|
||
|
--- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
|
||
|
+++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
|
||
|
@@ -15,6 +15,8 @@
|
||
|
#include <Library/Tcg2PhysicalPresenceLib.h>
|
||
|
#include <Library/XenPlatformLib.h>
|
||
|
|
||
|
+#include "FallbackRng.h"
|
||
|
+
|
||
|
//
|
||
|
// Global data
|
||
|
//
|
||
|
@@ -539,6 +541,9 @@ PlatformBootManagerBeforeConsole (
|
||
|
ConnectVirtioPciRng,
|
||
|
NULL
|
||
|
);
|
||
|
+
|
||
|
+ FallbackRngCheckAndInstall ();
|
||
|
+
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
@@ -1778,6 +1783,8 @@ PlatformBootManagerAfterConsole (
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));
|
||
|
|
||
|
+ FallbackRngPrintWarning ();
|
||
|
+
|
||
|
if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
|
||
|
DEBUG ((
|
||
|
DEBUG_INFO,
|
||
|
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.c b/OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.c
|
||
|
new file mode 100644
|
||
|
index 0000000000..bba60e29d5
|
||
|
--- /dev/null
|
||
|
+++ b/OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.c
|
||
|
@@ -0,0 +1,222 @@
|
||
|
+/** @file
|
||
|
+ Copyright (C) 2024, Red Hat, Inc.
|
||
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
+**/
|
||
|
+
|
||
|
+#include <Uefi/UefiBaseType.h>
|
||
|
+#include <Uefi/UefiSpec.h>
|
||
|
+#include <Protocol/Rng.h>
|
||
|
+#include <Library/BaseMemoryLib.h>
|
||
|
+#include <Library/BaseLib.h>
|
||
|
+#include <Library/DebugLib.h>
|
||
|
+#include <Library/RngLib.h>
|
||
|
+#include <Library/UefiBootServicesTableLib.h>
|
||
|
+#include <Library/UefiLib.h>
|
||
|
+#include <Library/PrintLib.h>
|
||
|
+#include <Library/DxeServicesTableLib.h>
|
||
|
+
|
||
|
+#include "FallbackRng.h"
|
||
|
+
|
||
|
+typedef struct {
|
||
|
+ EFI_RNG_PROTOCOL Rng;
|
||
|
+ EFI_HANDLE Handle;
|
||
|
+} FALLBACK_RNG_DEV;
|
||
|
+
|
||
|
+/**
|
||
|
+ Returns information about the random number generation implementation.
|
||
|
+
|
||
|
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL
|
||
|
+ instance.
|
||
|
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of
|
||
|
+ RNGAlgorithmList.
|
||
|
+ On output with a return code of
|
||
|
+ EFI_SUCCESS, the size in bytes of the
|
||
|
+ data returned in RNGAlgorithmList. On
|
||
|
+ output with a return code of
|
||
|
+ EFI_BUFFER_TOO_SMALL, the size of
|
||
|
+ RNGAlgorithmList required to obtain the
|
||
|
+ list.
|
||
|
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled
|
||
|
+ by the driver with one EFI_RNG_ALGORITHM
|
||
|
+ element for each supported RNG algorithm.
|
||
|
+ The list must not change across multiple
|
||
|
+ calls to the same driver. The first
|
||
|
+ algorithm in the list is the default
|
||
|
+ algorithm for the driver.
|
||
|
+
|
||
|
+ @retval EFI_SUCCESS The RNG algorithm list was returned
|
||
|
+ successfully.
|
||
|
+ @retval EFI_UNSUPPORTED The services is not supported by this
|
||
|
+ driver.
|
||
|
+ @retval EFI_DEVICE_ERROR The list of algorithms could not be
|
||
|
+ retrieved due to a hardware or firmware
|
||
|
+ error.
|
||
|
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are
|
||
|
+ incorrect.
|
||
|
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small
|
||
|
+ to hold the result.
|
||
|
+
|
||
|
+**/
|
||
|
+STATIC
|
||
|
+EFI_STATUS
|
||
|
+EFIAPI
|
||
|
+FallbackRngGetInfo (
|
||
|
+ IN EFI_RNG_PROTOCOL *This,
|
||
|
+ IN OUT UINTN *RNGAlgorithmListSize,
|
||
|
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
|
||
|
+ )
|
||
|
+{
|
||
|
+ if ((This == NULL) || (RNGAlgorithmListSize == NULL)) {
|
||
|
+ return EFI_INVALID_PARAMETER;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) {
|
||
|
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
|
||
|
+ return EFI_BUFFER_TOO_SMALL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (RNGAlgorithmList == NULL) {
|
||
|
+ return EFI_INVALID_PARAMETER;
|
||
|
+ }
|
||
|
+
|
||
|
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
|
||
|
+ CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw);
|
||
|
+
|
||
|
+ return EFI_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ Produces and returns an RNG value using either the default or specified RNG
|
||
|
+ algorithm.
|
||
|
+
|
||
|
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL
|
||
|
+ instance.
|
||
|
+ @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that
|
||
|
+ identifies the RNG algorithm to use. May
|
||
|
+ be NULL in which case the function will
|
||
|
+ use its default RNG algorithm.
|
||
|
+ @param[in] RNGValueLength The length in bytes of the memory buffer
|
||
|
+ pointed to by RNGValue. The driver shall
|
||
|
+ return exactly this numbers of bytes.
|
||
|
+ @param[out] RNGValue A caller-allocated memory buffer filled
|
||
|
+ by the driver with the resulting RNG
|
||
|
+ value.
|
||
|
+
|
||
|
+ @retval EFI_SUCCESS The RNG value was returned successfully.
|
||
|
+ @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm
|
||
|
+ is not supported by this driver.
|
||
|
+ @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due
|
||
|
+ to a hardware or firmware error.
|
||
|
+ @retval EFI_NOT_READY There is not enough random data available
|
||
|
+ to satisfy the length requested by
|
||
|
+ RNGValueLength.
|
||
|
+ @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is
|
||
|
+ zero.
|
||
|
+
|
||
|
+**/
|
||
|
+STATIC
|
||
|
+EFI_STATUS
|
||
|
+EFIAPI
|
||
|
+FallbackRngGetRNG (
|
||
|
+ IN EFI_RNG_PROTOCOL *This,
|
||
|
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm OPTIONAL,
|
||
|
+ IN UINTN RNGValueLength,
|
||
|
+ OUT UINT8 *RNGValue
|
||
|
+ )
|
||
|
+{
|
||
|
+ UINT64 RandomData;
|
||
|
+ EFI_STATUS Status;
|
||
|
+ UINTN i;
|
||
|
+
|
||
|
+ if ((This == NULL) || (RNGValueLength == 0) || (RNGValue == NULL)) {
|
||
|
+ return EFI_INVALID_PARAMETER;
|
||
|
+ }
|
||
|
+
|
||
|
+ //
|
||
|
+ // We only support the raw algorithm, so reject requests for anything else
|
||
|
+ //
|
||
|
+ if ((RNGAlgorithm != NULL) &&
|
||
|
+ !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw))
|
||
|
+ {
|
||
|
+ return EFI_UNSUPPORTED;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < RNGValueLength; ++i) {
|
||
|
+ if (i % 4 == 0) {
|
||
|
+ Status = GetRandomNumber64 (&RandomData);
|
||
|
+ if (EFI_ERROR (Status)) {
|
||
|
+ return Status;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return EFI_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+static FALLBACK_RNG_DEV Dev = {
|
||
|
+ .Rng.GetInfo = FallbackRngGetInfo,
|
||
|
+ .Rng.GetRNG = FallbackRngGetRNG,
|
||
|
+ .Handle = NULL,
|
||
|
+};
|
||
|
+
|
||
|
+EFI_STATUS
|
||
|
+FallbackRngCheckAndInstall (
|
||
|
+ )
|
||
|
+{
|
||
|
+ EFI_STATUS Status;
|
||
|
+ EFI_HANDLE *HandleBuffer = NULL;
|
||
|
+ UINTN HandleCount = 0;
|
||
|
+
|
||
|
+ if (Dev.Handle != NULL) {
|
||
|
+ DEBUG ((DEBUG_INFO, "Fallback RNG already installed.\n"));
|
||
|
+ return EFI_ALREADY_STARTED;
|
||
|
+ }
|
||
|
+
|
||
|
+ Status = gBS->LocateHandleBuffer (
|
||
|
+ ByProtocol,
|
||
|
+ &gEfiRngProtocolGuid,
|
||
|
+ NULL,
|
||
|
+ &HandleCount,
|
||
|
+ &HandleBuffer
|
||
|
+ );
|
||
|
+
|
||
|
+ gBS->FreePool (HandleBuffer);
|
||
|
+
|
||
|
+ if (Status == EFI_NOT_FOUND) {
|
||
|
+ HandleCount = 0;
|
||
|
+ } else if (EFI_ERROR (Status)) {
|
||
|
+ DEBUG ((DEBUG_ERROR, "Error locating RNG protocol instances: %r\n", Status));
|
||
|
+ return Status;
|
||
|
+ }
|
||
|
+
|
||
|
+ DEBUG ((DEBUG_INFO, "Found %u RNGs\n", HandleCount));
|
||
|
+
|
||
|
+ if (HandleCount == 0) {
|
||
|
+ // Install RNG
|
||
|
+ Status = gBS->InstallProtocolInterface (
|
||
|
+ &Dev.Handle,
|
||
|
+ &gEfiRngProtocolGuid,
|
||
|
+ EFI_NATIVE_INTERFACE,
|
||
|
+ &Dev.Rng
|
||
|
+ );
|
||
|
+ if (EFI_ERROR (Status)) {
|
||
|
+ DEBUG ((DEBUG_ERROR, "Failed to install fallback RNG: %r\n", Status));
|
||
|
+ return Status;
|
||
|
+ }
|
||
|
+
|
||
|
+ gDS->Dispatch ();
|
||
|
+ }
|
||
|
+
|
||
|
+ return EFI_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+VOID
|
||
|
+FallbackRngPrintWarning (
|
||
|
+ )
|
||
|
+{
|
||
|
+ if (Dev.Handle != NULL) {
|
||
|
+ Print (L"WARNING: Pseudo Random Number Generator in use - Pixiefail CVE not mitigated!\n");
|
||
|
+ DEBUG ((DEBUG_WARN, "WARNING: Pseudo Random Number Generator in use - Pixiefail CVE not mitigated!\n"));
|
||
|
+ gBS->Stall (2000000);
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.h b/OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.h
|
||
|
new file mode 100644
|
||
|
index 0000000000..77332bc51c
|
||
|
--- /dev/null
|
||
|
+++ b/OvmfPkg/Library/PlatformBootManagerLib/FallbackRng.h
|
||
|
@@ -0,0 +1,20 @@
|
||
|
+/** @file
|
||
|
+ Copyright (C) 2024, Red Hat, Inc.
|
||
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
+**/
|
||
|
+
|
||
|
+#ifndef _FALLBACK_RNG_H_
|
||
|
+#define _FALLBACK_RNG_H_
|
||
|
+
|
||
|
+#include <Uefi/UefiBaseType.h>
|
||
|
+#include <Uefi/UefiSpec.h>
|
||
|
+
|
||
|
+EFI_STATUS
|
||
|
+FallbackRngCheckAndInstall (
|
||
|
+ );
|
||
|
+
|
||
|
+VOID
|
||
|
+FallbackRngPrintWarning (
|
||
|
+ );
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
|
||
|
index c6ffc1ed9e..211716e30d 100644
|
||
|
--- a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
|
||
|
+++ b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
|
||
|
@@ -25,6 +25,8 @@
|
||
|
PlatformData.c
|
||
|
QemuKernel.c
|
||
|
BdsPlatform.h
|
||
|
+ FallbackRng.c
|
||
|
+ FallbackRng.h
|
||
|
|
||
|
[Packages]
|
||
|
MdePkg/MdePkg.dec
|
||
|
@@ -56,6 +58,7 @@
|
||
|
PlatformBmPrintScLib
|
||
|
Tcg2PhysicalPresenceLib
|
||
|
XenPlatformLib
|
||
|
+ RngLib
|
||
|
|
||
|
[Pcd]
|
||
|
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent
|
||
|
@@ -80,6 +83,7 @@
|
||
|
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
|
||
|
gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
|
||
|
gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
|
||
|
+ gEfiRngProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
|
||
|
|
||
|
[Guids]
|
||
|
gEfiEndOfDxeEventGroupGuid
|
||
|
@@ -87,3 +91,4 @@
|
||
|
gRootBridgesConnectedEventGroupGuid
|
||
|
gUefiShellFileGuid
|
||
|
gGrubFileGuid
|
||
|
+ gEfiRngAlgorithmRaw
|
||
|
--
|
||
|
2.39.3
|
||
|
|