From f4d4ea48518d3a9ba84170f35c77863037156f56 Mon Sep 17 00:00:00 2001 From: Girish Mahadevan Date: Wed, 11 Sep 2024 18:58:53 +0000 Subject: [PATCH] feat: add new rnglib Add a new RngLib that will try to get an RNG from the ARM TRNG Library or falls back to the timer-based library if the TRNG service isn't implemented in ATF. Signed-off-by: Girish Mahadevan Reviewed-by: Jeff Brasen Reviewed-by: Jake Garver Tested-by: Jake Garver --- Platform/NVIDIA/Jetson/Jetson.defconfig | 1 + .../NVIDIA/JetsonMinimal/Jetson.defconfig | 1 + Platform/NVIDIA/Kconfig | 16 ++ Platform/NVIDIA/NVIDIA.common.dsc.inc | 7 + Platform/NVIDIA/Server/Server.defconfig | 1 + Platform/NVIDIA/ServerIgx/ServerIgx.defconfig | 1 + Silicon/NVIDIA/Library/NvRngLib/NvRngLib.c | 128 +++++++++ Silicon/NVIDIA/Library/NvRngLib/NvRngLib.inf | 50 ++++ Silicon/NVIDIA/Library/NvRngLib/NvRngLib.uni | 14 + Silicon/NVIDIA/Library/NvRngLib/NvRngLibHw.c | 250 ++++++++++++++++++ .../NVIDIA/Library/NvRngLib/NvRngLibNonHw.c | 241 +++++++++++++++++ Silicon/NVIDIA/Library/NvRngLib/NvRngProto.h | 71 +++++ 12 files changed, 781 insertions(+) create mode 100644 Silicon/NVIDIA/Library/NvRngLib/NvRngLib.c create mode 100644 Silicon/NVIDIA/Library/NvRngLib/NvRngLib.inf create mode 100644 Silicon/NVIDIA/Library/NvRngLib/NvRngLib.uni create mode 100644 Silicon/NVIDIA/Library/NvRngLib/NvRngLibHw.c create mode 100644 Silicon/NVIDIA/Library/NvRngLib/NvRngLibNonHw.c create mode 100644 Silicon/NVIDIA/Library/NvRngLib/NvRngProto.h diff --git a/Platform/NVIDIA/Jetson/Jetson.defconfig b/Platform/NVIDIA/Jetson/Jetson.defconfig index 167f0597e4..c7c42b3e30 100644 --- a/Platform/NVIDIA/Jetson/Jetson.defconfig +++ b/Platform/NVIDIA/Jetson/Jetson.defconfig @@ -33,3 +33,4 @@ CONFIG_SECURITY_UEFI_MENU_USER_AUTH=y CONFIG_EHCI=y CONFIG_SECURITY_PHYSICAL_PRESENCE=y CONFIG_SECURITY_DISABLE_PHYSICAL_PRESENCE_POST_SECUREBOOT=y +CONFIG_SECURITY_HW_RNG=y diff --git a/Platform/NVIDIA/JetsonMinimal/Jetson.defconfig b/Platform/NVIDIA/JetsonMinimal/Jetson.defconfig index 1ab71d34fd..4d40d1611e 100644 --- a/Platform/NVIDIA/JetsonMinimal/Jetson.defconfig +++ b/Platform/NVIDIA/JetsonMinimal/Jetson.defconfig @@ -25,3 +25,4 @@ CONFIG_FS_EXT4=y # CONFIG_SHELL is not set CONFIG_SECURITY_PHYSICAL_PRESENCE=y CONFIG_SERIAL_PORT_CONSOLE_TEGRA=y +CONFIG_SECURITY_NON_HW_RNG=y diff --git a/Platform/NVIDIA/Kconfig b/Platform/NVIDIA/Kconfig index 80c4544135..a31f6f16b2 100644 --- a/Platform/NVIDIA/Kconfig +++ b/Platform/NVIDIA/Kconfig @@ -125,6 +125,22 @@ menu "Security options" default y help Support for UEFI Secure Boot verification of third party components. + + choice SECURITY_RNG_TYPE + prompt "UEFI RNG Type" + help + RNG Type. + + config SECURITY_NON_HW_RNG + bool "Unsafe RNG driver not based on HW RNG." + help + RngLib that will use an unsafe upstream Library (BaseRngLibTimerLib). + + config SECURITY_HW_RNG + bool "RNG using ARM TRNG." + help + RngLib that will use ARM TRNG based RNG or fallback to Timer based. + endchoice endmenu menu "Variable options" diff --git a/Platform/NVIDIA/NVIDIA.common.dsc.inc b/Platform/NVIDIA/NVIDIA.common.dsc.inc index 30b9f00e00..084b6e0300 100644 --- a/Platform/NVIDIA/NVIDIA.common.dsc.inc +++ b/Platform/NVIDIA/NVIDIA.common.dsc.inc @@ -237,7 +237,14 @@ CONFIG_ARM_WATCHDOG_INTERRUPT=0 AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf !endif BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +!ifdef CONFIG_SECURITY_HW_RNG + RngLib|Silicon/NVIDIA/Library/NvRngLib/NvRngLib.inf +!endif + +!ifdef CONFIG_SECURITY_NON_HW_RNG RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf +!endif PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf diff --git a/Platform/NVIDIA/Server/Server.defconfig b/Platform/NVIDIA/Server/Server.defconfig index 7ce572a813..472f01c7e3 100644 --- a/Platform/NVIDIA/Server/Server.defconfig +++ b/Platform/NVIDIA/Server/Server.defconfig @@ -35,3 +35,4 @@ CONFIG_SERVER_POWER_CONTROLLERS=y CONFIG_SMBIOS_DYNAMICTABLESPKG=y CONFIG_INFINEON_TPM_FW_UPDATE=y CONFIG_PRM_RAS_CPER_MODULE=y +CONFIG_SECURITY_HW_RNG=y diff --git a/Platform/NVIDIA/ServerIgx/ServerIgx.defconfig b/Platform/NVIDIA/ServerIgx/ServerIgx.defconfig index 4b9b2d303c..b79ec09328 100644 --- a/Platform/NVIDIA/ServerIgx/ServerIgx.defconfig +++ b/Platform/NVIDIA/ServerIgx/ServerIgx.defconfig @@ -36,3 +36,4 @@ CONFIG_SECURITY_UEFI_MENU_USER_AUTH=y CONFIG_EHCI=y CONFIG_SERIAL_PORT_CONSOLE_TEGRA=y CONFIG_SECURITY_PHYSICAL_PRESENCE=y +CONFIG_SECURITY_HW_RNG=y diff --git a/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.c b/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.c new file mode 100644 index 0000000000..6af77c2a42 --- /dev/null +++ b/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.c @@ -0,0 +1,128 @@ +/** @file + Rng Lib that gets the RNG from a secure RNG driver in StMM or from a Non-Safe + Rng Source if MM isn't present. + + SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "NvRngProto.h" + +STATIC NVIDIA_NVRNG_PROTOCOL *RngOps = NULL; + +/** + Generates a 16-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 16-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber16 ( + OUT UINT16 *Rand + ) +{ + return RngOps->NvGetRng16 (Rand); +} + +/** + Generates a 32-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 32-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber32 ( + OUT UINT32 *Rand + ) +{ + return RngOps->NvGetRng32 (Rand); +} + +/** + Generates a 64-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 64-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber64 ( + OUT UINT64 *Rand + ) +{ + return RngOps->NvGetRng64 (Rand); +} + +/** + Generates a 128-bit random number. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 128-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +BOOLEAN +EFIAPI +GetRandomNumber128 ( + OUT UINT64 *Rand + ) +{ + return RngOps->NvGetRng128 (Rand); +} + +/** + Get a GUID identifying the RNG algorithm implementation. + + @param [out] RngGuid If success, contains the GUID identifying + the RNG algorithm implementation. + + @retval EFI_SUCCESS Success. + @retval EFI_UNSUPPORTED Not supported. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +GetRngGuid ( + GUID *RngGuid + ) +{ + return RngOps->NvGetRngGuid (RngGuid); +} + +EFI_STATUS +EFIAPI +NvRngLibConstructor ( + VOID + ) +{ + RngOps = HwRngGetOps (); + if (RngOps == NULL) { + RngOps = NonHwRngGetOps (); + DEBUG ((DEBUG_ERROR, "%a: No StMM Using NonHW RngLib\n", __FUNCTION__)); + } else { + DEBUG ((DEBUG_INFO, "%a: Using HW RngLib\n", __FUNCTION__)); + } + + return EFI_SUCCESS; +} diff --git a/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.inf b/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.inf new file mode 100644 index 0000000000..56240bedb4 --- /dev/null +++ b/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.inf @@ -0,0 +1,50 @@ +## @file +# Rng Lib that gets the RNG from a secure RNG driver in StMM or from a Non-Safe +# Rng Source if MM isn't present. +# +# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010029 + BASE_NAME = NvRngLib + MODULE_UNI_FILE = NvRngLib.uni + FILE_GUID = 979ff860-9401-4757-b990-1f2a43b8aaab + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + CONSTRUCTOR = NvRngLibConstructor + LIBRARY_CLASS = RngLib + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 EBC +# + +[Sources] + NvRngLib.c + NvRngLibHw.c + NvRngLibNonHw.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/NVIDIA/NVIDIA.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + UefiBootServicesTableLib + DebugLib + ArmTrngLib + +[Protocols] + +[Guids] + gEdkiiRngAlgorithmUnSafe + gEfiRngAlgorithmRaw + +[Depex] + TRUE diff --git a/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.uni b/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.uni new file mode 100644 index 0000000000..97be00693a --- /dev/null +++ b/Silicon/NVIDIA/Library/NvRngLib/NvRngLib.uni @@ -0,0 +1,14 @@ +// /** @file +// Null Instance of RNG (Random Number Generator) Library. +// +// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "NVIDIA's instance of RNG Library" + +#string STR_MODULE_DESCRIPTION #language en-US "This library instance should be used with modules that inherit an (indirect) dependency on the RngLib class, but never actually call RngLib APIs for consuming randomness." + diff --git a/Silicon/NVIDIA/Library/NvRngLib/NvRngLibHw.c b/Silicon/NVIDIA/Library/NvRngLib/NvRngLibHw.c new file mode 100644 index 0000000000..cc01875805 --- /dev/null +++ b/Silicon/NVIDIA/Library/NvRngLib/NvRngLibHw.c @@ -0,0 +1,250 @@ +/** @file + Random number generator that gets the RNG via the ARM TrngLib. + + SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "Base.h" +#include "NvRngProto.h" +#include "ProcessorBind.h" +#include "Uefi/UefiBaseType.h" +#include + +STATIC NVIDIA_NVRNG_PROTOCOL HwRngOps; + +/** + Generate high-quality entropy source using a TRNG or through RDRAND. + + @param[in] Length Size of the buffer, in bytes, to fill with. + @param[out] Entropy Pointer to the buffer to store the entropy data. + + @retval RETURN_SUCCESS The function completed successfully. + @retval RETURN_INVALID_PARAMETER Invalid parameter. + @retval RETURN_UNSUPPORTED Function not implemented. + @retval RETURN_BAD_BUFFER_SIZE Buffer size is too small. + @retval RETURN_NOT_READY No Entropy available. +**/ +STATIC +EFI_STATUS +EFIAPI +GenerateEntropy ( + IN UINTN Length, + OUT UINT8 *Entropy + ) +{ + EFI_STATUS Status; + UINTN CollectedEntropyBits; + UINTN RequiredEntropyBits; + UINTN EntropyBits; + UINTN Index; + UINTN MaxBits; + + ZeroMem (Entropy, Length); + + RequiredEntropyBits = (Length << 3); + Index = 0; + CollectedEntropyBits = 0; + MaxBits = GetArmTrngMaxSupportedEntropyBits (); + Status = RETURN_NOT_READY; + while (CollectedEntropyBits < RequiredEntropyBits) { + EntropyBits = MIN ((RequiredEntropyBits - CollectedEntropyBits), MaxBits); + Status = GetArmTrngEntropy ( + EntropyBits, + (Length - Index), + &Entropy[Index] + ); + if (EFI_ERROR (Status)) { + // Discard the collected bits. + ZeroMem (Entropy, Length); + return Status; + } + + CollectedEntropyBits += EntropyBits; + Index += (EntropyBits >> 3); + } // while + + return Status; +} + +/** + Get a 16-bit random number from the RNG driver in StMM. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 16-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +HwGetRandomNumber16 ( + OUT UINT16 *Rand + ) +{ + EFI_STATUS Status; + UINT8 *RndPtr; + BOOLEAN Ret; + + ASSERT (Rand != NULL); + RndPtr = (UINT8 *)Rand; + + Ret = TRUE; + Status = GenerateEntropy (sizeof (UINT16), RndPtr); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a Failed to get Entropy %r\n", __FUNCTION__, Status)); + Ret = FALSE; + } + + return Ret; +} + +/** + Get a 32-bit random number from RNG Driver in StMM. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 32-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +HwGetRandomNumber32 ( + OUT UINT32 *Rand + ) +{ + EFI_STATUS Status; + UINT8 *RndPtr; + BOOLEAN Ret; + + ASSERT (Rand != NULL); + RndPtr = (UINT8 *)Rand; + + Ret = TRUE; + Status = GenerateEntropy (sizeof (UINT32), RndPtr); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a Failed to get Entropy %r\n", __FUNCTION__, Status)); + Ret = FALSE; + } + + return Ret; +} + +/** + Get a 64-bit random number from the RNG driver in StMM. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 64-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +HwGetRandomNumber64 ( + OUT UINT64 *Rand + ) +{ + EFI_STATUS Status; + UINT8 *RndPtr; + BOOLEAN Ret; + + ASSERT (Rand != NULL); + RndPtr = (UINT8 *)Rand; + + Ret = TRUE; + Status = GenerateEntropy (sizeof (UINT64), RndPtr); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a Failed to get Entropy %r\n", __FUNCTION__, Status)); + Ret = FALSE; + } + + return Ret; +} + +/** + Get 128-bit random number from RNG driver in StMM. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 128-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +HwGetRandomNumber128 ( + OUT UINT64 *Rand + ) +{ + ASSERT (Rand != NULL); + + if (!HwGetRandomNumber64 (Rand)) { + return FALSE; + } + + return HwGetRandomNumber64 (++Rand); +} + +/** + Get a GUID identifying the RNG algorithm implementated by NVRNG IP. + + @param [out] RngGuid RNG algorithm implementation. + + @retval EFI_SUCCESS Success. + EFI_INVALID_PARAMETER Null Parameter value. +**/ +STATIC +EFI_STATUS +HwGetRngGuid ( + GUID *RngGuid + ) +{ + if (RngGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + CopyGuid (RngGuid, &gEfiRngAlgorithmRaw); + return EFI_SUCCESS; +} + +/** + * Get the Rng Ops if using the StMM based RNG Driver. + * + * @param[in] None. + * + * @retval Pointer to RNG Ops on success. + * NULL on failure. + **/ +NVIDIA_NVRNG_PROTOCOL * +HwRngGetOps ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 MajorRev; + UINT16 MinorRev; + + Status = GetArmTrngVersion (&MajorRev, &MinorRev); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a %d Failed to get Trng Version %r\n", __FUNCTION__, __LINE__, Status)); + return NULL; + } + + HwRngOps.NvGetRng16 = HwGetRandomNumber16; + HwRngOps.NvGetRng32 = HwGetRandomNumber32; + HwRngOps.NvGetRng64 = HwGetRandomNumber64; + HwRngOps.NvGetRng128 = HwGetRandomNumber128; + HwRngOps.NvGetRngGuid = HwGetRngGuid; + + return &HwRngOps; +} diff --git a/Silicon/NVIDIA/Library/NvRngLib/NvRngLibNonHw.c b/Silicon/NVIDIA/Library/NvRngLib/NvRngLibNonHw.c new file mode 100644 index 0000000000..ea9120977a --- /dev/null +++ b/Silicon/NVIDIA/Library/NvRngLib/NvRngLibNonHw.c @@ -0,0 +1,241 @@ +/** @file + BaseRng Library that uses the TimerLib to provide reasonably random numbers. + Do not use this on a production system. + This is a copy of the Library in BaseRngLibTimerLib + + Copyright (c) 2023, Arm Limited. All rights reserved. + Copyright (c) Microsoft Corporation. + SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "NvRngProto.h" +#include +#include +#include + +STATIC NVIDIA_NVRNG_PROTOCOL NonHwRngOps; +#define DEFAULT_DELAY_TIME_IN_MICROSECONDS 10 + +/** + Using the TimerLib GetPerformanceCounterProperties() we delay + for enough time for the PerformanceCounter to increment. + + If the return value from GetPerformanceCounterProperties (TimerLib) + is zero, this function will return 10 and attempt to assert. + **/ +STATIC +UINT32 +CalculateMinimumDecentDelayInMicroseconds ( + VOID + ) +{ + UINT64 CounterHz; + + // Get the counter properties + CounterHz = GetPerformanceCounterProperties (NULL, NULL); + // Make sure we won't divide by zero + if (CounterHz == 0) { + ASSERT (CounterHz != 0); // Assert so the developer knows something is wrong + return DEFAULT_DELAY_TIME_IN_MICROSECONDS; + } + + // Calculate the minimum delay based on 1.5 microseconds divided by the hertz. + // We calculate the length of a cycle (1/CounterHz) and multiply it by 1.5 microseconds + // This ensures that the performance counter has increased by at least one + return (UINT32)(MAX (DivU64x64Remainder (1500000, CounterHz, NULL), 1)); +} + +/** + Generates a 16-bit random number from a non HW RNG generator. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 16-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +NonHwGetRandomNumber16 ( + OUT UINT16 *Rand + ) +{ + UINT32 Index; + UINT8 *RandPtr; + UINT32 DelayInMicroSeconds; + + ASSERT (Rand != NULL); + + if (Rand == NULL) { + return FALSE; + } + + DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds (); + RandPtr = (UINT8 *)Rand; + // Get 2 bytes of random ish data + for (Index = 0; Index < sizeof (UINT16); Index++) { + *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF); + // Delay to give the performance counter a chance to change + MicroSecondDelay (DelayInMicroSeconds); + RandPtr++; + } + + return TRUE; +} + +/** + Generates a 32-bit random number from a non HW RNG generator. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 32-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +NonHwGetRandomNumber32 ( + OUT UINT32 *Rand + ) +{ + UINT32 Index; + UINT8 *RandPtr; + UINT32 DelayInMicroSeconds; + + ASSERT (Rand != NULL); + + if (NULL == Rand) { + return FALSE; + } + + RandPtr = (UINT8 *)Rand; + DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds (); + // Get 4 bytes of random ish data + for (Index = 0; Index < sizeof (UINT32); Index++) { + *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF); + // Delay to give the performance counter a chance to change + MicroSecondDelay (DelayInMicroSeconds); + RandPtr++; + } + + return TRUE; +} + +/** + Generates a 64-bit random number from a non HW RNG generator. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 64-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +NonHwGetRandomNumber64 ( + OUT UINT64 *Rand + ) +{ + UINT32 Index; + UINT8 *RandPtr; + UINT32 DelayInMicroSeconds; + + ASSERT (Rand != NULL); + + if (NULL == Rand) { + return FALSE; + } + + RandPtr = (UINT8 *)Rand; + DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds (); + // Get 8 bytes of random ish data + for (Index = 0; Index < sizeof (UINT64); Index++) { + *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF); + // Delay to give the performance counter a chance to change + MicroSecondDelay (DelayInMicroSeconds); + RandPtr++; + } + + return TRUE; +} + +/** + Generates a 128-bit random number from a non HW RNG generator. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the 128-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate the random number. + +**/ +STATIC +BOOLEAN +NonHwGetRandomNumber128 ( + OUT UINT64 *Rand + ) +{ + ASSERT (Rand != NULL); + // This should take around 80ms + + // Read first 64 bits + if (!NonHwGetRandomNumber64 (Rand)) { + return FALSE; + } + + // Read second 64 bits + return NonHwGetRandomNumber64 (++Rand); +} + +/** + Get a GUID identifying the RNG algorithm implementation. + + @param [out] RngGuid If success, contains the GUID identifying + the RNG algorithm implementation. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +EFI_STATUS +EFIAPI +NonHwGetRngGuid ( + GUID *RngGuid + ) +{ + if (RngGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + CopyMem (RngGuid, &gEdkiiRngAlgorithmUnSafe, sizeof (*RngGuid)); + return EFI_SUCCESS; +} + +/** + * Get the Rng Ops if using the Unsafe NonHW Rng Generator. + * + * @param[in] None. + * + * @retval Pointer to RNG Ops on success. + * NULL on failure. + **/ +NVIDIA_NVRNG_PROTOCOL * +NonHwRngGetOps ( + VOID + ) +{ + NonHwRngOps.NvGetRng16 = NonHwGetRandomNumber16; + NonHwRngOps.NvGetRng32 = NonHwGetRandomNumber32; + NonHwRngOps.NvGetRng64 = NonHwGetRandomNumber64; + NonHwRngOps.NvGetRng128 = NonHwGetRandomNumber128; + NonHwRngOps.NvGetRngGuid = NonHwGetRngGuid; + + return &NonHwRngOps; +} diff --git a/Silicon/NVIDIA/Library/NvRngLib/NvRngProto.h b/Silicon/NVIDIA/Library/NvRngLib/NvRngProto.h new file mode 100644 index 0000000000..065cec0a30 --- /dev/null +++ b/Silicon/NVIDIA/Library/NvRngLib/NvRngProto.h @@ -0,0 +1,71 @@ +/** @file + Header file defining the RNG ops that both RNG methods can use. + + SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __NVIDIA_NVRNG_PROTOCOL_H__ +#define __NVIDIA_NVRNG_PROTOCOL_H__ + +#include "Base.h" +#include "ProcessorBind.h" +#include "Uefi/UefiBaseType.h" +#include +#include +#include +#include +#include + +typedef struct _NVIDIA_NVRNG_PROTOCOL NVIDIA_NVRNG_PROTOCOL; + +typedef +BOOLEAN +(EFIAPI *GETRNG16)( + IN UINT16 *Rng + ); + +typedef +BOOLEAN +(EFIAPI *GETRNG32)( + IN UINT32 *Rng + ); + +typedef +BOOLEAN +(EFIAPI *GETRNG64)( + IN UINT64 *Rng + ); + +typedef +BOOLEAN +(EFIAPI *GETRNG128)( + IN UINT64 *Rng + ); + +typedef +EFI_STATUS +(EFIAPI *GETRNGGUID)( + OUT GUID *Guid + ); + +struct _NVIDIA_NVRNG_PROTOCOL { + GETRNG16 NvGetRng16; + GETRNG32 NvGetRng32; + GETRNG64 NvGetRng64; + GETRNG128 NvGetRng128; + GETRNGGUID NvGetRngGuid; +}; + +NVIDIA_NVRNG_PROTOCOL * +HwRngGetOps ( + VOID + ); + +NVIDIA_NVRNG_PROTOCOL * +NonHwRngGetOps ( + VOID + ); + +#endif