From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga07.intel.com (mga07.intel.com []) by mx.groups.io with SMTP id smtpd.web10.830.1573697867801385708 for ; Wed, 13 Nov 2019 18:17:53 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: jian.j.wang@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Nov 2019 18:17:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.68,302,1569308400"; d="scan'208";a="235500492" Received: from shwdeopenpsi777.ccr.corp.intel.com ([10.239.158.59]) by fmsmga002.fm.intel.com with ESMTP; 13 Nov 2019 18:17:51 -0800 From: "Wang, Jian J" To: devel@edk2.groups.io Cc: Michael D Kinney , Liming Gao , Ray Ni Subject: [PATCH 04/11] MdePkg/BaseLib: add interface to wrap rdseed IA instruction Date: Thu, 14 Nov 2019 10:17:36 +0800 Message-Id: <20191114021743.3876-5-jian.j.wang@intel.com> X-Mailer: git-send-email 2.17.1.windows.2 In-Reply-To: <20191114021743.3876-1-jian.j.wang@intel.com> References: <20191114021743.3876-1-jian.j.wang@intel.com> 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 Cc: Liming Gao Cc: Ray Ni Signed-off-by: Jian J Wang --- 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.
+; 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.
+; 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.
+ 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