From 58931d73c80e059791850f2746b8ebd866069d4c Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Thu, 29 Aug 2024 16:31:45 +0200 Subject: [PATCH 1/4] MdePkg: Move PcdEnforceSecureRngAlgorithms from NetworkPkg The PcdEnforceSecureRngAlgorithms Pcd enforces the use of RNG algorithms defined by the UEFI spec. To re-use the Pcd in other packages and have a generic mean to control the usage of unsecure algorithms, move the Pcd to the MdePkg. Continuous-integration-options: PatchCheck.ignore-multi-package Signed-off-by: Pierre Gondois --- MdePkg/MdePkg.dec | 6 ++++++ NetworkPkg/Library/DxeNetLib/DxeNetLib.inf | 2 +- NetworkPkg/NetworkPkg.dec | 6 ------ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index b542d6d83235..624f62636092 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -2266,6 +2266,12 @@ ## This PCD specifies the interrupt vector for stack cookie check failures gEfiMdePkgTokenSpaceGuid.PcdStackCookieExceptionVector|0x42|UINT8|0x30001019 + ## Enforces the use of Secure UEFI spec defined RNG algorithms. + # TRUE - Enforce the use of Secure UEFI spec defined RNG algorithms. + # FALSE - Do not enforce and depend on the default implementation of RNG algorithm from the provider. + # @Prompt Enforce the use of Secure UEFI spec defined RNG algorithms. + gEfiMdePkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|TRUE|BOOLEAN|0x1000000D + [PcdsFixedAtBuild,PcdsPatchableInModule] ## Indicates the maximum length of unicode string used in the following # BaseLib functions: StrLen(), StrSize(), StrCmp(), StrnCmp(), StrCpy(), StrnCpy()

diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf index a8f534a29358..54dcb97e578d 100644 --- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf +++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf @@ -67,7 +67,7 @@ gEfiRngProtocolGuid ## CONSUMES [FixedPcd] - gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES [Depex] gEfiRngProtocolGuid diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec index 7c4289b77b21..9f18349cffe2 100644 --- a/NetworkPkg/NetworkPkg.dec +++ b/NetworkPkg/NetworkPkg.dec @@ -131,12 +131,6 @@ # @Prompt Indicates whether SnpDxe creates event for ExitBootServices() call. gEfiNetworkPkgTokenSpaceGuid.PcdSnpCreateExitBootServicesEvent|TRUE|BOOLEAN|0x1000000C - ## Enforces the use of Secure UEFI spec defined RNG algorithms for all network connections. - # TRUE - Enforce the use of Secure UEFI spec defined RNG algorithms. - # FALSE - Do not enforce and depend on the default implementation of RNG algorithm from the provider. - # @Prompt Enforce the use of Secure UEFI spec defined RNG algorithms. - gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|TRUE|BOOLEAN|0x1000000D - [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] ## IPv6 DHCP Unique Identifier (DUID) Type configuration (From RFCs 3315 and 6355). # 01 = DUID Based on Link-layer Address Plus Time [DUID-LLT] From 416298072ea6612a0a206513a693ef023e649dd9 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Tue, 3 Sep 2024 18:04:39 +0200 Subject: [PATCH 2/4] MdePkg/DxeRngLib: Refactor Rng algorithm selection 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 --- MdePkg/Library/DxeRngLib/DxeRngLib.c | 187 +++++++++++++++++++++---- MdePkg/Library/DxeRngLib/DxeRngLib.inf | 2 + 2 files changed, 158 insertions(+), 31 deletions(-) diff --git a/MdePkg/Library/DxeRngLib/DxeRngLib.c b/MdePkg/Library/DxeRngLib/DxeRngLib.c index 05c795759b9a..4b4efef0b424 100644 --- a/MdePkg/Library/DxeRngLib/DxeRngLib.c +++ b/MdePkg/Library/DxeRngLib/DxeRngLib.c @@ -1,17 +1,129 @@ /** @file Provides an implementation of the library class RngLib that uses the Rng protocol. - Copyright (c) 2023, Arm Limited. All rights reserved. + Copyright (c) 2023 - 2024, Arm Limited. All rights reserved. Copyright (c) Microsoft Corporation. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include +#include #include +#include #include #include +STATIC EFI_RNG_PROTOCOL *mRngProtocol; +STATIC UINTN mFirstAlgo = MAX_UINTN; + +typedef struct { + /// Guid of the secure algorithm. + EFI_GUID *Guid; + + /// Algorithm name. + CONST CHAR8 *Name; + + /// The algorithm is available for use. + BOOLEAN Available; +} SECURE_RNG_ALGO_ARRAY; + +// +// These represent UEFI SPEC defined algorithms that should be supported by +// the RNG protocol and are generally considered secure. +// +GLOBAL_REMOVE_IF_UNREFERENCED SECURE_RNG_ALGO_ARRAY mSecureHashAlgorithms[] = { + { + &gEfiRngAlgorithmSp80090Ctr256Guid, // SP800-90A DRBG CTR using AES-256 + "DRBG-CTR", + FALSE, + }, + { + &gEfiRngAlgorithmSp80090Hmac256Guid, // SP800-90A DRBG HMAC using SHA-256 + "DRBG-HMAC", + FALSE, + }, + { + &gEfiRngAlgorithmSp80090Hash256Guid, // SP800-90A DRBG Hash using SHA-256 + "DRBG-Hash", + FALSE, + }, + { + &gEfiRngAlgorithmRaw, // Raw data from NRBG (or TRNG) + "TRNG", + FALSE, + }, +}; + +/** + Constructor routine to probe the available secure Rng algorithms. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS Success. + @retval EFI_NOT_FOUND Not found. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +DxeRngLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN RngArraySize; + UINTN RngArrayCnt; + UINT32 Index; + UINT32 Index1; + EFI_RNG_ALGORITHM *RngArray; + + Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&mRngProtocol); + if (EFI_ERROR (Status) || (mRngProtocol == NULL)) { + DEBUG ((DEBUG_ERROR, "%a: Could not locate RNG protocol, Status = %r\n", __func__, Status)); + return Status; + } + + RngArraySize = 0; + + Status = mRngProtocol->GetInfo (mRngProtocol, &RngArraySize, NULL); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + return Status; + } else if (RngArraySize == 0) { + return EFI_NOT_FOUND; + } + + RngArrayCnt = RngArraySize / sizeof (*RngArray); + + RngArray = AllocateZeroPool (RngArraySize); + if (RngArray == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = mRngProtocol->GetInfo (mRngProtocol, &RngArraySize, RngArray); + if (EFI_ERROR (Status)) { + goto ExitHandler; + } + + for (Index = 0; Index < RngArrayCnt; Index++) { + for (Index1 = 0; Index1 < ARRAY_SIZE (mSecureHashAlgorithms); Index1++) { + if (CompareGuid (&RngArray[Index], mSecureHashAlgorithms[Index1].Guid)) { + mSecureHashAlgorithms[Index1].Available = TRUE; + if (mFirstAlgo == MAX_UINTN) { + mFirstAlgo = Index1; + } + + break; + } + } + } + +ExitHandler: + FreePool (RngArray); + return Status; +} + /** Routine Description: @@ -32,55 +144,68 @@ GenerateRandomNumberViaNist800Algorithm ( IN UINTN BufferSize ) { - EFI_STATUS Status; - EFI_RNG_PROTOCOL *RngProtocol; - - RngProtocol = NULL; + EFI_STATUS Status; + UINTN Index; + SECURE_RNG_ALGO_ARRAY *Algo; if (Buffer == NULL) { DEBUG ((DEBUG_ERROR, "%a: Buffer == NULL.\n", __func__)); return EFI_INVALID_PARAMETER; } - Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol); - if (EFI_ERROR (Status) || (RngProtocol == NULL)) { - DEBUG ((DEBUG_ERROR, "%a: Could not locate RNG prototocol, Status = %r\n", __func__, Status)); - return Status; - } - - Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Ctr256Guid, BufferSize, Buffer); - DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm CTR-256 - Status = %r\n", __func__, Status)); - if (!EFI_ERROR (Status)) { - return Status; - } - - Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hmac256Guid, BufferSize, Buffer); - DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm HMAC-256 - Status = %r\n", __func__, Status)); - if (!EFI_ERROR (Status)) { - return Status; + if (mRngProtocol == NULL) { + return EFI_NOT_FOUND; } - Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hash256Guid, BufferSize, Buffer); - DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Hash-256 - Status = %r\n", __func__, Status)); - if (!EFI_ERROR (Status)) { - return Status; + // Try the first available algorithm. + if (mFirstAlgo != MAX_UINTN) { + Algo = &mSecureHashAlgorithms[mFirstAlgo]; + Status = mRngProtocol->GetRNG (mRngProtocol, Algo->Guid, BufferSize, Buffer); + DEBUG (( + DEBUG_INFO, + "%a: GetRNG algorithm %a - Status = %r\n", + __func__, + Algo->Name, + Status + )); + if (!EFI_ERROR (Status)) { + return Status; + } + + Index = mFirstAlgo + 1; + } else { + Index = 0; } - Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmRaw, BufferSize, Buffer); - DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Raw - Status = %r\n", __func__, Status)); - if (!EFI_ERROR (Status)) { - return Status; + // Iterate over other available algorithms. + for ( ; Index < ARRAY_SIZE (mSecureHashAlgorithms); Index++) { + Algo = &mSecureHashAlgorithms[Index]; + if (!Algo->Available) { + continue; + } + + Status = mRngProtocol->GetRNG (mRngProtocol, Algo->Guid, BufferSize, Buffer); + DEBUG (( + DEBUG_INFO, + "%a: GetRNG algorithm %a - Status = %r\n", + __func__, + Algo->Name, + Status + )); + if (!EFI_ERROR (Status)) { + return Status; + } } // If all the other methods have failed, use the default method from the RngProtocol - Status = RngProtocol->GetRNG (RngProtocol, NULL, BufferSize, Buffer); + Status = mRngProtocol->GetRNG (mRngProtocol, NULL, BufferSize, Buffer); DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm default - Status = %r\n", __func__, Status)); if (!EFI_ERROR (Status)) { return Status; } // If we get to this point, we have failed - DEBUG ((DEBUG_ERROR, "%a: GetRNG() failed, staus = %r\n", __func__, Status)); + DEBUG ((DEBUG_ERROR, "%a: GetRNG() failed, Status = %r\n", __func__, Status)); return Status; }// GenerateRandomNumberViaNist800Algorithm() diff --git a/MdePkg/Library/DxeRngLib/DxeRngLib.inf b/MdePkg/Library/DxeRngLib/DxeRngLib.inf index 281fec46502f..ca649585d4cf 100644 --- a/MdePkg/Library/DxeRngLib/DxeRngLib.inf +++ b/MdePkg/Library/DxeRngLib/DxeRngLib.inf @@ -15,6 +15,7 @@ MODULE_TYPE = DXE_DRIVER VERSION_STRING = 1.0 LIBRARY_CLASS = RngLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = DxeRngLibConstructor [Packages] MdePkg/MdePkg.dec @@ -24,6 +25,7 @@ [LibraryClasses] DebugLib + MemoryAllocationLib UefiBootServicesTableLib [Protocols] From 9ee1e9a939fef438ca669abacd68dc8f3873df7b Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Thu, 29 Aug 2024 16:42:33 +0200 Subject: [PATCH 3/4] MdePkg/DxeRngLib: Use PcdEnforceSecureRngAlgorithms for default algorithm Use PcdEnforceSecureRngAlgorithms to allow using the Rng protocol with the default algorithm. All previous call to the Rng protocol are requesting a secure Rng algorithm. Not specifying the Rng algorithm GUID to use is considered unsecure. Signed-off-by: Pierre Gondois --- MdePkg/Library/DxeRngLib/DxeRngLib.c | 12 +++++++----- MdePkg/Library/DxeRngLib/DxeRngLib.inf | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/MdePkg/Library/DxeRngLib/DxeRngLib.c b/MdePkg/Library/DxeRngLib/DxeRngLib.c index 4b4efef0b424..17c932d802c7 100644 --- a/MdePkg/Library/DxeRngLib/DxeRngLib.c +++ b/MdePkg/Library/DxeRngLib/DxeRngLib.c @@ -197,11 +197,13 @@ GenerateRandomNumberViaNist800Algorithm ( } } - // If all the other methods have failed, use the default method from the RngProtocol - Status = mRngProtocol->GetRNG (mRngProtocol, NULL, BufferSize, Buffer); - DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm default - Status = %r\n", __func__, Status)); - if (!EFI_ERROR (Status)) { - return Status; + if (!PcdGetBool (PcdEnforceSecureRngAlgorithms)) { + // If all the other methods have failed, use the default method from the RngProtocol + Status = mRngProtocol->GetRNG (mRngProtocol, NULL, BufferSize, Buffer); + DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm default - Status = %r\n", __func__, Status)); + if (!EFI_ERROR (Status)) { + return Status; + } } // If we get to this point, we have failed diff --git a/MdePkg/Library/DxeRngLib/DxeRngLib.inf b/MdePkg/Library/DxeRngLib/DxeRngLib.inf index ca649585d4cf..0eff20d98886 100644 --- a/MdePkg/Library/DxeRngLib/DxeRngLib.inf +++ b/MdePkg/Library/DxeRngLib/DxeRngLib.inf @@ -39,3 +39,6 @@ gEfiRngAlgorithmSp80090Hash256Guid gEfiRngAlgorithmSp80090Hmac256Guid gEfiRngAlgorithmRaw + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES From 066da6bd6625afdd5a2a37f9efc6a24be498ef71 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Fri, 30 Aug 2024 13:42:52 +0200 Subject: [PATCH 4/4] MdePkg/DxeRngLib: Add gEfiRngAlgorithmArmRndr to the secure algorithms DxeRngLib iterates over a list of secure algorithms before trying to use the default algorithm provided by the Rng protocol. Add gEfiRngAlgorithmArmRndr to this list. The algorithm represented by this GUID is a secure DRBG of an unknown type, implemented by the aarch64 RNDR instruction. On AARCH64 platform, use the RNDR instruction as the first option if it is available. Signed-off-by: Pierre Gondois --- MdePkg/Library/DxeRngLib/DxeRngLib.c | 7 +++++++ MdePkg/Library/DxeRngLib/DxeRngLib.inf | 3 +++ 2 files changed, 10 insertions(+) diff --git a/MdePkg/Library/DxeRngLib/DxeRngLib.c b/MdePkg/Library/DxeRngLib/DxeRngLib.c index 17c932d802c7..3092d3ebcf80 100644 --- a/MdePkg/Library/DxeRngLib/DxeRngLib.c +++ b/MdePkg/Library/DxeRngLib/DxeRngLib.c @@ -33,6 +33,13 @@ typedef struct { // the RNG protocol and are generally considered secure. // GLOBAL_REMOVE_IF_UNREFERENCED SECURE_RNG_ALGO_ARRAY mSecureHashAlgorithms[] = { + #ifdef MDE_CPU_AARCH64 + { + &gEfiRngAlgorithmArmRndr, // unspecified SP800-90A DRBG (through RNDR instr.) + "ARM-RNDR", + FALSE, + }, + #endif { &gEfiRngAlgorithmSp80090Ctr256Guid, // SP800-90A DRBG CTR using AES-256 "DRBG-CTR", diff --git a/MdePkg/Library/DxeRngLib/DxeRngLib.inf b/MdePkg/Library/DxeRngLib/DxeRngLib.inf index 0eff20d98886..f430b12586eb 100644 --- a/MdePkg/Library/DxeRngLib/DxeRngLib.inf +++ b/MdePkg/Library/DxeRngLib/DxeRngLib.inf @@ -40,5 +40,8 @@ gEfiRngAlgorithmSp80090Hmac256Guid gEfiRngAlgorithmRaw +[Guids.AARCH64] + gEfiRngAlgorithmArmRndr + [FixedPcd] gEfiMdePkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES