Jonathan Doman
2015-06-19 17:47:58 UTC
Separate out the low-level random data read code from RngDxe and move
into new RandLib, including IA32 and X64 directories.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jonathan Doman <***@hp.com>
---
SecurityPkg/Include/Library/RandLib.h | 50 +++++
SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm | 67 ++++++
SecurityPkg/Library/RandLib/IA32/GccRdRand.c | 69 ++++++
SecurityPkg/Library/RandLib/IA32/RdRandWord.c | 104 +++++++++
SecurityPkg/Library/RandLib/RandLib.inf | 53 +++++
SecurityPkg/Library/RandLib/RdRand.c | 284 +++++++++++++++++++++++++
SecurityPkg/Library/RandLib/RdRand.h | 166 +++++++++++++++
SecurityPkg/Library/RandLib/X64/AsmRdRand.asm | 83 ++++++++
SecurityPkg/Library/RandLib/X64/GccRdRand.c | 95 +++++++++
SecurityPkg/Library/RandLib/X64/RdRandWord.c | 70 ++++++
SecurityPkg/SecurityPkg.dec | 3 +
SecurityPkg/SecurityPkg.dsc | 1 +
12 files changed, 1045 insertions(+)
create mode 100644 SecurityPkg/Include/Library/RandLib.h
create mode 100644 SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm
create mode 100644 SecurityPkg/Library/RandLib/IA32/GccRdRand.c
create mode 100644 SecurityPkg/Library/RandLib/IA32/RdRandWord.c
create mode 100644 SecurityPkg/Library/RandLib/RandLib.inf
create mode 100644 SecurityPkg/Library/RandLib/RdRand.c
create mode 100644 SecurityPkg/Library/RandLib/RdRand.h
create mode 100644 SecurityPkg/Library/RandLib/X64/AsmRdRand.asm
create mode 100644 SecurityPkg/Library/RandLib/X64/GccRdRand.c
create mode 100644 SecurityPkg/Library/RandLib/X64/RdRandWord.c
diff --git a/SecurityPkg/Include/Library/RandLib.h b/SecurityPkg/Include/Library/RandLib.h
new file mode 100644
index 0000000..f50c10e
--- /dev/null
+++ b/SecurityPkg/Include/Library/RandLib.h
@@ -0,0 +1,50 @@
+/** @file RandLib.h
+
+ Interfaces provided by RandLib to support RngDxe.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef __RAND_LIB_DOT_H__
+#define __RAND_LIB_DOT_H__
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Determines whether or not RDRAND instruction is supported by the host hardware.
+
+ @retval EFI_SUCCESS RDRAND instruction supported.
+ @retval EFI_UNSUPPORTED RDRAND instruction not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+IsRdRandSupported (
+ VOID
+ );
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ );
+
+#endif /* __RAND_LIB_DOT_H__ */
diff --git a/SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm b/SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm
new file mode 100644
index 0000000..37b3830
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm
@@ -0,0 +1,67 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+; AsmRdRand.Asm
+;
+; Abstract:
+;
+; Implementation for 16-, and 32- invocations of RDRAND instruction under 32bit platform.
+;
+; Notes:
+;
+; Visual Studio coding practices do not use inline asm since multiple compilers and
+; architectures are supported assembler not recognizing rdrand instruction so using DB's.
+;
+;------------------------------------------------------------------------------
+
+ .586P
+ .model flat, C
+ .code
+
+;------------------------------------------------------------------------------
+; Generate a 16 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand16Step (UINT16 *Rand); ECX
+;------------------------------------------------------------------------------
+RdRand16Step PROC
+ ; rdrand ax ; generate a 16 bit RN into ax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r16: "0f c7 /6 ModRM:r/m(w)"
+ jb rn16_ok ; jmp if CF=1
+ xor eax, eax ; reg=0 if CF=0
+ ret ; return with failure status
+rn16_ok:
+ mov [ecx], ax
+ mov eax, 1
+ ret
+RdRand16Step ENDP
+
+;------------------------------------------------------------------------------
+; Generate a 32 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand32Step (UINT32 *Rand); ECX
+;------------------------------------------------------------------------------
+RdRand32Step PROC
+ ; rdrand eax ; generate a 32 bit RN into eax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r32: "0f c7 /6 ModRM:r/m(w)"
+ jb rn32_ok ; jmp if CF=1
+ xor eax, eax ; reg=0 if CF=0
+ ret ; return with failure status
+rn32_ok:
+ mov [ecx], eax
+ mov eax, 1
+ ret
+RdRand32Step ENDP
+
+ END
diff --git a/SecurityPkg/Library/RandLib/IA32/GccRdRand.c b/SecurityPkg/Library/RandLib/IA32/GccRdRand.c
new file mode 100644
index 0000000..f42302a
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/IA32/GccRdRand.c
@@ -0,0 +1,69 @@
+/** @file
+ RDRAND Support Routines for GCC environment.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+/**
+ Generates a 16-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand16Step (
+ OUT UINT16 *Rand
+ )
+{
+ UINT8 Carry;
+
+ //
+ // Uses byte code for RDRAND instruction,
+ // in case that GCC version has no direct support on RDRAND assembly.
+ //
+ __asm__ __volatile__ (
+ ".byte 0x66; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
+
+/**
+ Generates a 32-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand32Step (
+ OUT UINT32 *Rand
+ )
+{
+ UINT8 Carry;
+
+ __asm__ __volatile__ (
+ ".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/RandLib/IA32/RdRandWord.c b/SecurityPkg/Library/RandLib/IA32/RdRandWord.c
new file mode 100644
index 0000000..125c53b
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/IA32/RdRandWord.c
@@ -0,0 +1,104 @@
+/** @file
+ RDRAND Support Routines.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RdRand.h"
+
+/**
+ Generates a 64-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand64Step (
+ OUT UINT64 *Rand
+ )
+{
+ UINT32 RandLow;
+ UINT32 RandHigh;
+
+ //
+ // Generating a 64-bit rand on a 32-bit system by
+ // mapping two 32-bit RDRAND instructions.
+ //
+ if (!RdRand32Step (&RandLow)) {
+ return FALSE;
+ }
+ if (!RdRand32Step (&RandHigh)) {
+ return FALSE;
+ }
+
+ *Rand = (UINT64) RandLow | LShiftU64 ((UINT64)RandHigh, 32);
+
+ return TRUE;
+}
+
+/**
+ Calls RDRAND to request a word-length random number.
+
+ @param[out] Rand Buffer pointer to store the random number.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS Random word generation succeeded.
+ @retval EFI_NOT_READY Failed to request random word.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandWord (
+ OUT UINTN *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ return RdRand32 (Rand, NeedRetry);
+}
+
+/**
+ Calls RDRAND to request multiple word-length random numbers.
+
+ @param[in] Length Size of the buffer, in words, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random words generation succeeded.
+ @retval EFI_NOT_READY Failed to request random words.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetWords (
+ IN UINTN Length,
+ OUT UINTN *RandBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ for (Index = 0; Index < Length; Index++) {
+ //
+ // Obtain one word-length (32-bit) Random Number with possible retry-loop.
+ //
+ Status = RdRand32 (RandBuffer, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RandBuffer++;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/SecurityPkg/Library/RandLib/RandLib.inf b/SecurityPkg/Library/RandLib/RandLib.inf
new file mode 100644
index 0000000..68f5cc7
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/RandLib.inf
@@ -0,0 +1,53 @@
+## @file RandLib.inf
+#
+# Provide rand data using x86 instructions
+#
+# (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IntelRandLib
+ FILE_GUID = D0317815-4036-2FF5-0F56-4990A7B37A6F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RandLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ RdRand.c
+
+[Sources.IA32]
+ IA32/RdRandWord.c
+ IA32/AsmRdRand.asm
+ IA32/GccRdRand.c | GCC
+
+[Sources.X64]
+ X64/RdRandWord.c
+ X64/AsmRdRand.asm
+ X64/GccRdRand.c | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[Depex]
+ TRUE
+
+[BuildOptions]
+ XCODE:*_*_*_CC_FLAGS = -mmmx -msse
+
diff --git a/SecurityPkg/Library/RandLib/RdRand.c b/SecurityPkg/Library/RandLib/RdRand.c
new file mode 100644
index 0000000..3babbc3
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/RdRand.c
@@ -0,0 +1,284 @@
+/** @file
+ Support routines for RDRAND instruction access.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RdRand.h"
+#include <Library/RandLib.h>
+
+
+//
+// Bit mask used to determine if RdRand instruction is supported.
+//
+#define RDRAND_MASK 0x40000000
+
+/**
+ Determines whether or not RDRAND instruction is supported by the host hardware.
+
+ @retval EFI_SUCCESS RDRAND instruction supported.
+ @retval EFI_UNSUPPORTED RDRAND instruction not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+IsRdRandSupported (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+ BOOLEAN IsIntelCpu;
+
+ Status = EFI_UNSUPPORTED;
+ IsIntelCpu = FALSE;
+
+ //
+ // Checks whether the current processor is an Intel product by CPUID.
+ //
+ AsmCpuid (0, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ if ((CompareMem ((CHAR8 *)(&RegEbx), "Genu", 4) == 0) &&
+ (CompareMem ((CHAR8 *)(&RegEdx), "ineI", 4) == 0) &&
+ (CompareMem ((CHAR8 *)(&RegEcx), "ntel", 4) == 0)) {
+ IsIntelCpu = TRUE;
+ }
+
+ if (IsIntelCpu) {
+ //
+ // Determine RDRAND support by examining bit 30 of the ECX register returned by CPUID.
+ // A value of 1 indicates that processor supports RDRAND instruction.
+ //
+ AsmCpuid (1, 0, 0, &RegEcx, 0);
+
+ if ((RegEcx & RDRAND_MASK) == RDRAND_MASK) {
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Calls RDRAND to obtain a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand16 (
+ OUT UINT16 *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ UINT32 Index;
+ UINT32 RetryCount;
+
+ if (NeedRetry) {
+ RetryCount = RETRY_LIMIT;
+ } else {
+ RetryCount = 1;
+ }
+
+ //
+ // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.
+ //
+ for (Index = 0; Index < RetryCount; Index++) {
+ if (RdRand16Step (Rand)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Calls RDRAND to obtain a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand32 (
+ OUT UINT32 *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ UINT32 Index;
+ UINT32 RetryCount;
+
+ if (NeedRetry) {
+ RetryCount = RETRY_LIMIT;
+ } else {
+ RetryCount = 1;
+ }
+
+ //
+ // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.
+ //
+ for (Index = 0; Index < RetryCount; Index++) {
+ if (RdRand32Step (Rand)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Calls RDRAND to obtain a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand64 (
+ OUT UINT64 *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ UINT32 Index;
+ UINT32 RetryCount;
+
+ if (NeedRetry) {
+ RetryCount = RETRY_LIMIT;
+ } else {
+ RetryCount = 1;
+ }
+
+ //
+ // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.
+ //
+ for (Index = 0; Index < RetryCount; Index++) {
+ if (RdRand64Step (Rand)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Start;
+ UINT8 *ResidualStart;
+ UINTN *BlockStart;
+ UINTN TempRand;
+ UINTN Count;
+ UINTN Residual;
+ UINTN StartLen;
+ UINTN BlockNum;
+ UINTN Index;
+
+ ResidualStart = NULL;
+ TempRand = 0;
+
+ //
+ // Compute the address of the first word aligned (32/64-bit) block in the
+ // destination buffer, depending on whether we are in 32- or 64-bit mode.
+ //
+ Start = RandBuffer;
+ if (((UINT32)(UINTN)Start % (UINT32)sizeof(UINTN)) == 0) {
+ BlockStart = (UINTN *)Start;
+ Count = Length;
+ StartLen = 0;
+ } else {
+ BlockStart = (UINTN *)(((UINTN)Start & ~(UINTN)(sizeof(UINTN) - 1)) + (UINTN)sizeof(UINTN));
+ Count = Length - (sizeof (UINTN) - (UINT32)((UINTN)Start % sizeof (UINTN)));
+ StartLen = (UINT32)((UINTN)BlockStart - (UINTN)Start);
+ }
+
+ //
+ // Compute the number of word blocks and the remaining number of bytes.
+ //
+ Residual = Count % sizeof (UINTN);
+ BlockNum = Count / sizeof (UINTN);
+ if (Residual != 0) {
+ ResidualStart = (UINT8 *) (BlockStart + BlockNum);
+ }
+
+ //
+ // Obtain a temporary random number for use in the residuals. Failout if retry fails.
+ //
+ if (StartLen > 0) {
+ Status = RdRandWord ((UINTN *) &TempRand, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Populate the starting mis-aligned block.
+ //
+ for (Index = 0; Index < StartLen; Index++) {
+ Start[Index] = (UINT8)(TempRand & 0xff);
+ TempRand = TempRand >> 8;
+ }
+
+ //
+ // Populate the central aligned block. Fail out if retry fails.
+ //
+ Status = RdRandGetWords (BlockNum, (UINTN *)(BlockStart));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Populate the final mis-aligned block.
+ //
+ if (Residual > 0) {
+ Status = RdRandWord ((UINTN *)&TempRand, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ for (Index = 0; Index < Residual; Index++) {
+ ResidualStart[Index] = (UINT8)(TempRand & 0xff);
+ TempRand = TempRand >> 8;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/Library/RandLib/RdRand.h b/SecurityPkg/Library/RandLib/RdRand.h
new file mode 100644
index 0000000..32dfc73
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/RdRand.h
@@ -0,0 +1,166 @@
+/** @file
+ Header for the RDRAND APIs used by RNG DXE driver.
+
+ Support API definitions for RDRAND instruction access, which will leverage
+ Intel Secure Key technology to provide high-quality random numbers for use
+ in applications, or entropy for seeding other random number generators.
+ Refer to http://software.intel.com/en-us/articles/intel-digital-random-number
+ -generator-drng-software-implementation-guide/ for more information about Intel
+ Secure Key technology.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __RD_RAND_H__
+#define __RD_RAND_H__
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Uefi/UefiBaseType.h>
+
+//
+// The maximun number of retries to obtain one available random number.
+//
+#define RETRY_LIMIT 10
+
+/**
+ Generates a 16-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand16Step (
+ OUT UINT16 *Rand
+ );
+
+/**
+ Generates a 32-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand32Step (
+ OUT UINT32 *Rand
+ );
+
+/**
+ Generates a 64-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand64Step (
+ OUT UINT64 *Rand
+ );
+
+/**
+ Calls RDRAND to obtain a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand16 (
+ OUT UINT16 *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to obtain a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand32 (
+ OUT UINT32 *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to obtain a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand64 (
+ OUT UINT64 *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to request a word-length random number.
+
+ @param[out] Rand Buffer pointer to store the random number.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS Random word generation succeeded.
+ @retval EFI_NOT_READY Failed to request random word.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandWord (
+ OUT UINTN *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to request multiple word-length random numbers.
+
+ @param[in] Length Size of the buffer, in words, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random words generation succeeded.
+ @retval EFI_NOT_READY Failed to request random words.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetWords (
+ IN UINTN Length,
+ OUT UINTN *RandBuffer
+ );
+
+#endif // __RD_RAND_H__
diff --git a/SecurityPkg/Library/RandLib/X64/AsmRdRand.asm b/SecurityPkg/Library/RandLib/X64/AsmRdRand.asm
new file mode 100644
index 0000000..8a4fe65
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/X64/AsmRdRand.asm
@@ -0,0 +1,83 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+; AsmRdRand.Asm
+;
+; Abstract:
+;
+; Implementation for 16-, 32-, and 64-bit invocations of RDRAND instruction under 64bit platform.
+;
+; Notes:
+;
+; Visual Studio coding practices do not use inline asm since multiple compilers and
+; architectures are supported assembler not recognizing rdrand instruction so using DB's.
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; Generate a 16 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand16Step (UINT16 *Rand); RCX
+;------------------------------------------------------------------------------
+RdRand16Step PROC
+ ; rdrand ax ; generate a 16 bit RN into ax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r16: "0f c7 /6 ModRM:r/m(w)"
+ jb rn16_ok ; jmp if CF=1
+ xor rax, rax ; reg=0 if CF=0
+ ret ; return with failure status
+rn16_ok:
+ mov [rcx], ax
+ mov rax, 1
+ ret
+RdRand16Step ENDP
+
+;------------------------------------------------------------------------------
+; Generate a 32 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand32Step (UINT32 *Rand); RCX
+;------------------------------------------------------------------------------
+RdRand32Step PROC
+ ; rdrand eax ; generate a 32 bit RN into eax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r32: "0f c7 /6 ModRM:r/m(w)"
+ jb rn32_ok ; jmp if CF=1
+ xor rax, rax ; reg=0 if CF=0
+ ret ; return with failure status
+rn32_ok:
+ mov [rcx], eax
+ mov rax, 1
+ ret
+RdRand32Step ENDP
+
+;------------------------------------------------------------------------------
+; Generate a 64 bit random number
+; Return TRUE if RN generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand64Step (UINT64 *Random); RCX
+;------------------------------------------------------------------------------
+RdRand64Step PROC
+ ; rdrand rax ; generate a 64 bit RN into rax, CF=1 if RN generated ok, otherwise CF=0
+ db 048h, 0fh, 0c7h, 0f0h ; rdrand r64: "REX.W + 0F C7 /6 ModRM:r/m(w)"
+ jb rn64_ok ; jmp if CF=1
+ xor rax, rax ; reg=0 if CF=0
+ ret ; return with failure status
+rn64_ok:
+ mov [rcx], rax
+ mov rax, 1
+ ret
+RdRand64Step ENDP
+
+ END
diff --git a/SecurityPkg/Library/RandLib/X64/GccRdRand.c b/SecurityPkg/Library/RandLib/X64/GccRdRand.c
new file mode 100644
index 0000000..d28336d
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/X64/GccRdRand.c
@@ -0,0 +1,95 @@
+/** @file
+ RDRAND Support Routines for GCC environment.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+/**
+ Generates a 16-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand16Step (
+ OUT UINT16 *Rand
+ )
+{
+ UINT8 Carry;
+
+ //
+ // Uses byte code for RDRAND instruction,
+ // in case that GCC version has no direct support on RDRAND assembly.
+ //
+ __asm__ __volatile__ (
+ ".byte 0x66; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
+
+/**
+ Generates a 32-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand32Step (
+ OUT UINT32 *Rand
+ )
+{
+ UINT8 Carry;
+
+ __asm__ __volatile__ (
+ ".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
+
+/**
+ Generates a 64-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand64Step (
+ OUT UINT64 *Rand
+ )
+{
+ UINT8 Carry;
+
+ __asm__ __volatile__ (
+ ".byte 0x48; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
diff --git a/SecurityPkg/Library/RandLib/X64/RdRandWord.c b/SecurityPkg/Library/RandLib/X64/RdRandWord.c
new file mode 100644
index 0000000..946e5ba
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/X64/RdRandWord.c
@@ -0,0 +1,70 @@
+/** @file
+ RDRAND Support Routines.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RdRand.h"
+
+/**
+ Calls RDRAND to request a word-length random number.
+
+ @param[out] Rand Buffer pointer to store the random number.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS Random word generation succeeded.
+ @retval EFI_NOT_READY Failed to request random word.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandWord (
+ OUT UINTN *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ return RdRand64 (Rand, NeedRetry);
+}
+
+/**
+ Calls RDRAND to request multiple word-length random numbers.
+
+ @param[in] Length Size of the buffer, in words, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random words generation succeeded.
+ @retval EFI_NOT_READY Failed to request random words.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetWords (
+ IN UINTN Length,
+ OUT UINTN *RandBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ for (Index = 0; Index < Length; Index++) {
+ //
+ // Obtain one word-length (64-bit) Random Number with possible retry-loop.
+ //
+ Status = RdRand64 (RandBuffer, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RandBuffer++;
+ }
+
+ return EFI_SUCCESS;
+}
\ No newline at end of file
diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index 25ec7d0..8281deb 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -75,6 +75,9 @@
#
TrEEPpVendorLib|Include/Library/TrEEPpVendorLib.h
+ ## @libraryclass Provides RDRAND.
+ RandLib|Include/Library/RandLib.h
+
[Guids]
## Security package token space guid.
# Include/Guid/SecurityPkgTokenSpace.h
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 35a7a51..26758c3 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -59,6 +59,7 @@
TrEEPhysicalPresenceLib|SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf
TcgPpVendorLib|SecurityPkg/Library/TcgPpVendorLibNull/TcgPpVendorLibNull.inf
TrEEPpVendorLib|SecurityPkg/Library/TrEEPpVendorLibNull/TrEEPpVendorLibNull.inf
+ RandLib|SecurityPkg/Library/RandLib/RandLib.inf
[LibraryClasses.common.PEIM]
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
into new RandLib, including IA32 and X64 directories.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jonathan Doman <***@hp.com>
---
SecurityPkg/Include/Library/RandLib.h | 50 +++++
SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm | 67 ++++++
SecurityPkg/Library/RandLib/IA32/GccRdRand.c | 69 ++++++
SecurityPkg/Library/RandLib/IA32/RdRandWord.c | 104 +++++++++
SecurityPkg/Library/RandLib/RandLib.inf | 53 +++++
SecurityPkg/Library/RandLib/RdRand.c | 284 +++++++++++++++++++++++++
SecurityPkg/Library/RandLib/RdRand.h | 166 +++++++++++++++
SecurityPkg/Library/RandLib/X64/AsmRdRand.asm | 83 ++++++++
SecurityPkg/Library/RandLib/X64/GccRdRand.c | 95 +++++++++
SecurityPkg/Library/RandLib/X64/RdRandWord.c | 70 ++++++
SecurityPkg/SecurityPkg.dec | 3 +
SecurityPkg/SecurityPkg.dsc | 1 +
12 files changed, 1045 insertions(+)
create mode 100644 SecurityPkg/Include/Library/RandLib.h
create mode 100644 SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm
create mode 100644 SecurityPkg/Library/RandLib/IA32/GccRdRand.c
create mode 100644 SecurityPkg/Library/RandLib/IA32/RdRandWord.c
create mode 100644 SecurityPkg/Library/RandLib/RandLib.inf
create mode 100644 SecurityPkg/Library/RandLib/RdRand.c
create mode 100644 SecurityPkg/Library/RandLib/RdRand.h
create mode 100644 SecurityPkg/Library/RandLib/X64/AsmRdRand.asm
create mode 100644 SecurityPkg/Library/RandLib/X64/GccRdRand.c
create mode 100644 SecurityPkg/Library/RandLib/X64/RdRandWord.c
diff --git a/SecurityPkg/Include/Library/RandLib.h b/SecurityPkg/Include/Library/RandLib.h
new file mode 100644
index 0000000..f50c10e
--- /dev/null
+++ b/SecurityPkg/Include/Library/RandLib.h
@@ -0,0 +1,50 @@
+/** @file RandLib.h
+
+ Interfaces provided by RandLib to support RngDxe.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef __RAND_LIB_DOT_H__
+#define __RAND_LIB_DOT_H__
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Determines whether or not RDRAND instruction is supported by the host hardware.
+
+ @retval EFI_SUCCESS RDRAND instruction supported.
+ @retval EFI_UNSUPPORTED RDRAND instruction not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+IsRdRandSupported (
+ VOID
+ );
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ );
+
+#endif /* __RAND_LIB_DOT_H__ */
diff --git a/SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm b/SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm
new file mode 100644
index 0000000..37b3830
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/IA32/AsmRdRand.asm
@@ -0,0 +1,67 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+; AsmRdRand.Asm
+;
+; Abstract:
+;
+; Implementation for 16-, and 32- invocations of RDRAND instruction under 32bit platform.
+;
+; Notes:
+;
+; Visual Studio coding practices do not use inline asm since multiple compilers and
+; architectures are supported assembler not recognizing rdrand instruction so using DB's.
+;
+;------------------------------------------------------------------------------
+
+ .586P
+ .model flat, C
+ .code
+
+;------------------------------------------------------------------------------
+; Generate a 16 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand16Step (UINT16 *Rand); ECX
+;------------------------------------------------------------------------------
+RdRand16Step PROC
+ ; rdrand ax ; generate a 16 bit RN into ax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r16: "0f c7 /6 ModRM:r/m(w)"
+ jb rn16_ok ; jmp if CF=1
+ xor eax, eax ; reg=0 if CF=0
+ ret ; return with failure status
+rn16_ok:
+ mov [ecx], ax
+ mov eax, 1
+ ret
+RdRand16Step ENDP
+
+;------------------------------------------------------------------------------
+; Generate a 32 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand32Step (UINT32 *Rand); ECX
+;------------------------------------------------------------------------------
+RdRand32Step PROC
+ ; rdrand eax ; generate a 32 bit RN into eax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r32: "0f c7 /6 ModRM:r/m(w)"
+ jb rn32_ok ; jmp if CF=1
+ xor eax, eax ; reg=0 if CF=0
+ ret ; return with failure status
+rn32_ok:
+ mov [ecx], eax
+ mov eax, 1
+ ret
+RdRand32Step ENDP
+
+ END
diff --git a/SecurityPkg/Library/RandLib/IA32/GccRdRand.c b/SecurityPkg/Library/RandLib/IA32/GccRdRand.c
new file mode 100644
index 0000000..f42302a
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/IA32/GccRdRand.c
@@ -0,0 +1,69 @@
+/** @file
+ RDRAND Support Routines for GCC environment.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+/**
+ Generates a 16-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand16Step (
+ OUT UINT16 *Rand
+ )
+{
+ UINT8 Carry;
+
+ //
+ // Uses byte code for RDRAND instruction,
+ // in case that GCC version has no direct support on RDRAND assembly.
+ //
+ __asm__ __volatile__ (
+ ".byte 0x66; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
+
+/**
+ Generates a 32-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand32Step (
+ OUT UINT32 *Rand
+ )
+{
+ UINT8 Carry;
+
+ __asm__ __volatile__ (
+ ".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
\ No newline at end of file
diff --git a/SecurityPkg/Library/RandLib/IA32/RdRandWord.c b/SecurityPkg/Library/RandLib/IA32/RdRandWord.c
new file mode 100644
index 0000000..125c53b
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/IA32/RdRandWord.c
@@ -0,0 +1,104 @@
+/** @file
+ RDRAND Support Routines.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RdRand.h"
+
+/**
+ Generates a 64-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand64Step (
+ OUT UINT64 *Rand
+ )
+{
+ UINT32 RandLow;
+ UINT32 RandHigh;
+
+ //
+ // Generating a 64-bit rand on a 32-bit system by
+ // mapping two 32-bit RDRAND instructions.
+ //
+ if (!RdRand32Step (&RandLow)) {
+ return FALSE;
+ }
+ if (!RdRand32Step (&RandHigh)) {
+ return FALSE;
+ }
+
+ *Rand = (UINT64) RandLow | LShiftU64 ((UINT64)RandHigh, 32);
+
+ return TRUE;
+}
+
+/**
+ Calls RDRAND to request a word-length random number.
+
+ @param[out] Rand Buffer pointer to store the random number.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS Random word generation succeeded.
+ @retval EFI_NOT_READY Failed to request random word.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandWord (
+ OUT UINTN *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ return RdRand32 (Rand, NeedRetry);
+}
+
+/**
+ Calls RDRAND to request multiple word-length random numbers.
+
+ @param[in] Length Size of the buffer, in words, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random words generation succeeded.
+ @retval EFI_NOT_READY Failed to request random words.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetWords (
+ IN UINTN Length,
+ OUT UINTN *RandBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ for (Index = 0; Index < Length; Index++) {
+ //
+ // Obtain one word-length (32-bit) Random Number with possible retry-loop.
+ //
+ Status = RdRand32 (RandBuffer, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RandBuffer++;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/SecurityPkg/Library/RandLib/RandLib.inf b/SecurityPkg/Library/RandLib/RandLib.inf
new file mode 100644
index 0000000..68f5cc7
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/RandLib.inf
@@ -0,0 +1,53 @@
+## @file RandLib.inf
+#
+# Provide rand data using x86 instructions
+#
+# (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IntelRandLib
+ FILE_GUID = D0317815-4036-2FF5-0F56-4990A7B37A6F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RandLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ RdRand.c
+
+[Sources.IA32]
+ IA32/RdRandWord.c
+ IA32/AsmRdRand.asm
+ IA32/GccRdRand.c | GCC
+
+[Sources.X64]
+ X64/RdRandWord.c
+ X64/AsmRdRand.asm
+ X64/GccRdRand.c | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[Depex]
+ TRUE
+
+[BuildOptions]
+ XCODE:*_*_*_CC_FLAGS = -mmmx -msse
+
diff --git a/SecurityPkg/Library/RandLib/RdRand.c b/SecurityPkg/Library/RandLib/RdRand.c
new file mode 100644
index 0000000..3babbc3
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/RdRand.c
@@ -0,0 +1,284 @@
+/** @file
+ Support routines for RDRAND instruction access.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RdRand.h"
+#include <Library/RandLib.h>
+
+
+//
+// Bit mask used to determine if RdRand instruction is supported.
+//
+#define RDRAND_MASK 0x40000000
+
+/**
+ Determines whether or not RDRAND instruction is supported by the host hardware.
+
+ @retval EFI_SUCCESS RDRAND instruction supported.
+ @retval EFI_UNSUPPORTED RDRAND instruction not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+IsRdRandSupported (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+ BOOLEAN IsIntelCpu;
+
+ Status = EFI_UNSUPPORTED;
+ IsIntelCpu = FALSE;
+
+ //
+ // Checks whether the current processor is an Intel product by CPUID.
+ //
+ AsmCpuid (0, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ if ((CompareMem ((CHAR8 *)(&RegEbx), "Genu", 4) == 0) &&
+ (CompareMem ((CHAR8 *)(&RegEdx), "ineI", 4) == 0) &&
+ (CompareMem ((CHAR8 *)(&RegEcx), "ntel", 4) == 0)) {
+ IsIntelCpu = TRUE;
+ }
+
+ if (IsIntelCpu) {
+ //
+ // Determine RDRAND support by examining bit 30 of the ECX register returned by CPUID.
+ // A value of 1 indicates that processor supports RDRAND instruction.
+ //
+ AsmCpuid (1, 0, 0, &RegEcx, 0);
+
+ if ((RegEcx & RDRAND_MASK) == RDRAND_MASK) {
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Calls RDRAND to obtain a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand16 (
+ OUT UINT16 *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ UINT32 Index;
+ UINT32 RetryCount;
+
+ if (NeedRetry) {
+ RetryCount = RETRY_LIMIT;
+ } else {
+ RetryCount = 1;
+ }
+
+ //
+ // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.
+ //
+ for (Index = 0; Index < RetryCount; Index++) {
+ if (RdRand16Step (Rand)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Calls RDRAND to obtain a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand32 (
+ OUT UINT32 *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ UINT32 Index;
+ UINT32 RetryCount;
+
+ if (NeedRetry) {
+ RetryCount = RETRY_LIMIT;
+ } else {
+ RetryCount = 1;
+ }
+
+ //
+ // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.
+ //
+ for (Index = 0; Index < RetryCount; Index++) {
+ if (RdRand32Step (Rand)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Calls RDRAND to obtain a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand64 (
+ OUT UINT64 *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ UINT32 Index;
+ UINT32 RetryCount;
+
+ if (NeedRetry) {
+ RetryCount = RETRY_LIMIT;
+ } else {
+ RetryCount = 1;
+ }
+
+ //
+ // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.
+ //
+ for (Index = 0; Index < RetryCount; Index++) {
+ if (RdRand64Step (Rand)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Start;
+ UINT8 *ResidualStart;
+ UINTN *BlockStart;
+ UINTN TempRand;
+ UINTN Count;
+ UINTN Residual;
+ UINTN StartLen;
+ UINTN BlockNum;
+ UINTN Index;
+
+ ResidualStart = NULL;
+ TempRand = 0;
+
+ //
+ // Compute the address of the first word aligned (32/64-bit) block in the
+ // destination buffer, depending on whether we are in 32- or 64-bit mode.
+ //
+ Start = RandBuffer;
+ if (((UINT32)(UINTN)Start % (UINT32)sizeof(UINTN)) == 0) {
+ BlockStart = (UINTN *)Start;
+ Count = Length;
+ StartLen = 0;
+ } else {
+ BlockStart = (UINTN *)(((UINTN)Start & ~(UINTN)(sizeof(UINTN) - 1)) + (UINTN)sizeof(UINTN));
+ Count = Length - (sizeof (UINTN) - (UINT32)((UINTN)Start % sizeof (UINTN)));
+ StartLen = (UINT32)((UINTN)BlockStart - (UINTN)Start);
+ }
+
+ //
+ // Compute the number of word blocks and the remaining number of bytes.
+ //
+ Residual = Count % sizeof (UINTN);
+ BlockNum = Count / sizeof (UINTN);
+ if (Residual != 0) {
+ ResidualStart = (UINT8 *) (BlockStart + BlockNum);
+ }
+
+ //
+ // Obtain a temporary random number for use in the residuals. Failout if retry fails.
+ //
+ if (StartLen > 0) {
+ Status = RdRandWord ((UINTN *) &TempRand, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Populate the starting mis-aligned block.
+ //
+ for (Index = 0; Index < StartLen; Index++) {
+ Start[Index] = (UINT8)(TempRand & 0xff);
+ TempRand = TempRand >> 8;
+ }
+
+ //
+ // Populate the central aligned block. Fail out if retry fails.
+ //
+ Status = RdRandGetWords (BlockNum, (UINTN *)(BlockStart));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Populate the final mis-aligned block.
+ //
+ if (Residual > 0) {
+ Status = RdRandWord ((UINTN *)&TempRand, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ for (Index = 0; Index < Residual; Index++) {
+ ResidualStart[Index] = (UINT8)(TempRand & 0xff);
+ TempRand = TempRand >> 8;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/Library/RandLib/RdRand.h b/SecurityPkg/Library/RandLib/RdRand.h
new file mode 100644
index 0000000..32dfc73
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/RdRand.h
@@ -0,0 +1,166 @@
+/** @file
+ Header for the RDRAND APIs used by RNG DXE driver.
+
+ Support API definitions for RDRAND instruction access, which will leverage
+ Intel Secure Key technology to provide high-quality random numbers for use
+ in applications, or entropy for seeding other random number generators.
+ Refer to http://software.intel.com/en-us/articles/intel-digital-random-number
+ -generator-drng-software-implementation-guide/ for more information about Intel
+ Secure Key technology.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __RD_RAND_H__
+#define __RD_RAND_H__
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Uefi/UefiBaseType.h>
+
+//
+// The maximun number of retries to obtain one available random number.
+//
+#define RETRY_LIMIT 10
+
+/**
+ Generates a 16-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand16Step (
+ OUT UINT16 *Rand
+ );
+
+/**
+ Generates a 32-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand32Step (
+ OUT UINT32 *Rand
+ );
+
+/**
+ Generates a 64-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand64Step (
+ OUT UINT64 *Rand
+ );
+
+/**
+ Calls RDRAND to obtain a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand16 (
+ OUT UINT16 *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to obtain a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand32 (
+ OUT UINT32 *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to obtain a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the random result.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS RDRAND call was successful.
+ @retval EFI_NOT_READY Failed attempts to call RDRAND.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRand64 (
+ OUT UINT64 *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to request a word-length random number.
+
+ @param[out] Rand Buffer pointer to store the random number.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS Random word generation succeeded.
+ @retval EFI_NOT_READY Failed to request random word.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandWord (
+ OUT UINTN *Rand,
+ IN BOOLEAN NeedRetry
+ );
+
+/**
+ Calls RDRAND to request multiple word-length random numbers.
+
+ @param[in] Length Size of the buffer, in words, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random words generation succeeded.
+ @retval EFI_NOT_READY Failed to request random words.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetWords (
+ IN UINTN Length,
+ OUT UINTN *RandBuffer
+ );
+
+#endif // __RD_RAND_H__
diff --git a/SecurityPkg/Library/RandLib/X64/AsmRdRand.asm b/SecurityPkg/Library/RandLib/X64/AsmRdRand.asm
new file mode 100644
index 0000000..8a4fe65
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/X64/AsmRdRand.asm
@@ -0,0 +1,83 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+; AsmRdRand.Asm
+;
+; Abstract:
+;
+; Implementation for 16-, 32-, and 64-bit invocations of RDRAND instruction under 64bit platform.
+;
+; Notes:
+;
+; Visual Studio coding practices do not use inline asm since multiple compilers and
+; architectures are supported assembler not recognizing rdrand instruction so using DB's.
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; Generate a 16 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand16Step (UINT16 *Rand); RCX
+;------------------------------------------------------------------------------
+RdRand16Step PROC
+ ; rdrand ax ; generate a 16 bit RN into ax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r16: "0f c7 /6 ModRM:r/m(w)"
+ jb rn16_ok ; jmp if CF=1
+ xor rax, rax ; reg=0 if CF=0
+ ret ; return with failure status
+rn16_ok:
+ mov [rcx], ax
+ mov rax, 1
+ ret
+RdRand16Step ENDP
+
+;------------------------------------------------------------------------------
+; Generate a 32 bit random number
+; Return TRUE if Rand generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand32Step (UINT32 *Rand); RCX
+;------------------------------------------------------------------------------
+RdRand32Step PROC
+ ; rdrand eax ; generate a 32 bit RN into eax, CF=1 if RN generated ok, otherwise CF=0
+ db 0fh, 0c7h, 0f0h ; rdrand r32: "0f c7 /6 ModRM:r/m(w)"
+ jb rn32_ok ; jmp if CF=1
+ xor rax, rax ; reg=0 if CF=0
+ ret ; return with failure status
+rn32_ok:
+ mov [rcx], eax
+ mov rax, 1
+ ret
+RdRand32Step ENDP
+
+;------------------------------------------------------------------------------
+; Generate a 64 bit random number
+; Return TRUE if RN generated successfully, or FALSE if not
+;
+; BOOLEAN EFIAPI RdRand64Step (UINT64 *Random); RCX
+;------------------------------------------------------------------------------
+RdRand64Step PROC
+ ; rdrand rax ; generate a 64 bit RN into rax, CF=1 if RN generated ok, otherwise CF=0
+ db 048h, 0fh, 0c7h, 0f0h ; rdrand r64: "REX.W + 0F C7 /6 ModRM:r/m(w)"
+ jb rn64_ok ; jmp if CF=1
+ xor rax, rax ; reg=0 if CF=0
+ ret ; return with failure status
+rn64_ok:
+ mov [rcx], rax
+ mov rax, 1
+ ret
+RdRand64Step ENDP
+
+ END
diff --git a/SecurityPkg/Library/RandLib/X64/GccRdRand.c b/SecurityPkg/Library/RandLib/X64/GccRdRand.c
new file mode 100644
index 0000000..d28336d
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/X64/GccRdRand.c
@@ -0,0 +1,95 @@
+/** @file
+ RDRAND Support Routines for GCC environment.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+/**
+ Generates a 16-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand16Step (
+ OUT UINT16 *Rand
+ )
+{
+ UINT8 Carry;
+
+ //
+ // Uses byte code for RDRAND instruction,
+ // in case that GCC version has no direct support on RDRAND assembly.
+ //
+ __asm__ __volatile__ (
+ ".byte 0x66; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
+
+/**
+ Generates a 32-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand32Step (
+ OUT UINT32 *Rand
+ )
+{
+ UINT8 Carry;
+
+ __asm__ __volatile__ (
+ ".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
+
+/**
+ Generates a 64-bit random number through RDRAND instruction.
+
+ @param[out] Rand Buffer pointer to store the random result.
+
+ @retval TRUE RDRAND call was successful.
+ @retval FALSE Failed attempts to call RDRAND.
+
+**/
+BOOLEAN
+EFIAPI
+RdRand64Step (
+ OUT UINT64 *Rand
+ )
+{
+ UINT8 Carry;
+
+ __asm__ __volatile__ (
+ ".byte 0x48; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
+ :"=a" (*Rand),
+ "=qm" (Carry)
+ );
+
+ return (BOOLEAN) Carry;
+}
diff --git a/SecurityPkg/Library/RandLib/X64/RdRandWord.c b/SecurityPkg/Library/RandLib/X64/RdRandWord.c
new file mode 100644
index 0000000..946e5ba
--- /dev/null
+++ b/SecurityPkg/Library/RandLib/X64/RdRandWord.c
@@ -0,0 +1,70 @@
+/** @file
+ RDRAND Support Routines.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RdRand.h"
+
+/**
+ Calls RDRAND to request a word-length random number.
+
+ @param[out] Rand Buffer pointer to store the random number.
+ @param[in] NeedRetry Determine whether or not to loop retry.
+
+ @retval EFI_SUCCESS Random word generation succeeded.
+ @retval EFI_NOT_READY Failed to request random word.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandWord (
+ OUT UINTN *Rand,
+ IN BOOLEAN NeedRetry
+ )
+{
+ return RdRand64 (Rand, NeedRetry);
+}
+
+/**
+ Calls RDRAND to request multiple word-length random numbers.
+
+ @param[in] Length Size of the buffer, in words, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random words generation succeeded.
+ @retval EFI_NOT_READY Failed to request random words.
+
+**/
+EFI_STATUS
+EFIAPI
+RdRandGetWords (
+ IN UINTN Length,
+ OUT UINTN *RandBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ for (Index = 0; Index < Length; Index++) {
+ //
+ // Obtain one word-length (64-bit) Random Number with possible retry-loop.
+ //
+ Status = RdRand64 (RandBuffer, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RandBuffer++;
+ }
+
+ return EFI_SUCCESS;
+}
\ No newline at end of file
diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index 25ec7d0..8281deb 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -75,6 +75,9 @@
#
TrEEPpVendorLib|Include/Library/TrEEPpVendorLib.h
+ ## @libraryclass Provides RDRAND.
+ RandLib|Include/Library/RandLib.h
+
[Guids]
## Security package token space guid.
# Include/Guid/SecurityPkgTokenSpace.h
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 35a7a51..26758c3 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -59,6 +59,7 @@
TrEEPhysicalPresenceLib|SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf
TcgPpVendorLib|SecurityPkg/Library/TcgPpVendorLibNull/TcgPpVendorLibNull.inf
TrEEPpVendorLib|SecurityPkg/Library/TrEEPpVendorLibNull/TrEEPpVendorLibNull.inf
+ RandLib|SecurityPkg/Library/RandLib/RandLib.inf
[LibraryClasses.common.PEIM]
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
--
2.4.3
------------------------------------------------------------------------------
2.4.3
------------------------------------------------------------------------------