[PATCH] UefiPayloadPkg: Add RNG support


Patrick Rudolph
 

Uses the RDRAND instruction if available and install EfiRngProtocol.
The protocol may be used by iPXE or the Linux kernel to gather entropy.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
UefiPayloadPkg/Library/BaseRngLib/BaseRng.c | 199 ++++++++++++++++++++
UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf | 32 ++++
UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni | 17 ++
UefiPayloadPkg/UefiPayloadPkg.dsc | 8 +
UefiPayloadPkg/UefiPayloadPkg.fdf | 4 +
5 files changed, 260 insertions(+)

diff --git a/UefiPayloadPkg/Library/BaseRngLib/BaseRng.c b/UefiPayloadPkg/L=
ibrary/BaseRngLib/BaseRng.c
new file mode 100644
index 0000000000..1fe9e1dbe0
--- /dev/null
+++ b/UefiPayloadPkg/Library/BaseRngLib/BaseRng.c
@@ -0,0 +1,199 @@
+/** @file=0D
+ Random number generator services that uses RdRand instruction access=0D
+ to provide high-quality random numbers.=0D
+=0D
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Register/Intel/Cpuid.h>=0D
+=0D
+STATIC BOOLEAN mHasRdRand;=0D
+=0D
+//=0D
+// Bit mask used to determine if RdRand instruction is supported.=0D
+//=0D
+#define RDRAND_MASK BIT30=0D
+=0D
+//=0D
+// Limited retry number when valid random data is returned.=0D
+// Uses the recommended value defined in Section 7.3.17 of "Intel 64 and I=
A-32=0D
+// Architectures Software Developer's Mannual".=0D
+//=0D
+#define RDRAND_RETRY_LIMIT 10=0D
+=0D
+/**=0D
+ The constructor function checks whether or not RDRAND instruction is sup=
ported=0D
+ by the host hardware.=0D
+=0D
+ The constructor function checks whether or not RDRAND instruction is sup=
ported.=0D
+ It will always return RETURN_SUCCESS.=0D
+=0D
+ @retval RETURN_SUCCESS The constructor always returns EFI_SUCCESS.=0D
+=0D
+**/=0D
+RETURN_STATUS=0D
+EFIAPI=0D
+BaseRngLibConstructor (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINT32 RegEax;=0D
+ UINT32 RegEcx;=0D
+=0D
+ AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL);=0D
+ if (RegEax < 1) {=0D
+ mHasRdRand =3D FALSE;=0D
+ return RETURN_SUCCESS;=0D
+ }=0D
+=0D
+ //=0D
+ // Determine RDRAND support by examining bit 30 of the ECX register retu=
rned by=0D
+ // CPUID. A value of 1 indicates that processor support RDRAND instructi=
on.=0D
+ //=0D
+ AsmCpuid (CPUID_VERSION_INFO, 0, 0, &RegEcx, 0);=0D
+=0D
+ mHasRdRand =3D ((RegEcx & RDRAND_MASK) =3D=3D RDRAND_MASK);=0D
+=0D
+ return RETURN_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Generates a 16-bit random number.=0D
+=0D
+ if Rand is NULL, then ASSERT().=0D
+=0D
+ @param[out] Rand Buffer pointer to store the 16-bit random value.=0D
+=0D
+ @retval TRUE Random number generated successfully.=0D
+ @retval FALSE Failed to generate the random number.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+GetRandomNumber16 (=0D
+ OUT UINT16 *Rand=0D
+ )=0D
+{=0D
+ UINT32 Index;=0D
+=0D
+ ASSERT (Rand !=3D NULL);=0D
+=0D
+ if (mHasRdRand) {=0D
+ //=0D
+ // A loop to fetch a 16 bit random value with a retry count limit.=0D
+ //=0D
+ for (Index =3D 0; Index < RDRAND_RETRY_LIMIT; Index++) {=0D
+ if (AsmRdRand16 (Rand)) {=0D
+ return TRUE;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return FALSE;=0D
+}=0D
+=0D
+/**=0D
+ Generates a 32-bit random number.=0D
+=0D
+ if Rand is NULL, then ASSERT().=0D
+=0D
+ @param[out] Rand Buffer pointer to store the 32-bit random value.=0D
+=0D
+ @retval TRUE Random number generated successfully.=0D
+ @retval FALSE Failed to generate the random number.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+GetRandomNumber32 (=0D
+ OUT UINT32 *Rand=0D
+ )=0D
+{=0D
+ UINT32 Index;=0D
+=0D
+ ASSERT (Rand !=3D NULL);=0D
+=0D
+ if (mHasRdRand) {=0D
+ //=0D
+ // A loop to fetch a 32 bit random value with a retry count limit.=0D
+ //=0D
+ for (Index =3D 0; Index < RDRAND_RETRY_LIMIT; Index++) {=0D
+ if (AsmRdRand32 (Rand)) {=0D
+ return TRUE;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return FALSE;=0D
+}=0D
+=0D
+/**=0D
+ Generates a 64-bit random number.=0D
+=0D
+ if Rand is NULL, then ASSERT().=0D
+=0D
+ @param[out] Rand Buffer pointer to store the 64-bit random value.=0D
+=0D
+ @retval TRUE Random number generated successfully.=0D
+ @retval FALSE Failed to generate the random number.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+GetRandomNumber64 (=0D
+ OUT UINT64 *Rand=0D
+ )=0D
+{=0D
+ UINT32 Index;=0D
+=0D
+ ASSERT (Rand !=3D NULL);=0D
+=0D
+ if (mHasRdRand) {=0D
+ //=0D
+ // A loop to fetch a 64 bit random value with a retry count limit.=0D
+ //=0D
+ for (Index =3D 0; Index < RDRAND_RETRY_LIMIT; Index++) {=0D
+ if (AsmRdRand64 (Rand)) {=0D
+ return TRUE;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return FALSE;=0D
+}=0D
+=0D
+/**=0D
+ Generates a 128-bit random number.=0D
+=0D
+ if Rand is NULL, then ASSERT().=0D
+=0D
+ @param[out] Rand Buffer pointer to store the 128-bit random value.=0D
+=0D
+ @retval TRUE Random number generated successfully.=0D
+ @retval FALSE Failed to generate the random number.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+GetRandomNumber128 (=0D
+ OUT UINT64 *Rand=0D
+ )=0D
+{=0D
+ ASSERT (Rand !=3D NULL);=0D
+=0D
+ //=0D
+ // Read first 64 bits=0D
+ //=0D
+ if (!GetRandomNumber64 (Rand)) {=0D
+ return FALSE;=0D
+ }=0D
+=0D
+ //=0D
+ // Read second 64 bits=0D
+ //=0D
+ return GetRandomNumber64 (++Rand);=0D
+}=0D
diff --git a/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf b/UefiPayload=
Pkg/Library/BaseRngLib/BaseRngLib.inf
new file mode 100644
index 0000000000..67a91ccfff
--- /dev/null
+++ b/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf
@@ -0,0 +1,32 @@
+## @file=0D
+# Instance of RNG (Random Number Generator) Library.=0D
+#=0D
+# Copyright (c) 2020 9elements Agency GmbH.<BR>=0D
+#=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D BaseRngLib=0D
+ MODULE_UNI_FILE =3D BaseRngLib.uni=0D
+ FILE_GUID =3D 05C48431-DE18-4550-931A-3350E8551498=
=0D
+ MODULE_TYPE =3D BASE=0D
+ VERSION_STRING =3D 1.0=0D
+ LIBRARY_CLASS =3D RngLib=0D
+ CONSTRUCTOR =3D BaseRngLibConstructor=0D
+=0D
+#=0D
+# VALID_ARCHITECTURES =3D IA32 X64=0D
+#=0D
+=0D
+[Sources.Ia32, Sources.X64]=0D
+ BaseRng.c=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+=0D
+[LibraryClasses]=0D
+ BaseLib=0D
+ DebugLib=0D
diff --git a/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni b/UefiPayload=
Pkg/Library/BaseRngLib/BaseRngLib.uni
new file mode 100644
index 0000000000..f3ed954c52
--- /dev/null
+++ b/UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni
@@ -0,0 +1,17 @@
+// /** @file=0D
+// Instance of RNG (Random Number Generator) Library.=0D
+//=0D
+// BaseRng Library that uses CPU RdRand instruction access to provide=0D
+// high-quality random numbers.=0D
+//=0D
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG L=
ibrary"=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library t=
hat uses CPU RdRand instruction access to provide high-quality random numbe=
rs"=0D
+=0D
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayload=
Pkg.dsc
index ae62a9c4d6..78a475ea02 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -494,6 +494,14 @@
!endif=0D
UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf=0D
=0D
+ #=0D
+ # Random Number Generator=0D
+ #=0D
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf {=0D
+ <LibraryClasses>=0D
+ RngLib|UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf=0D
+ }=0D
+=0D
#------------------------------=0D
# Build the shell=0D
#------------------------------=0D
diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayload=
Pkg.fdf
index a97ace7395..57c06c8621 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.fdf
+++ b/UefiPayloadPkg/UefiPayloadPkg.fdf
@@ -169,6 +169,10 @@ INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf=0D
INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf=0D
=0D
+#=0D
+# Random Number Generator=0D
+#=0D
+INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf=0D
=0D
#=0D
# Shell=0D
--=20
2.26.2

Join devel@edk2.groups.io to automatically receive all group messages.