From 3cfc7813bb7e904c4a940d638facc10be5e22645 Mon Sep 17 00:00:00 2001 From: Qin Long Date: Mon, 21 Sep 2015 05:53:52 +0000 Subject: [PATCH] MdePkg: Add CPU RdRand access APIs for random number generation Add AsmRdRand16/32/64 APIs for RdRand instruction access to generate high-quality random number. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Qin Long Reviewed-by: Michael Kinney Reviewed-by: Liming Gao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18518 6f19259b-4bc3-4df7-8a09-765794883524 --- MdePkg/Include/Library/BaseLib.h | 51 ++++++++++++++ MdePkg/Library/BaseLib/BaseLib.inf | 6 ++ MdePkg/Library/BaseLib/Ia32/RdRand.S | 80 ++++++++++++++++++++++ MdePkg/Library/BaseLib/Ia32/RdRand.asm | 94 ++++++++++++++++++++++++++ MdePkg/Library/BaseLib/X64/RdRand.S | 72 ++++++++++++++++++++ MdePkg/Library/BaseLib/X64/RdRand.asm | 83 +++++++++++++++++++++++ 6 files changed, 386 insertions(+) create mode 100644 MdePkg/Library/BaseLib/Ia32/RdRand.S create mode 100644 MdePkg/Library/BaseLib/Ia32/RdRand.asm create mode 100644 MdePkg/Library/BaseLib/X64/RdRand.S create mode 100644 MdePkg/Library/BaseLib/X64/RdRand.asm diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 7e10804082..c41fa783df 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -7647,6 +7647,57 @@ AsmPrepareAndThunk16 ( IN OUT THUNK_CONTEXT *ThunkContext ); +/** + Generates a 16-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @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 +AsmRdRand16 ( + OUT UINT16 *Rand + ); + +/** + Generates a 32-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @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 +AsmRdRand32 ( + OUT UINT32 *Rand + ); + +/** + Generates a 64-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @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 +AsmRdRand64 ( + OUT UINT64 *Rand + ); + #endif #endif diff --git a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf index 4a37e60fe3..4cc86d7e5d 100644 --- a/MdePkg/Library/BaseLib/BaseLib.inf +++ b/MdePkg/Library/BaseLib/BaseLib.inf @@ -159,6 +159,7 @@ Ia32/EnablePaging64.asm | MSFT Ia32/EnableCache.c | MSFT Ia32/DisableCache.c | MSFT + Ia32/RdRand.asm | MSFT Ia32/Wbinvd.asm | INTEL Ia32/WriteMm7.asm | INTEL @@ -252,6 +253,7 @@ Ia32/EnablePaging64.asm | INTEL Ia32/EnableCache.asm | INTEL Ia32/DisableCache.asm | INTEL + Ia32/RdRand.asm | INTEL Ia32/GccInline.c | GCC Ia32/Thunk16.nasm | GCC @@ -279,6 +281,7 @@ Ia32/LShiftU64.S | GCC Ia32/EnableCache.S | GCC Ia32/DisableCache.S | GCC + Ia32/RdRand.S | GCC Ia32/DivS64x64Remainder.c Ia32/InternalSwitchStack.c | MSFT @@ -383,10 +386,12 @@ X64/CpuBreakpoint.c | MSFT X64/WriteMsr64.c | MSFT X64/ReadMsr64.c | MSFT + X64/RdRand.asm | MSFT X64/CpuBreakpoint.asm | INTEL X64/WriteMsr64.asm | INTEL X64/ReadMsr64.asm | INTEL + X64/RdRand.asm | INTEL X64/Non-existing.c Math64.c @@ -417,6 +422,7 @@ X64/CpuIdEx.S | GCC X64/EnableCache.S | GCC X64/DisableCache.S | GCC + X64/RdRand.S | GCC ChkStkGcc.c | GCC [Sources.IPF] diff --git a/MdePkg/Library/BaseLib/Ia32/RdRand.S b/MdePkg/Library/BaseLib/Ia32/RdRand.S new file mode 100644 index 0000000000..503f65a721 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ia32/RdRand.S @@ -0,0 +1,80 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# 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: +# +# RdRand.S +# +# Abstract: +# +# Generates random number through CPU RdRand instruction under 32-bit platform. +# +# Notes: +# +#------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Generates a 16 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI AsmRdRand16 (UINT16 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmRdRand16) +ASM_PFX(AsmRdRand16): + .byte 0x0f, 0xc7, 0xf0 // rdrand r16: "0f c7 /6 ModRM:r/m(w)" + jc rn16_ok // jmp if CF=1 + xor %eax, %eax // reg=0 if CF=0 + ret // return with failure status +rn16_ok: + mov 0x4(%esp), %edx + mov %ax, (%edx) + mov $0x1, %eax + ret + +//------------------------------------------------------------------------------ +// Generates a 32 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI AsmRdRand32 (UINT32 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmRdRand32) +ASM_PFX(AsmRdRand32): + .byte 0x0f, 0xc7, 0xf0 // rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jc rn32_ok // jmp if CF=1 + xor %eax, %eax // reg=0 if CF=0 + ret // return with failure status +rn32_ok: + mov 0x4(%esp), %edx + mov %eax, (%edx) + mov $0x1, %eax + ret + +//------------------------------------------------------------------------------ +// Generates a 64 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI AsmRdRand64 (UINT64 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmRdRand64) +ASM_PFX(AsmRdRand64): + .byte 0x0f, 0xc7, 0xf0 // rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jnc rn64_ret // jmp if CF=0 + mov 0x4(%esp), %edx + mov %eax, (%edx) + + .byte 0x0f, 0xc7, 0xf0 // generate another 32 bit RN + jnc rn64_ret // jmp if CF=0 + mov %eax, 0x4(%edx) + + mov $0x1, %eax + ret +rn64_ret: + xor %eax, %eax + ret // return with failure status diff --git a/MdePkg/Library/BaseLib/Ia32/RdRand.asm b/MdePkg/Library/BaseLib/Ia32/RdRand.asm new file mode 100644 index 0000000000..21349b0918 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ia32/RdRand.asm @@ -0,0 +1,94 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; 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: +; +; RdRand.asm +; +; Abstract: +; +; Generates random number through CPU RdRand instruction under 32-bit platform. +; +; Notes: +; +;------------------------------------------------------------------------------ + +.686P +.model flat, C + +.code + +;------------------------------------------------------------------------------ +; Generates a 16 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI AsmRdRand16 (UINT16 *Rand); +;------------------------------------------------------------------------------ +AsmRdRand16 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)" + jc rn16_ok ; jmp if CF=1 + xor eax, eax ; reg=0 if CF=0 + ret ; return with failure status +rn16_ok: + mov edx, dword ptr [esp + 4] + mov [edx], ax + mov eax, 1 + ret +AsmRdRand16 ENDP + +;------------------------------------------------------------------------------ +; Generates a 32 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI AsmRdRand32 (UINT32 *Rand); +;------------------------------------------------------------------------------ +AsmRdRand32 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)" + jc rn32_ok ; jmp if CF=1 + xor eax, eax ; reg=0 if CF=0 + ret ; return with failure status +rn32_ok: + mov edx, dword ptr [esp + 4] + mov [edx], eax + mov eax, 1 + ret +AsmRdRand32 ENDP + +;------------------------------------------------------------------------------ +; Generates a 64 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI AsmRdRand64 (UINT64 *Rand); +;------------------------------------------------------------------------------ +AsmRdRand64 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)" + jnc rn64_ret ; jmp if CF=0 + mov edx, dword ptr [esp + 4] + mov [edx], eax + + db 0fh, 0c7h, 0f0h ; 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 + ret ; return with failure status +AsmRdRand64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/X64/RdRand.S b/MdePkg/Library/BaseLib/X64/RdRand.S new file mode 100644 index 0000000000..49b50e6901 --- /dev/null +++ b/MdePkg/Library/BaseLib/X64/RdRand.S @@ -0,0 +1,72 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# 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: +# +# RdRand.S +# +# Abstract: +# +# Generates random number through CPU RdRand instruction under 64-bit platform. +# +# Notes: +# +#------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Generates a 16 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI AsmRdRand16 (UINT16 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmRdRand16) +ASM_PFX(AsmRdRand16): + .byte 0x0f, 0xc7, 0xf0 // rdrand r16: "0f c7 /6 ModRM:r/m(w)" + jc rn16_ok // jmp if CF=1 + xor %rax, %rax // reg=0 if CF=0 + ret // return with failure status +rn16_ok: + mov %ax, (%rcx) + mov $0x1, %rax + ret + +//------------------------------------------------------------------------------ +// Generates a 32 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI AsmRdRand32 (UINT32 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmRdRand32) +ASM_PFX(AsmRdRand32): + .byte 0x0f, 0xc7, 0xf0 // rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jc rn32_ok // jmp if CF=1 + xor %rax, %rax // reg=0 if CF=0 + ret // return with failure status +rn32_ok: + mov %eax, (%rcx) + mov $0x1, %rax + ret + +//------------------------------------------------------------------------------ +// Generates a 64 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI AsmRdRand64 (UINT64 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmRdRand64) +ASM_PFX(AsmRdRand64): + .byte 0x48, 0x0f, 0xc7, 0xf0 // rdrand r64: "REX.W + 0f c7 /6 ModRM:r/m(w)" + jc rn64_ok // jmp if CF=1 + xor %rax, %rax // reg=0 if CF=0 + ret // return with failure status +rn64_ok: + mov %rax, (%rcx) + mov $0x1, %rax + ret diff --git a/MdePkg/Library/BaseLib/X64/RdRand.asm b/MdePkg/Library/BaseLib/X64/RdRand.asm new file mode 100644 index 0000000000..370cdb607a --- /dev/null +++ b/MdePkg/Library/BaseLib/X64/RdRand.asm @@ -0,0 +1,83 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; 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: +; +; RdRand.asm +; +; Abstract: +; +; Generates random number through CPU RdRand instruction under 64-bit platform. +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; Generates a 16 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI AsmRdRand16 (UINT16 *Rand); +;------------------------------------------------------------------------------ +AsmRdRand16 PROC + ; rdrand ax ; generate a 16 bit RN into eax, + ; CF=1 if RN generated ok, otherwise CF=0 + db 0fh, 0c7h, 0f0h ; rdrand r16: "0f c7 /6 ModRM:r/m(w)" + jc 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 +AsmRdRand16 ENDP + +;------------------------------------------------------------------------------ +; Generates a 32 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI AsmRdRand32 (UINT32 *Rand); +;------------------------------------------------------------------------------ +AsmRdRand32 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)" + jc 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 +AsmRdRand32 ENDP + +;------------------------------------------------------------------------------ +; Generates a 64 bit random number through one RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI AsmRdRand64 (UINT64 *Random); +;------------------------------------------------------------------------------ +AsmRdRand64 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)" + jc 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 +AsmRdRand64 ENDP + + END -- 2.39.5