You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
10 KiB
337 lines
10 KiB
5 months ago
|
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
|
||
|
|