]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
SecurityPkg/RngDxe: Check before advertising Cpu Rng algo
[mirror_edk2.git] / SecurityPkg / RandomNumberGenerator / RngDxe / AArch64 / RngDxe.c
index f9c740d761ff8fb4c07c0ce4af2b1166adafe418..09a5924a699bc3abcab3967d6d6f7b7849f35149 100644 (file)
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/RngLib.h>\r
 #include <Protocol/Rng.h>\r
 \r
 #include "RngDxeInternals.h"\r
 \r
+// Maximum number of Rng algorithms.\r
+#define RNG_AVAILABLE_ALGO_MAX  1\r
+\r
+/** Allocate and initialize mAvailableAlgoArray with the available\r
+    Rng algorithms. Also update mAvailableAlgoArrayCount.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetAvailableAlgorithms (\r
+  VOID\r
+  )\r
+{\r
+  UINT64  DummyRand;\r
+\r
+  // Allocate RNG_AVAILABLE_ALGO_MAX entries to avoid evaluating\r
+  // Rng algorithms 2 times, one for the allocation, one to populate.\r
+  mAvailableAlgoArray = AllocateZeroPool (RNG_AVAILABLE_ALGO_MAX);\r
+  if (mAvailableAlgoArray == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  // Check RngGetBytes() before advertising PcdCpuRngSupportedAlgorithm.\r
+  if (!EFI_ERROR (RngGetBytes (sizeof (DummyRand), (UINT8 *)&DummyRand))) {\r
+    CopyMem (\r
+      &mAvailableAlgoArray[mAvailableAlgoArrayCount],\r
+      PcdGetPtr (PcdCpuRngSupportedAlgorithm),\r
+      sizeof (EFI_RNG_ALGORITHM)\r
+      );\r
+    mAvailableAlgoArrayCount++;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/** Free mAvailableAlgoArray.\r
+**/\r
+VOID\r
+EFIAPI\r
+FreeAvailableAlgorithms (\r
+  VOID\r
+  )\r
+{\r
+  FreePool (mAvailableAlgoArray);\r
+  return;\r
+}\r
+\r
 /**\r
   Produces and returns an RNG value using either the default or specified RNG algorithm.\r
 \r
@@ -59,6 +111,7 @@ RngGetRNG (
   )\r
 {\r
   EFI_STATUS  Status;\r
+  UINTN       Index;\r
 \r
   if ((This == NULL) || (RNGValueLength == 0) || (RNGValue == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -68,9 +121,21 @@ RngGetRNG (
     //\r
     // Use the default RNG algorithm if RNGAlgorithm is NULL.\r
     //\r
-    RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);\r
+    for (Index = 0; Index < mAvailableAlgoArrayCount; Index++) {\r
+      if (!IsZeroGuid (&mAvailableAlgoArray[Index])) {\r
+        RNGAlgorithm = &mAvailableAlgoArray[Index];\r
+        goto FoundAlgo;\r
+      }\r
+    }\r
+\r
+    if (Index == mAvailableAlgoArrayCount) {\r
+      // No algorithm available.\r
+      ASSERT (Index != mAvailableAlgoArrayCount);\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
   }\r
 \r
+FoundAlgo:\r
   if (CompareGuid (RNGAlgorithm, PcdGetPtr (PcdCpuRngSupportedAlgorithm))) {\r
     Status = RngGetBytes (RNGValueLength, RNGValue);\r
     return Status;\r
@@ -113,24 +178,30 @@ RngGetInfo (
   OUT EFI_RNG_ALGORITHM  *RNGAlgorithmList\r
   )\r
 {\r
-  UINTN              RequiredSize;\r
-  EFI_RNG_ALGORITHM  *CpuRngSupportedAlgorithm;\r
-\r
-  RequiredSize = sizeof (EFI_RNG_ALGORITHM);\r
+  UINTN  RequiredSize;\r
 \r
   if ((This == NULL) || (RNGAlgorithmListSize == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  RequiredSize = mAvailableAlgoArrayCount * sizeof (EFI_RNG_ALGORITHM);\r
+\r
+  if (RequiredSize == 0) {\r
+    // No supported algorithms found.\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   if (*RNGAlgorithmListSize < RequiredSize) {\r
     *RNGAlgorithmListSize = RequiredSize;\r
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
 \r
-  CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);\r
-\r
-  CopyMem (&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));\r
+  if (RNGAlgorithmList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
+  // There is no gap in the array, so copy the block.\r
+  CopyMem (RNGAlgorithmList, mAvailableAlgoArray, RequiredSize);\r
   *RNGAlgorithmListSize = RequiredSize;\r
   return EFI_SUCCESS;\r
 }\r