]> xenbits.xensource.com Git - people/aperard/ovmf.git/commitdiff
MdePkg/DxeRngLib: Refactor Rng algorithm selection
authorPierre Gondois <pierre.gondois@arm.com>
Tue, 3 Sep 2024 16:04:39 +0000 (18:04 +0200)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 13 Sep 2024 14:34:21 +0000 (14:34 +0000)
Add a library constructor which:
- locate the RNG prototocol and keep a reference to it in order to avoid
  locating it multiple times (for each random number generation)
- check which secure algorithm is available on the platform.
  This avoids to try each secure algorithm until finding one
  available for each random number generation call.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
MdePkg/Library/DxeRngLib/DxeRngLib.c
MdePkg/Library/DxeRngLib/DxeRngLib.inf

index 05c795759b9a31080a4073d8f841ead22ad0249e..4b4efef0b424541936da1ce5d27f9d98cb984d9e 100644 (file)
 /** @file\r
  Provides an implementation of the library class RngLib that uses the Rng protocol.\r
 \r
- Copyright (c) 2023, Arm Limited. All rights reserved.\r
+ Copyright (c) 2023 - 2024, Arm Limited. All rights reserved.\r
  Copyright (c) Microsoft Corporation. All rights reserved.\r
  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 #include <Uefi.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Library/RngLib.h>\r
 #include <Protocol/Rng.h>\r
 \r
+STATIC EFI_RNG_PROTOCOL  *mRngProtocol;\r
+STATIC UINTN             mFirstAlgo = MAX_UINTN;\r
+\r
+typedef struct {\r
+  /// Guid of the secure algorithm.\r
+  EFI_GUID       *Guid;\r
+\r
+  /// Algorithm name.\r
+  CONST CHAR8    *Name;\r
+\r
+  /// The algorithm is available for use.\r
+  BOOLEAN        Available;\r
+} SECURE_RNG_ALGO_ARRAY;\r
+\r
+//\r
+// These represent UEFI SPEC defined algorithms that should be supported by\r
+// the RNG protocol and are generally considered secure.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED SECURE_RNG_ALGO_ARRAY  mSecureHashAlgorithms[] = {\r
+  {\r
+    &gEfiRngAlgorithmSp80090Ctr256Guid,  // SP800-90A DRBG CTR using AES-256\r
+    "DRBG-CTR",\r
+    FALSE,\r
+  },\r
+  {\r
+    &gEfiRngAlgorithmSp80090Hmac256Guid, // SP800-90A DRBG HMAC using SHA-256\r
+    "DRBG-HMAC",\r
+    FALSE,\r
+  },\r
+  {\r
+    &gEfiRngAlgorithmSp80090Hash256Guid, // SP800-90A DRBG Hash using SHA-256\r
+    "DRBG-Hash",\r
+    FALSE,\r
+  },\r
+  {\r
+    &gEfiRngAlgorithmRaw, // Raw data from NRBG (or TRNG)\r
+    "TRNG",\r
+    FALSE,\r
+  },\r
+};\r
+\r
+/**\r
+  Constructor routine to probe the available secure Rng algorithms.\r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS           Success.\r
+  @retval EFI_NOT_FOUND         Not found.\r
+  @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeRngLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  UINTN              RngArraySize;\r
+  UINTN              RngArrayCnt;\r
+  UINT32             Index;\r
+  UINT32             Index1;\r
+  EFI_RNG_ALGORITHM  *RngArray;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&mRngProtocol);\r
+  if (EFI_ERROR (Status) || (mRngProtocol == NULL)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: Could not locate RNG protocol, Status = %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  RngArraySize = 0;\r
+\r
+  Status = mRngProtocol->GetInfo (mRngProtocol, &RngArraySize, NULL);\r
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
+    return Status;\r
+  } else if (RngArraySize == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  RngArrayCnt = RngArraySize / sizeof (*RngArray);\r
+\r
+  RngArray = AllocateZeroPool (RngArraySize);\r
+  if (RngArray == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = mRngProtocol->GetInfo (mRngProtocol, &RngArraySize, RngArray);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ExitHandler;\r
+  }\r
+\r
+  for (Index = 0; Index < RngArrayCnt; Index++) {\r
+    for (Index1 = 0; Index1 < ARRAY_SIZE (mSecureHashAlgorithms); Index1++) {\r
+      if (CompareGuid (&RngArray[Index], mSecureHashAlgorithms[Index1].Guid)) {\r
+        mSecureHashAlgorithms[Index1].Available = TRUE;\r
+        if (mFirstAlgo == MAX_UINTN) {\r
+          mFirstAlgo = Index1;\r
+        }\r
+\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+ExitHandler:\r
+  FreePool (RngArray);\r
+  return Status;\r
+}\r
+\r
 /**\r
   Routine Description:\r
 \r
@@ -32,55 +144,68 @@ GenerateRandomNumberViaNist800Algorithm (
   IN  UINTN  BufferSize\r
   )\r
 {\r
-  EFI_STATUS        Status;\r
-  EFI_RNG_PROTOCOL  *RngProtocol;\r
-\r
-  RngProtocol = NULL;\r
+  EFI_STATUS             Status;\r
+  UINTN                  Index;\r
+  SECURE_RNG_ALGO_ARRAY  *Algo;\r
 \r
   if (Buffer == NULL) {\r
     DEBUG ((DEBUG_ERROR, "%a: Buffer == NULL.\n", __func__));\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol);\r
-  if (EFI_ERROR (Status) || (RngProtocol == NULL)) {\r
-    DEBUG ((DEBUG_ERROR, "%a: Could not locate RNG prototocol, Status = %r\n", __func__, Status));\r
-    return Status;\r
-  }\r
-\r
-  Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Ctr256Guid, BufferSize, Buffer);\r
-  DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm CTR-256 - Status = %r\n", __func__, Status));\r
-  if (!EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hmac256Guid, BufferSize, Buffer);\r
-  DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm HMAC-256 - Status = %r\n", __func__, Status));\r
-  if (!EFI_ERROR (Status)) {\r
-    return Status;\r
+  if (mRngProtocol == NULL) {\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
-  Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hash256Guid, BufferSize, Buffer);\r
-  DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Hash-256 - Status = %r\n", __func__, Status));\r
-  if (!EFI_ERROR (Status)) {\r
-    return Status;\r
+  // Try the first available algorithm.\r
+  if (mFirstAlgo != MAX_UINTN) {\r
+    Algo   = &mSecureHashAlgorithms[mFirstAlgo];\r
+    Status = mRngProtocol->GetRNG (mRngProtocol, Algo->Guid, BufferSize, Buffer);\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: GetRNG algorithm %a - Status = %r\n",\r
+      __func__,\r
+      Algo->Name,\r
+      Status\r
+      ));\r
+    if (!EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Index = mFirstAlgo + 1;\r
+  } else {\r
+    Index = 0;\r
   }\r
 \r
-  Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmRaw, BufferSize, Buffer);\r
-  DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Raw - Status = %r\n", __func__, Status));\r
-  if (!EFI_ERROR (Status)) {\r
-    return Status;\r
+  // Iterate over other available algorithms.\r
+  for ( ; Index < ARRAY_SIZE (mSecureHashAlgorithms); Index++) {\r
+    Algo = &mSecureHashAlgorithms[Index];\r
+    if (!Algo->Available) {\r
+      continue;\r
+    }\r
+\r
+    Status = mRngProtocol->GetRNG (mRngProtocol, Algo->Guid, BufferSize, Buffer);\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: GetRNG algorithm %a - Status = %r\n",\r
+      __func__,\r
+      Algo->Name,\r
+      Status\r
+      ));\r
+    if (!EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
   // If all the other methods have failed, use the default method from the RngProtocol\r
-  Status = RngProtocol->GetRNG (RngProtocol, NULL, BufferSize, Buffer);\r
+  Status = mRngProtocol->GetRNG (mRngProtocol, NULL, BufferSize, Buffer);\r
   DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm default - Status = %r\n", __func__, Status));\r
   if (!EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   // If we get to this point, we have failed\r
-  DEBUG ((DEBUG_ERROR, "%a: GetRNG() failed, staus = %r\n", __func__, Status));\r
+  DEBUG ((DEBUG_ERROR, "%a: GetRNG() failed, Status = %r\n", __func__, Status));\r
 \r
   return Status;\r
 }// GenerateRandomNumberViaNist800Algorithm()\r
index 281fec46502fbf7bc264505b1ba726002d0ff9e1..ca649585d4cf5104ece31cf5e9f35ab1e21dc478 100644 (file)
@@ -15,6 +15,7 @@
   MODULE_TYPE     = DXE_DRIVER\r
   VERSION_STRING  = 1.0\r
   LIBRARY_CLASS   = RngLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER\r
+  CONSTRUCTOR     = DxeRngLibConstructor\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
@@ -24,6 +25,7 @@
 \r
 [LibraryClasses]\r
   DebugLib\r
+  MemoryAllocationLib\r
   UefiBootServicesTableLib\r
 \r
 [Protocols]\r