edk2/SOURCES/edk2-SecurityPkg-RngDxe-Check-before-advertising-Cpu-Rng-.patch

337 lines
10 KiB
Diff
Raw Permalink Normal View History

2024-08-14 08:16:04 +00:00
From 5bd27a5a923c8880a06d52fca48e304becbbb8f6 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Tue, 25 Jun 2024 22:25:23 -0400
Subject: [PATCH 08/31] SecurityPkg/RngDxe: Check before advertising Cpu Rng
algo
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 77: UINT32 overflow in S3 ResumeCount and Pixiefail fixes
RH-Jira: RHEL-21854 RHEL-21856 RHEL-40099
RH-Acked-by: Gerd Hoffmann <None>
RH-Commit: [8/31] 5417b276749a2d1b1afa9465b5b7a501def26a12
JIRA: https://issues.redhat.com/browse/RHEL-21856
CVE: CVE-2022-45237
Upstream: Merged
commit 4b3e9d80bedf5909a4ec901425ed9c0a738fc76f
Author: Pierre Gondois <pierre.gondois@arm.com>
Date: Fri Oct 28 17:32:54 2022 +0200
SecurityPkg/RngDxe: Check before advertising Cpu Rng algo
RngGetBytes() relies on the RngLib. The RngLib might use the RNDR
instruction if the FEAT_RNG feature is present. RngGetInfo and
RngGetRNG both must check that RngGetBytes() is working before
advertising/using it.
To do so, allocate an array storing the available algorithms.
The Rng algorithm at the lowest index will be the default Rng
algorithm. The array is shared between RngGetInfo and RngGetRNG.
This array is allocated when the driver is loaded, and freed
when unloaded.
This patch also prevents from having PcdCpuRngSupportedAlgorithm
let to a zero GUID, but let the possibility to have no valid Rng
algorithm in such case.
Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
Acked-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
.../RngDxe/AArch64/RngDxe.c | 87 +++++++++++++++++--
.../RngDxe/Rand/RngDxe.c | 26 ++++++
.../RandomNumberGenerator/RngDxe/RngDxe.c | 40 ++++++++-
.../RandomNumberGenerator/RngDxe/RngDxe.inf | 1 +
.../RngDxe/RngDxeInternals.h | 27 ++++++
5 files changed, 172 insertions(+), 9 deletions(-)
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
index 8c6ad4ed43..c9d66d9777 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
@@ -22,11 +22,63 @@
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/RngLib.h>
#include <Protocol/Rng.h>
#include "RngDxeInternals.h"
+// Maximum number of Rng algorithms.
+#define RNG_AVAILABLE_ALGO_MAX 1
+
+/** Allocate and initialize mAvailableAlgoArray with the available
+ Rng algorithms. Also update mAvailableAlgoArrayCount.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+GetAvailableAlgorithms (
+ VOID
+ )
+{
+ UINT64 DummyRand;
+
+ // Allocate RNG_AVAILABLE_ALGO_MAX entries to avoid evaluating
+ // Rng algorithms 2 times, one for the allocation, one to populate.
+ mAvailableAlgoArray = AllocateZeroPool (RNG_AVAILABLE_ALGO_MAX);
+ if (mAvailableAlgoArray == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Check RngGetBytes() before advertising PcdCpuRngSupportedAlgorithm.
+ if (!EFI_ERROR (RngGetBytes (sizeof (DummyRand), (UINT8 *)&DummyRand))) {
+ CopyMem (
+ &mAvailableAlgoArray[mAvailableAlgoArrayCount],
+ PcdGetPtr (PcdCpuRngSupportedAlgorithm),
+ sizeof (EFI_RNG_ALGORITHM)
+ );
+ mAvailableAlgoArrayCount++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Free mAvailableAlgoArray.
+**/
+VOID
+EFIAPI
+FreeAvailableAlgorithms (
+ VOID
+ )
+{
+ FreePool (mAvailableAlgoArray);
+ return;
+}
+
/**
Produces and returns an RNG value using either the default or specified RNG algorithm.
@@ -59,6 +111,7 @@ RngGetRNG (
)
{
EFI_STATUS Status;
+ UINTN Index;
if ((This == NULL) || (RNGValueLength == 0) || (RNGValue == NULL)) {
return EFI_INVALID_PARAMETER;
@@ -68,9 +121,21 @@ RngGetRNG (
//
// Use the default RNG algorithm if RNGAlgorithm is NULL.
//
- RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+ for (Index = 0; Index < mAvailableAlgoArrayCount; Index++) {
+ if (!IsZeroGuid (&mAvailableAlgoArray[Index])) {
+ RNGAlgorithm = &mAvailableAlgoArray[Index];
+ goto FoundAlgo;
+ }
+ }
+
+ if (Index == mAvailableAlgoArrayCount) {
+ // No algorithm available.
+ ASSERT (Index != mAvailableAlgoArrayCount);
+ return EFI_DEVICE_ERROR;
+ }
}
+FoundAlgo:
if (CompareGuid (RNGAlgorithm, PcdGetPtr (PcdCpuRngSupportedAlgorithm))) {
Status = RngGetBytes (RNGValueLength, RNGValue);
return Status;
@@ -113,24 +178,30 @@ RngGetInfo (
OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
)
{
- UINTN RequiredSize;
- EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
-
- RequiredSize = sizeof (EFI_RNG_ALGORITHM);
+ UINTN RequiredSize;
if ((This == NULL) || (RNGAlgorithmListSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
+ RequiredSize = mAvailableAlgoArrayCount * sizeof (EFI_RNG_ALGORITHM);
+
+ if (RequiredSize == 0) {
+ // No supported algorithms found.
+ return EFI_UNSUPPORTED;
+ }
+
if (*RNGAlgorithmListSize < RequiredSize) {
*RNGAlgorithmListSize = RequiredSize;
return EFI_BUFFER_TOO_SMALL;
}
- CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
-
- CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));
+ if (RNGAlgorithmList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ // There is no gap in the array, so copy the block.
+ CopyMem (RNGAlgorithmList, mAvailableAlgoArray, RequiredSize);
*RNGAlgorithmListSize = RequiredSize;
return EFI_SUCCESS;
}
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
index 70b6ac20c9..7caa64a4ff 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
@@ -26,6 +26,32 @@
#include "RngDxeInternals.h"
+/** Allocate and initialize mAvailableAlgoArray with the available
+ Rng algorithms. Also update mAvailableAlgoArrayCount.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+GetAvailableAlgorithms (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/** Free mAvailableAlgoArray.
+**/
+VOID
+EFIAPI
+FreeAvailableAlgorithms (
+ VOID
+ )
+{
+ return;
+}
+
/**
Produces and returns an RNG value using either the default or specified RNG algorithm.
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
index 4599728889..cc2ddfcc06 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
@@ -27,6 +27,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "RngDxeInternals.h"
+//
+// Array containing the validated Rng algorithm.
+// The entry with the lowest index will be the default algorithm.
+//
+UINTN mAvailableAlgoArrayCount;
+EFI_RNG_ALGORITHM *mAvailableAlgoArray;
+
//
// The Random Number Generator (RNG) protocol
//
@@ -66,8 +73,39 @@ RngDriverEntry (
&mRngRdRand,
NULL
);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the list of available algorithm.
+ //
+ return GetAvailableAlgorithms ();
+}
+
+/**
+ This is the unload handle for RndgDxe module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
- return Status;
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+RngDriverUnLoad (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ //
+ // Free the list of available algorithm.
+ //
+ FreeAvailableAlgorithms ();
+ return EFI_SUCCESS;
}
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
index 60efb5562e..1985dfbb46 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
@@ -22,6 +22,7 @@
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = RngDriverEntry
+ UNLOAD_IMAGE = RngDriverUnLoad
MODULE_UNI_FILE = RngDxe.uni
#
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
index f17adb83fb..0ef5e6522f 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
@@ -12,6 +12,33 @@
#include <Protocol/Rng.h>
+//
+// Array containing the validated Rng algorithm.
+// The entry with the lowest index will be the default algorithm.
+//
+extern UINTN mAvailableAlgoArrayCount;
+extern EFI_RNG_ALGORITHM *mAvailableAlgoArray;
+
+/** Allocate and initialize mAvailableAlgoArray with the available
+ Rng algorithms. Also update mAvailableAlgoArrayCount.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+GetAvailableAlgorithms (
+ VOID
+ );
+
+/** Free mAvailableAlgoArray.
+**/
+VOID
+EFIAPI
+FreeAvailableAlgorithms (
+ VOID
+ );
+
/**
Returns information about the random number generation implementation.
--
2.39.3