UefiPayloadPkg: Add RNG support
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>
This commit is contained in:
		
				
					committed by
					
						
						Tim Crawford
					
				
			
			
				
	
			
			
			
						parent
						
							95c492569f
						
					
				
				
					commit
					69ae47ba5d
				
			
							
								
								
									
										199
									
								
								UefiPayloadPkg/Library/BaseRngLib/BaseRng.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								UefiPayloadPkg/Library/BaseRngLib/BaseRng.c
									
									
									
									
									
										Normal file
									
								
							@@ -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.<BR>
 | 
			
		||||
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
			
		||||
 | 
			
		||||
**/
 | 
			
		||||
 | 
			
		||||
#include <Library/BaseLib.h>
 | 
			
		||||
#include <Library/DebugLib.h>
 | 
			
		||||
#include <Register/Intel/Cpuid.h>
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
## @file
 | 
			
		||||
#  Instance of RNG (Random Number Generator) Library.
 | 
			
		||||
#
 | 
			
		||||
#  Copyright (c) 2020 9elements Agency GmbH.<BR>
 | 
			
		||||
#
 | 
			
		||||
#  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
 | 
			
		||||
							
								
								
									
										17
									
								
								UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.uni
									
									
									
									
									
										Normal file
									
								
							@@ -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.<BR>
 | 
			
		||||
//
 | 
			
		||||
// 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"
 | 
			
		||||
 | 
			
		||||
@@ -559,6 +559,14 @@
 | 
			
		||||
!endif
 | 
			
		||||
  UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
 | 
			
		||||
 | 
			
		||||
  #
 | 
			
		||||
  # Random Number Generator
 | 
			
		||||
  #
 | 
			
		||||
  SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf {
 | 
			
		||||
      <LibraryClasses>
 | 
			
		||||
      RngLib|UefiPayloadPkg/Library/BaseRngLib/BaseRngLib.inf
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #------------------------------
 | 
			
		||||
  #  Build the shell
 | 
			
		||||
  #------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
#
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user