From ff9baf5bf0ef960b9f1bb9668cfe6f3d66b288d0 Mon Sep 17 00:00:00 2001 From: Oliver Steffen Date: Mon, 4 Nov 2024 12:40:12 +0100 Subject: [PATCH] OvmfPkg: Add a Fallback RNG (RH only) RH-Author: Oliver Steffen RH-MergeRequest: 80: OvmfPkg: Add a Fallback RNG (RH only) RH-Jira: RHEL-65725 RH-Acked-by: Gerd Hoffmann 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 --- .../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 #include +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +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