[edk2-devel] [PATCH v3 17/22] SecurityPkg/RngDxe: Check before advertising Cpu Rng algo

PierreGondois pierre.gondois at arm.com
Wed Jun 29 15:02:32 UTC 2022


From: Pierre Gondois <pierre.gondois at arm.com>

RngGetBytes() relies on the RngLib. The RngLib might use the RNDR
instruction if the FEAT_RNG feature is present. Check RngGetBytes() is
working before advertising it via RngGetInfo().

To only check this one time, create a static array that is shared
between RngGetInfo and RngGetRNG. This array contains GUIDs.
The Rng algorithm with the lowest GUID and that has been checked
will be the default Rng algorithm.

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 at arm.com>
---
 .../RngDxe/AArch64/RngDxe.c                   | 77 +++++++++++++++++--
 1 file changed, 69 insertions(+), 8 deletions(-)

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
index f9c740d761ff..d8b696bbea5f 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
@@ -23,10 +23,44 @@
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/UefiBootServicesTableLib.h>
+#include <Library/RngLib.h>
 #include <Protocol/Rng.h>
 
 #include "RngDxeInternals.h"
 
+//
+// Static array containing the validated Rng algorithm.
+// This array is used by RngGetInfo and RngGetRNG and needs to be
+// populated only once.
+// The valid entry with the lowest index will be the default algorithm.
+//
+#define RNG_AVAILABLE_ALGO_MAX  1
+STATIC BOOLEAN            mAvailableAlgoArrayInit = FALSE;
+STATIC UINTN              mAvailableAlgoArrayCount;
+STATIC EFI_RNG_ALGORITHM  mAvailableAlgoArray[RNG_AVAILABLE_ALGO_MAX];
+
+/** Initialize mAvailableAlgoArray with the available Rng algorithms.
+**/
+STATIC
+VOID
+EFIAPI
+RngInitAvailableAlgoArray (
+  VOID
+  )
+{
+  // Check RngGetBytes() before advertising PcdCpuRngSupportedAlgorithm.
+  if (!EFI_ERROR (RngGetBytes (sizeof (Rand), (UINT8 *)&Rand))) {
+    CopyMem (
+      &mAvailableAlgoArray[mAvailableAlgoArrayCount],
+      PcdGetPtr (PcdCpuRngSupportedAlgorithm),
+      sizeof (EFI_RNG_ALGORITHM)
+      );
+    mAvailableAlgoArrayCount++;
+  }
+
+  mAvailableAlgoArrayInit = TRUE;
+}
+
 /**
   Produces and returns an RNG value using either the default or specified RNG algorithm.
 
@@ -59,18 +93,35 @@ RngGetRNG (
   )
 {
   EFI_STATUS  Status;
+  UINTN       Index;
 
   if ((This == NULL) || (RNGValueLength == 0) || (RNGValue == NULL)) {
     return EFI_INVALID_PARAMETER;
   }
 
+  if (!mAvailableAlgoArrayInit) {
+    RngInitAvailableAlgoArray ();
+  }
+
   if (RNGAlgorithm == NULL) {
     //
     // Use the default RNG algorithm if RNGAlgorithm is NULL.
     //
-    RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+    for (Index = 0; Index < RNG_AVAILABLE_ALGO_MAX; Index++) {
+      if (!IsZeroGuid (&mAvailableAlgoArray[Index])) {
+        RNGAlgorithm = &mAvailableAlgoArray[Index];
+        goto FoundAlgo;
+      }
+    }
+
+    if (Index == RNG_AVAILABLE_ALGO_MAX) {
+      // No algorithm available.
+      ASSERT (Index != RNG_AVAILABLE_ALGO_MAX);
+      return EFI_DEVICE_ERROR;
+    }
   }
 
+FoundAlgo:
   if (CompareGuid (RNGAlgorithm, PcdGetPtr (PcdCpuRngSupportedAlgorithm))) {
     Status = RngGetBytes (RNGValueLength, RNGValue);
     return Status;
@@ -113,24 +164,34 @@ 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;
   }
 
+  if (!mAvailableAlgoArrayInit) {
+    RngInitAvailableAlgoArray ();
+  }
+
+  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;
 }
-- 
2.25.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#90868): https://edk2.groups.io/g/devel/message/90868
Mute This Topic: https://groups.io/mt/92066753/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list