Jonathan Doman [mailto:jonathan.do...@hp.com] wrote:

]Sent: Friday, June 19, 2015 12:48 PM
]To: edk2-devel@lists.sourceforge.net
]Subject: [edk2] [PATCH 1/2] SecurityPkg: Add RandLib from existing RngDxe code
]
]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 <jonathan.do...@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


Is this using the correct calling convention? I think this is the 32-bit
version, and EDK2 x86 32-bit code uses cdecl calling convention. If so,
the passed value for arg1 is in [esp+4], not ecx. Same for all the other
32-bit asm functions here.


]+    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) {


What about non-Intel processors? I believe RDRAND has been adopted by at
least one other x86 processor vendor in a compatible way, making it easy
to support. In general EDK2 supports AMD and other x86 processors, so
artificially excluding a compatible non-Intel RDRAND implementation seems
wrong.


]+    //
]+    // 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



------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to