diff --git a/UefiPayloadPkg/Library/BaseRngLib/BaseRng.c b/UefiPayloadPkg/Library/BaseRngLib/BaseRng.c new file mode 100644 index 0000000000..1fe9e1dbe0 --- /dev/null +++ b/UefiPayloadPkg/Library/BaseRngLib/BaseRng.c @@ -0,0 +1,199 @@ +/** @file + Random number generator services that uses RdRand instruction access + to provide high-quality random numbers. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +STATIC BOOLEAN mHasRdRand; + +// +// Bit mask used to determine if RdRand instruction is supported. +// +#define RDRAND_MASK BIT30 + +// +// Limited retry number when valid random data is returned. +// Uses the recommended value defined in Section 7.3.17 of "Intel 64 and IA-32 +// Architectures Software Developer's Mannual". +// +#define RDRAND_RETRY_LIMIT 10 + +/** + The constructor function checks whether or not RDRAND instruction is supported + by the host hardware. + + The constructor function checks whether or not RDRAND instruction is supported. + It will always return RETURN_SUCCESS. + + @retval RETURN_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +BaseRngLibConstructor ( + VOID + ) +{ + UINT32 RegEax; + UINT32 RegEcx; + + AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL); + if (RegEax < 1) { + mHasRdRand = FALSE; + return RETURN_SUCCESS; + } + + // + // Determine RDRAND support by examining bit 30 of the ECX register returned by + // CPUID. A value of 1 indicates that processor support RDRAND instruction. + // + AsmCpuid (CPUID_VERSION_INFO, 0, 0, &RegEcx, 0); + + mHasRdRand = ((RegEcx & RDRAND_MASK) == RDRAND_MASK); + + return RETURN_SUCCESS; +} + +/** + 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 + ) +{ + UINT32 Index; + + ASSERT (Rand != NULL); + + if (mHasRdRand) { + // + // A loop to fetch a 16 bit random value with a retry count limit. + // + for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) { + if (AsmRdRand16 (Rand)) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + 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 + ) +{ + UINT32 Index; + + ASSERT (Rand != NULL); + + if (mHasRdRand) { + // + // A loop to fetch a 32 bit random value with a retry count limit. + // + for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) { + if (AsmRdRand32 (Rand)) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + 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 + ) +{ + UINT32 Index; + + ASSERT (Rand != NULL); + + if (mHasRdRand) { + // + // A loop to fetch a 64 bit random value with a retry count limit. + // + for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) { + if (AsmRdRand64 (Rand)) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + 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 + ) +{ + ASSERT (Rand != NULL); + + // + // Read first 64 bits + // + if (!GetRandomNumber64 (Rand)) { + return FALSE; + } + + // + // Read second 64 bits + // + return GetRandomNumber64 (++Rand); +} diff --git a/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf b/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf new file mode 100644 index 0000000000..67a91ccfff --- /dev/null +++ b/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf @@ -0,0 +1,32 @@ +## @file +# Instance of RNG (Random Number Generator) Library. +# +# Copyright (c) 2020 9elements Agency GmbH.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseRngLib + MODULE_UNI_FILE = BaseRngLib.uni + FILE_GUID = 05C48431-DE18-4550-931A-3350E8551498 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RngLib + CONSTRUCTOR = BaseRngLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.Ia32, Sources.X64] + BaseRng.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib diff --git a/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni b/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni new file mode 100644 index 0000000000..f3ed954c52 --- /dev/null +++ b/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of RNG (Random Number Generator) Library. +// +// BaseRng Library that uses CPU RdRand instruction access to provide +// high-quality random numbers. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG Library" + +#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses CPU RdRand instruction access to provide high-quality random numbers" + diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index fb6ec5206d..b04dcf263f 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -559,6 +559,14 @@ !endif UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf + # + # Random Number Generator + # + SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf { + + RngLib|UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf + } + #------------------------------ # Build the shell #------------------------------ diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf index 81a4e52841..75a19839e5 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.fdf +++ b/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -213,6 +213,10 @@ INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf # INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf +# Random Number Generator +# +INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf + # # Shell #