BaseRngLib uses rdrand instruction to get random number from DRNG in the
processor, which is not a good candidate for seeding openssl rand
interface.

rdseed in x86 cpu provides non-deterministic random number (NRBG) which
meets NIST SP 800-90B and NIST SP800-90C standards and can be used as
seed for other software DRNG. This patch adds a C interface AsmRdSeed()
to wrap it in BaseLib so that we can add a new RngLib for users to choose
in their platform, if their processor support rdseed instruction.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1871
Cc: Michael D Kinney <michael.d.kin...@intel.com>
Cc: Liming Gao <liming....@intel.com>
Cc: Ray Ni <ray...@intel.com>
Signed-off-by: Jian J Wang <jian.j.w...@intel.com>
---
 MdePkg/Include/Library/BaseLib.h          | 51 +++++++++++++
 MdePkg/Library/BaseLib/BaseLib.inf        |  4 ++
 MdePkg/Library/BaseLib/BaseLibInternals.h | 46 ++++++++++++
 MdePkg/Library/BaseLib/Ia32/RdSeed.nasm   | 87 +++++++++++++++++++++++
 MdePkg/Library/BaseLib/X64/RdSeed.nasm    | 80 +++++++++++++++++++++
 MdePkg/Library/BaseLib/X86RdSeed.c        | 73 +++++++++++++++++++
 6 files changed, 341 insertions(+)
 create mode 100644 MdePkg/Library/BaseLib/Ia32/RdSeed.nasm
 create mode 100644 MdePkg/Library/BaseLib/X64/RdSeed.nasm
 create mode 100644 MdePkg/Library/BaseLib/X86RdSeed.c

diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h
index 2a75bc023f..e2f9bf121e 100644
--- a/MdePkg/Include/Library/BaseLib.h
+++ b/MdePkg/Include/Library/BaseLib.h
@@ -7856,6 +7856,57 @@ AsmRdRand64  (
   OUT     UINT64                    *Rand
   );
 
+/**
+  Generates a 16-bit random seed through RDSEED instruction.
+
+  if Seed is NULL, then ASSERT().
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+ **/
+BOOLEAN
+EFIAPI
+AsmRdSeed16 (
+  OUT     UINT16                    *Seed
+  );
+
+/**
+  Generates a 32-bit random seed through RDSEED instruction.
+
+  if Seed is NULL, then ASSERT().
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+**/
+BOOLEAN
+EFIAPI
+AsmRdSeed32 (
+  OUT     UINT32                    *Seed
+  );
+
+/**
+  Generates a 64-bit random seed through RDSEED instruction.
+
+  if Seed is NULL, then ASSERT().
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+**/
+BOOLEAN
+EFIAPI
+AsmRdSeed64  (
+  OUT     UINT64                    *Seed
+  );
+
 /**
   Load given selector into TR register.
 
diff --git a/MdePkg/Library/BaseLib/BaseLib.inf 
b/MdePkg/Library/BaseLib/BaseLib.inf
index 3586beb0ab..5e12093ba3 100644
--- a/MdePkg/Library/BaseLib/BaseLib.inf
+++ b/MdePkg/Library/BaseLib/BaseLib.inf
@@ -181,6 +181,7 @@
   Ia32/EnableCache.nasm| GCC
   Ia32/DisableCache.nasm| GCC
   Ia32/RdRand.nasm
+  Ia32/RdSeed.nasm
 
   Ia32/DivS64x64Remainder.c
   Ia32/InternalSwitchStack.c | MSFT
@@ -202,6 +203,7 @@
   X86DisablePaging64.c
   X86DisablePaging32.c
   X86RdRand.c
+  X86RdSeed.c
   X86PatchInstruction.c
   X86SpeculationBarrier.c
 
@@ -306,12 +308,14 @@
   X86DisablePaging64.c
   X86DisablePaging32.c
   X86RdRand.c
+  X86RdSeed.c
   X86PatchInstruction.c
   X86SpeculationBarrier.c
   X64/GccInline.c | GCC
   X64/EnableDisableInterrupts.nasm
   X64/DisablePaging64.nasm
   X64/RdRand.nasm
+  X64/RdSeed.nasm
   ChkStkGcc.c  | GCC
 
 [Sources.EBC]
diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h 
b/MdePkg/Library/BaseLib/BaseLibInternals.h
index 6837d67d90..7b18b192c9 100644
--- a/MdePkg/Library/BaseLib/BaseLibInternals.h
+++ b/MdePkg/Library/BaseLib/BaseLibInternals.h
@@ -862,6 +862,52 @@ InternalX86RdRand64  (
   OUT     UINT64                    *Rand
   );
 
+/**
+  Generates a 16-bit random seed through RDSEED instruction.
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+ **/
+BOOLEAN
+EFIAPI
+InternalX86RdSeed16 (
+  OUT     UINT16                    *Seed
+  );
+
+/**
+  Generates a 32-bit random seed through RDSEED instruction.
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+**/
+BOOLEAN
+EFIAPI
+InternalX86RdSeed32 (
+  OUT     UINT32                    *Seed
+  );
+
+/**
+  Generates a 64-bit random seed through RDSEED instruction.
+
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+**/
+BOOLEAN
+EFIAPI
+InternalX86RdSeed64  (
+  OUT     UINT64                    *Seed
+  );
+
 #else
 
 #endif
diff --git a/MdePkg/Library/BaseLib/Ia32/RdSeed.nasm 
b/MdePkg/Library/BaseLib/Ia32/RdSeed.nasm
new file mode 100644
index 0000000000..0a4de30db6
--- /dev/null
+++ b/MdePkg/Library/BaseLib/Ia32/RdSeed.nasm
@@ -0,0 +1,87 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;   RdSeed.nasm
+;
+; Abstract:
+;
+;   Generates random seed through CPU RdSeed instruction under 32-bit platform.
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+;------------------------------------------------------------------------------
+;  Generates a 16 bit random seed through RDSEED instruction.
+;  Return TRUE if Seed generated successfully, or FALSE if not.
+;
+;  BOOLEAN EFIAPI InternalX86RdSeed16 (UINT16 *Seed);
+;------------------------------------------------------------------------------
+global ASM_PFX(InternalX86RdSeed16)
+ASM_PFX(InternalX86RdSeed16):
+    ; rdseed   ax                  ; generate a 16 bit RN into ax
+                                   ; CF=1 if RN generated ok, otherwise CF=0
+    db     0xf, 0xc7, 0xf8         ; rdseed r16: "0f c7 /7  ModRM:r/m(w)"
+    jc     rn16_ok                 ; jmp if CF=1
+    xor    eax, eax                ; reg=0 if CF=0
+    pause
+    ret                            ; return with failure status
+rn16_ok:
+    mov    edx, dword [esp + 4]
+    mov    [edx], ax
+    mov    eax,  1
+    ret
+
+;------------------------------------------------------------------------------
+;  Generates a 32 bit random seed through RDSEED instruction.
+;  Return TRUE if Seed generated successfully, or FALSE if not.
+;
+;  BOOLEAN EFIAPI InternalX86RdSeed32 (UINT32 *Seed);
+;------------------------------------------------------------------------------
+global ASM_PFX(InternalX86RdSeed32)
+ASM_PFX(InternalX86RdSeed32):
+    ; rdseed   eax                 ; generate a 32 bit RN into eax
+                                   ; CF=1 if RN generated ok, otherwise CF=0
+    db     0xf, 0xc7, 0xf8         ; rdseed r32: "0f c7 /7  ModRM:r/m(w)"
+    jc     rn32_ok                 ; jmp if CF=1
+    xor    eax, eax                ; reg=0 if CF=0
+    pause
+    ret                            ; return with failure status
+rn32_ok:
+    mov    edx, dword [esp + 4]
+    mov    [edx], eax
+    mov    eax,  1
+    ret
+
+;------------------------------------------------------------------------------
+;  Generates a 64 bit random seed through RDSEED instruction.
+;  Return TRUE if Seed generated successfully, or FALSE if not.
+;
+;  BOOLEAN EFIAPI InternalX86RdSeed64 (UINT64 *Seed);
+;------------------------------------------------------------------------------
+global ASM_PFX(InternalX86RdSeed64)
+ASM_PFX(InternalX86RdSeed64):
+    ; rdseed   eax                 ; generate a 32 bit RN into eax
+                                   ; CF=1 if RN generated ok, otherwise CF=0
+    db     0xf, 0xc7, 0xf8         ; rdseed r32: "0f c7 /7  ModRM:r/m(w)"
+    jnc    rn64_ret                ; jmp if CF=0
+    mov    edx, dword [esp + 4]
+    mov    [edx], eax
+
+    db     0xf, 0xc7, 0xf0         ; generate another 32 bit RN
+    jnc    rn64_ret                ; jmp if CF=0
+    mov    [edx + 4], eax
+
+    mov    eax,  1
+    ret
+rn64_ret:
+    xor    eax, eax
+    pause
+    ret                            ; return with failure status
+
diff --git a/MdePkg/Library/BaseLib/X64/RdSeed.nasm 
b/MdePkg/Library/BaseLib/X64/RdSeed.nasm
new file mode 100644
index 0000000000..a60acfeace
--- /dev/null
+++ b/MdePkg/Library/BaseLib/X64/RdSeed.nasm
@@ -0,0 +1,80 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;   RdSeed.nasm
+;
+; Abstract:
+;
+;   Generates random seed through CPU RdSeed instruction under 64-bit platform.
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    DEFAULT REL
+    SECTION .text
+
+;------------------------------------------------------------------------------
+;  Generates a 16 bit random seed through RDSEED instruction.
+;  Return TRUE if Seed generated successfully, or FALSE if not.
+;
+;  BOOLEAN EFIAPI InternalX86RdSeed16 (UINT16 *Seed);
+;------------------------------------------------------------------------------
+global ASM_PFX(InternalX86RdSeed16)
+ASM_PFX(InternalX86RdSeed16):
+    ; rdseed   ax                  ; generate a 16 bit RN into eax,
+                                   ; CF=1 if RN generated ok, otherwise CF=0
+    db     0xf, 0xc7, 0xf8         ; rdseed r16: "0f c7 /7  ModRM:r/m(w)"
+    jc     rn16_ok                 ; jmp if CF=1
+    xor    rax, rax                ; reg=0 if CF=0
+    pause
+    ret                            ; return with failure status
+rn16_ok:
+    mov    [rcx], ax
+    mov    rax,  1
+    ret
+
+;------------------------------------------------------------------------------
+;  Generates a 32 bit random seed through RDSEED instruction.
+;  Return TRUE if Seed generated successfully, or FALSE if not.
+;
+;  BOOLEAN EFIAPI InternalX86RdSeed32 (UINT32 *Seed);
+;------------------------------------------------------------------------------
+global ASM_PFX(InternalX86RdSeed32)
+ASM_PFX(InternalX86RdSeed32):
+    ; rdseed   eax                 ; generate a 32 bit RN into eax,
+                                   ; CF=1 if RN generated ok, otherwise CF=0
+    db     0xf, 0xc7, 0xf8         ; rdseed r32: "0f c7 /7  ModRM:r/m(w)"
+    jc     rn32_ok                 ; jmp if CF=1
+    xor    rax, rax                ; reg=0 if CF=0
+    pause
+    ret                            ; return with failure status
+rn32_ok:
+    mov    [rcx], eax
+    mov    rax,  1
+    ret
+
+;------------------------------------------------------------------------------
+;  Generates a 64 bit random seed through one RDSEED instruction.
+;  Return TRUE if Seed generated successfully, or FALSE if not.
+;
+;  BOOLEAN EFIAPI InternalX86RdSeed64 (UINT64 *Seed);
+;------------------------------------------------------------------------------
+global ASM_PFX(InternalX86RdSeed64)
+ASM_PFX(InternalX86RdSeed64):
+    ; rdseed   rax                 ; generate a 64 bit RN into rax,
+                                   ; CF=1 if RN generated ok, otherwise CF=0
+    db     0x48, 0xf, 0xc7, 0xf8   ; rdseed r64: "REX.W + 0f c7 /7 
ModRM:r/m(w)"
+    jc     rn64_ok                 ; jmp if CF=1
+    xor    rax, rax                ; reg=0 if CF=0
+    pause
+    ret                            ; return with failure status
+rn64_ok:
+    mov    [rcx], rax
+    mov    rax, 1
+    ret
+
diff --git a/MdePkg/Library/BaseLib/X86RdSeed.c 
b/MdePkg/Library/BaseLib/X86RdSeed.c
new file mode 100644
index 0000000000..9fa7948ff1
--- /dev/null
+++ b/MdePkg/Library/BaseLib/X86RdSeed.c
@@ -0,0 +1,73 @@
+/** @file
+  IA-32/x64 AsmRdSeedxx()
+  Generates random seed through CPU RdSeed instruction.
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BaseLibInternals.h"
+
+/**
+  Generates a 16-bit random seed through RDSEED instruction.
+
+  if Seed is NULL, then ASSERT().
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+ **/
+BOOLEAN
+EFIAPI
+AsmRdSeed16 (
+  OUT     UINT16                    *Seed
+  )
+{
+  ASSERT (Seed != NULL);
+  return InternalX86RdSeed16 (Seed);
+}
+
+/**
+  Generates a 32-bit random seed through RDSEED instruction.
+
+  if Seed is NULL, then ASSERT().
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+**/
+BOOLEAN
+EFIAPI
+AsmRdSeed32 (
+  OUT     UINT32                    *Seed
+  )
+{
+  ASSERT (Seed != NULL);
+  return InternalX86RdSeed32 (Seed);
+}
+
+/**
+  Generates a 64-bit random seed through RDSEED instruction.
+
+  if Seed is NULL, then ASSERT().
+
+  @param[out]  Seed     Buffer pointer to store the seed data.
+
+  @retval TRUE          RDSEED call was successful.
+  @retval FALSE         Failed attempts to call RDSEED.
+
+**/
+BOOLEAN
+EFIAPI
+AsmRdSeed64  (
+  OUT     UINT64                    *Seed
+  )
+{
+  ASSERT (Seed != NULL);
+  return InternalX86RdSeed64 (Seed);
+}
-- 
2.17.1.windows.2


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#50610): https://edk2.groups.io/g/devel/message/50610
Mute This Topic: https://groups.io/mt/56714069/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to