Fix RDSEED hang on x86 (GH #872) (#873)

Calls to `MASM_RDSEED_GenerateBlock` would hang for an unknown reasons on Windows 10 and VS2017/VS2019 toolchains. Similar calls to `MASM_RDRAND_GenerateBlock` worked as expected. They were effectively the same code. The only differences were the function names and the opcodes (they were literally copy/paste).

Splitting `rdrand.asm` (with both `RDRAND` and `RDSEED`) into `rdrand.asm` (with `RDRAND`) and `rdseed.asm` (with `RDSEED`) resolved the issue. We don't know why.
pull/877/head
Jeffrey Walton 2019-08-06 21:01:22 -04:00 committed by GitHub
parent e5ab7919f9
commit b1c691b53a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 277 additions and 213 deletions

View File

@ -118,7 +118,7 @@ LIB_OBJS = \
zdeflate.obj zinflate.obj zlib.obj zdeflate.obj zinflate.obj zlib.obj
ASM_OBJS = \ ASM_OBJS = \
rdrand-x86.obj rdrand-x64.obj x64masm.obj x64dll.obj rdrand-x86.obj rdrand-x64.obj rdseed-x86.obj rdseed-x64.obj x64masm.obj x64dll.obj
TEST_SRCS = \ TEST_SRCS = \
test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp \ test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp \
@ -196,10 +196,12 @@ PLATFORM = x64
# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP # CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP
AS = ml.exe AS = ml.exe
ASFLAGS = /nologo /D_M_X86 /W3 /Cx /Zi /safeseh ASFLAGS = /nologo /D_M_X86 /W3 /Cx /Zi /safeseh
LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm rdseed.asm
LIB_OBJS = $(LIB_OBJS) rdrand-x86.obj LIB_OBJS = $(LIB_OBJS) rdrand-x86.obj rdseed-x86.obj
LDFLAGS = $(LDFLAGS) /MACHINE:X86 LDFLAGS = $(LDFLAGS) /MACHINE:X86
LDLIBS = $(LDLIBS) kernel32.lib LDLIBS = $(LDLIBS) kernel32.lib
RDRAND_OBJ = rdrand-x86.obj
RDSEED_OBJ = rdseed-x86.obj
!ENDIF !ENDIF
# May need $(VCINSTALLDIR)\bin\amd64\ml64.exe # May need $(VCINSTALLDIR)\bin\amd64\ml64.exe
@ -209,10 +211,12 @@ LDLIBS = $(LDLIBS) kernel32.lib
# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP # CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP
AS = ml64.exe AS = ml64.exe
ASFLAGS = /nologo /D_M_X64 /W3 /Cx /Zi ASFLAGS = /nologo /D_M_X64 /W3 /Cx /Zi
LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm rdseed.asm
LIB_OBJS = $(LIB_OBJS) rdrand-x64.obj x64masm.obj x64dll.obj LIB_OBJS = $(LIB_OBJS) rdrand-x64.obj rdseed-x64.obj x64masm.obj x64dll.obj
LDFLAGS = $(LDFLAGS) /MACHINE:X64 LDFLAGS = $(LDFLAGS) /MACHINE:X64
LDLIBS = $(LDLIBS) kernel32.lib LDLIBS = $(LDLIBS) kernel32.lib
RDRAND_OBJ = rdrand-x64.obj
RDSEED_OBJ = rdseed-x64.obj
!ENDIF !ENDIF
!IF "$(PLATFORM)" == "ARM" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "ARM64" || "$(PLATFORM)" == "arm64" !IF "$(PLATFORM)" == "ARM" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "ARM64" || "$(PLATFORM)" == "arm64"
@ -283,21 +287,25 @@ pch.pch: pch.h pch.cpp
$(CXX) $(CXXFLAGS) /Yc"pch.h" /Fp"pch.pch" /c pch.cpp $(CXX) $(CXXFLAGS) /Yc"pch.h" /Fp"pch.pch" /c pch.cpp
# No precompiled headers # No precompiled headers
iterhash.obj: iterhash.obj: iterhash.h iterhash.cpp
$(CXX) $(CXXFLAGS) /Y- /c iterhash.cpp $(CXX) $(CXXFLAGS) /Y- /c iterhash.cpp
dll.obj: dll.obj: dll.h dll.cpp
$(CXX) $(CXXFLAGS) /Y- /c dll.cpp $(CXX) $(CXXFLAGS) /Y- /c dll.cpp
rdrand.obj: rdrand.obj: rdrand.h rdrand.cpp
$(CXX) $(CXXFLAGS) /c rdrand.cpp $(CXX) $(CXXFLAGS) /c rdrand.cpp
# Built for x86/x64 # Built for x86/x64
rdrand-x86.obj: rdrand-x86.obj: rdrand.asm
$(AS) $(ASFLAGS) /Fo rdrand-x86.obj /c rdrand.asm $(AS) $(ASFLAGS) /Fo rdrand-x86.obj /c rdrand.asm
rdrand-x64.obj: rdrand-x64.obj: rdrand.asm
$(AS) $(ASFLAGS) /Fo rdrand-x64.obj /c rdrand.asm $(AS) $(ASFLAGS) /Fo rdrand-x64.obj /c rdrand.asm
x64masm.obj: rdseed-x86.obj: rdseed.asm
$(AS) $(ASFLAGS) /Fo rdseed-x86.obj /c rdseed.asm
rdseed-x64.obj: rdseed.asm
$(AS) $(ASFLAGS) /Fo rdseed-x64.obj /c rdseed.asm
x64masm.obj: x64masm.asm
$(AS) $(ASFLAGS) /Fo x64masm.obj /c x64masm.asm $(AS) $(ASFLAGS) /Fo x64masm.obj /c x64masm.asm
x64dll.obj: x64dll.obj: x64dll.asm
$(AS) $(ASFLAGS) /Fo x64dll.obj /c x64dll.asm $(AS) $(ASFLAGS) /Fo x64dll.obj /c x64dll.asm
# You may need to delete this on early versions of Visual Studio. # You may need to delete this on early versions of Visual Studio.

View File

@ -373,6 +373,16 @@
<Command>ml64.exe /c /nologo /D_M_X64 /W3 /Cx /Zi /Fo"$(IntDir)rdrand-x64.obj" "%(FullPath)"</Command> <Command>ml64.exe /c /nologo /D_M_X64 /W3 /Cx /Zi /Fo"$(IntDir)rdrand-x64.obj" "%(FullPath)"</Command>
<Outputs>$(IntDir)\rdrand-x64.obj;%(Outputs)</Outputs> <Outputs>$(IntDir)\rdrand-x64.obj;%(Outputs)</Outputs>
</CustomBuild> </CustomBuild>
<CustomBuild Condition="'$(Platform)'=='Win32'" Include="rdseed.asm">
<Message>Building and assembling rdseed.asm</Message>
<Command>ml.exe /c /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo"$(IntDir)rdseed-x86.obj" "%(FullPath)"</Command>
<Outputs>$(IntDir)\rdseed-x86.obj;%(Outputs)</Outputs>
</CustomBuild>
<CustomBuild Condition="'$(Platform)'=='x64'" Include="rdseed.asm">
<Message>Building and assembling rdseed.asm</Message>
<Command>ml64.exe /c /nologo /D_M_X64 /W3 /Cx /Zi /Fo"$(IntDir)rdseed-x64.obj" "%(FullPath)"</Command>
<Outputs>$(IntDir)\rdseed-x64.obj;%(Outputs)</Outputs>
</CustomBuild>
<CustomBuild Condition="'$(Platform)'=='x64' AND ('$(Configuration)'=='Debug' Or '$(Configuration)'=='Release')" Include="x64dll.asm"> <CustomBuild Condition="'$(Platform)'=='x64' AND ('$(Configuration)'=='Debug' Or '$(Configuration)'=='Release')" Include="x64dll.asm">
<Message>Building and assembling x64dll.asm</Message> <Message>Building and assembling x64dll.asm</Message>
<Command>ml64.exe /c /nologo /D_M_X64 /W3 /Zi /Fo"$(IntDir)x64dll.obj" "%(FullPath)"</Command> <Command>ml64.exe /c /nologo /D_M_X64 /W3 /Zi /Fo"$(IntDir)x64dll.obj" "%(FullPath)"</Command>

View File

@ -1064,6 +1064,9 @@
<CustomBuild Include="rdrand.asm"> <CustomBuild Include="rdrand.asm">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="rdseed.asm">
<Filter>Source Files</Filter>
</CustomBuild>
<CustomBuild Include="x64dll.asm"> <CustomBuild Include="x64dll.asm">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</CustomBuild> </CustomBuild>

View File

@ -1,9 +1,9 @@
;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. ;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
;; Copyright assigned to the Crypto++ project. ;; Copyright assigned to the Crypto++ project.
;; This ASM file provides RDRAND and RDSEED to downlevel Microsoft tool chains. ;; This ASM file provides RDRAND to downlevel Microsoft tool chains.
;; Everything "just works" under Visual Studio. Other platforms will have to ;; Everything "just works" under Visual Studio. Other platforms will
;; run MASM/MASM-64 and then link to the object files. ;; have to run MASM/MASM-64 and then link to the object files.
;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh ;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi ;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi
@ -13,11 +13,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TITLE MASM_RDRAND_GenerateBlock and MASM_RDSEED_GenerateBlock TITLE MASM_RDRAND_GenerateBlock source file
SUBTITLE Microsoft specific ASM code to utilize RDRAND and RDSEED for down level Microsoft toolchains SUBTITLE Microsoft specific ASM code to utilize RDRAND for down level Microsoft toolchains
PUBLIC MASM_RDRAND_GenerateBlock PUBLIC MASM_RDRAND_GenerateBlock
PUBLIC MASM_RDSEED_GenerateBlock
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -38,7 +37,6 @@ IFDEF _M_X86 ;; Set via the command line
;; Fastcall calling conventions exports ;; Fastcall calling conventions exports
ALIAS <@MASM_RDRAND_GenerateBlock@8> = <MASM_RDRAND_GenerateBlock> ALIAS <@MASM_RDRAND_GenerateBlock@8> = <MASM_RDRAND_GenerateBlock>
ALIAS <@MASM_RDSEED_GenerateBlock@8> = <MASM_RDSEED_GenerateBlock>
ENDIF ENDIF
@ -125,10 +123,10 @@ RDRAND_GenerateBlock_Return:
MASM_RDRAND_GenerateBlock ENDP MASM_RDRAND_GenerateBlock ENDP
ENDIF ;; _M_X86 ;; OPTION PROLOGUE:PrologueDef
;; OPTION EPILOGUE:EpilogueDef
OPTION PROLOGUE:PrologueDef ENDIF ;; _M_X86
OPTION EPILOGUE:EpilogueDef
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -223,197 +221,11 @@ RDRAND_GenerateBlock_Return:
MASM_RDRAND_GenerateBlock ENDP MASM_RDRAND_GenerateBlock ENDP
ENDIF ;; _M_X64 ;; OPTION PROLOGUE:PrologueDef
;; OPTION EPILOGUE:EpilogueDef
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IFDEF _M_X86 ;; Set via the command line
.CODE
ALIGN 8
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
;; No need for Load_Arguments due to fastcall
;; ECX (in): arg1, byte* buffer
;; EDX (in): arg2, size_t bsize
MASM_RDSEED_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
MWSIZE EQU 04h ;; machine word size
buffer EQU ecx
bsize EQU edx
;; Top of While loop
RDSEED_GenerateBlock_Top:
;; Check remaining size
cmp bsize, 0
je RDSEED_GenerateBlock_Return
RDSEED_Call_EAX:
;; RDSEED is not available prior to VS2012. Just emit
;; the byte codes using DB. This is `rdseed eax`.
DB 0Fh, 0C7h, 0F8h
;; If CF=1, the number returned by RDSEED is valid.
;; If CF=0, a random number was not available.
;; Retry immediately
jnc RDSEED_Call_EAX
RDSEED_succeeded:
cmp bsize, MWSIZE
jb RDSEED_Partial_Machine_Word
RDSEED_Full_Machine_Word:
mov DWORD PTR [buffer], eax
add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like
sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds
;; Continue
jmp RDSEED_GenerateBlock_Top
;; 1,2,3 bytes remain
RDSEED_Partial_Machine_Word:
;; Test bit 1 to see if size is at least 2
test bsize, 2
jz RDSEED_Bit_1_Not_Set
mov WORD PTR [buffer], ax
shr eax, 16
add buffer, 2
RDSEED_Bit_1_Not_Set:
;; Test bit 0 to see if size is at least 1
test bsize, 1
jz RDSEED_Bit_0_Not_Set
mov BYTE PTR [buffer], al
RDSEED_Bit_0_Not_Set:
;; We've hit all the bits
RDSEED_GenerateBlock_Return:
;; Clear artifacts
xor eax, eax
ret
MASM_RDSEED_GenerateBlock ENDP
ENDIF ;; _M_X86
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IFDEF _M_X64 ;; Set via the command line
.CODE
ALIGN 16
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
;; No need for Load_Arguments due to fastcall
;; RCX (in): arg1, byte* buffer
;; RDX (in): arg2, size_t bsize
MASM_RDSEED_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD
MWSIZE EQU 08h ;; machine word size
buffer EQU rcx
bsize EQU rdx
;; Top of While loop
RDSEED_GenerateBlock_Top:
;; Check remaining size
cmp bsize, 0
je RDSEED_GenerateBlock_Return
RDSEED_Call_RAX:
;; RDSEED is not available prior to VS2012. Just emit
;; the byte codes using DB. This is `rdseed rax`.
DB 048h, 0Fh, 0C7h, 0F8h
;; If CF=1, the number returned by RDSEED is valid.
;; If CF=0, a random number was not available.
;; Retry immediately
jnc RDSEED_Call_RAX
RDSEED_succeeded:
cmp bsize, MWSIZE
jb RDSEED_Partial_Machine_Word
RDSEED_Full_Machine_Word:
mov QWORD PTR [buffer], rax
add buffer, MWSIZE
sub bsize, MWSIZE
;; Continue
jmp RDSEED_GenerateBlock_Top
;; 1,2,3,4,5,6,7 bytes remain
RDSEED_Partial_Machine_Word:
;; Test bit 2 to see if size is at least 4
test bsize, 4
jz RDSEED_Bit_2_Not_Set
mov DWORD PTR [buffer], eax
shr rax, 32
add buffer, 4
RDSEED_Bit_2_Not_Set:
;; Test bit 1 to see if size is at least 2
test bsize, 2
jz RDSEED_Bit_1_Not_Set
mov WORD PTR [buffer], ax
shr eax, 16
add buffer, 2
RDSEED_Bit_1_Not_Set:
;; Test bit 0 to see if size is at least 1
test bsize, 1
jz RDSEED_Bit_0_Not_Set
mov BYTE PTR [buffer], al
RDSEED_Bit_0_Not_Set:
;; We've hit all the bits
RDSEED_GenerateBlock_Return:
;; Clear artifacts
xor rax, rax
ret
MASM_RDSEED_GenerateBlock ENDP
ENDIF ;; _M_X64 ENDIF ;; _M_X64
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

232
rdseed.asm Normal file
View File

@ -0,0 +1,232 @@
;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
;; Copyright assigned to the Crypto++ project.
;; This ASM file provides RDSEED to downlevel Microsoft tool chains.
;; Everything "just works" under Visual Studio. Other platforms will
;; have to run MASM/MASM-64 and then link to the object files.
;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi
;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\ml.exe" %ASFLAGS% /Fo rdrand-x86.obj /c rdrand.asm
;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\amd64\ml64.exe" %ASFLAGS64% /Fo rdrand-x64.obj /c rdrand.asm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TITLE MASM_RDSEED_GenerateBlock source file
SUBTITLE Microsoft specific ASM code to utilize RDSEED for down level Microsoft toolchains
PUBLIC MASM_RDSEED_GenerateBlock
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; C/C++ Function prototypes (both are fastcall)
;; X86:
;; extern "C" void __fastcall MASM_RDSEED_GenerateBlock(byte* ptr, size_t size);
;; X64:
;; extern "C" void __fastcall MASM_RDSEED_GenerateBlock(byte* ptr, size_t size);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IFDEF _M_X86 ;; Set via the command line
.486
.MODEL FLAT
;; Fastcall calling conventions exports
ALIAS <@MASM_RDSEED_GenerateBlock@8> = <MASM_RDSEED_GenerateBlock>
ENDIF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IFDEF _M_X86 ;; Set via the command line
.CODE
ALIGN 8
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
;; No need for Load_Arguments due to fastcall
;; ECX (in): arg1, byte* buffer
;; EDX (in): arg2, size_t bsize
MASM_RDSEED_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
MWSIZE EQU 04h ;; machine word size
buffer EQU ecx
bsize EQU edx
;; Top of While loop
RDSEED_GenerateBlock_Top:
;; Check remaining size
cmp bsize, 0
je RDSEED_GenerateBlock_Return
RDSEED_Call_EAX:
;; RDSEED is not available prior to VS2012. Just emit
;; the byte codes using DB. This is `rdseed eax`.
DB 0Fh, 0C7h, 0F8h
;; If CF=1, the number returned by RDSEED is valid.
;; If CF=0, a random number was not available.
;; Retry immediately
jnc RDSEED_Call_EAX
RDSEED_succeeded:
cmp bsize, MWSIZE
jb RDSEED_Partial_Machine_Word
RDSEED_Full_Machine_Word:
mov DWORD PTR [buffer], eax
add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like
sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds
;; Continue
jmp RDSEED_GenerateBlock_Top
;; 1,2,3 bytes remain
RDSEED_Partial_Machine_Word:
;; Test bit 1 to see if size is at least 2
test bsize, 2
jz RDSEED_Bit_1_Not_Set
mov WORD PTR [buffer], ax
shr eax, 16
add buffer, 2
RDSEED_Bit_1_Not_Set:
;; Test bit 0 to see if size is at least 1
test bsize, 1
jz RDSEED_Bit_0_Not_Set
mov BYTE PTR [buffer], al
RDSEED_Bit_0_Not_Set:
;; We've hit all the bits
RDSEED_GenerateBlock_Return:
;; Clear artifacts
xor eax, eax
ret
MASM_RDSEED_GenerateBlock ENDP
;; OPTION PROLOGUE:PrologueDef
;; OPTION EPILOGUE:EpilogueDef
ENDIF ;; _M_X86
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IFDEF _M_X64 ;; Set via the command line
.CODE
ALIGN 16
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
;; No need for Load_Arguments due to fastcall
;; RCX (in): arg1, byte* buffer
;; RDX (in): arg2, size_t bsize
MASM_RDSEED_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD
MWSIZE EQU 08h ;; machine word size
buffer EQU rcx
bsize EQU rdx
;; Top of While loop
RDSEED_GenerateBlock_Top:
;; Check remaining size
cmp bsize, 0
je RDSEED_GenerateBlock_Return
RDSEED_Call_RAX:
;; RDSEED is not available prior to VS2012. Just emit
;; the byte codes using DB. This is `rdseed rax`.
DB 048h, 0Fh, 0C7h, 0F8h
;; If CF=1, the number returned by RDSEED is valid.
;; If CF=0, a random number was not available.
;; Retry immediately
jnc RDSEED_Call_RAX
RDSEED_succeeded:
cmp bsize, MWSIZE
jb RDSEED_Partial_Machine_Word
RDSEED_Full_Machine_Word:
mov QWORD PTR [buffer], rax
add buffer, MWSIZE
sub bsize, MWSIZE
;; Continue
jmp RDSEED_GenerateBlock_Top
;; 1,2,3,4,5,6,7 bytes remain
RDSEED_Partial_Machine_Word:
;; Test bit 2 to see if size is at least 4
test bsize, 4
jz RDSEED_Bit_2_Not_Set
mov DWORD PTR [buffer], eax
shr rax, 32
add buffer, 4
RDSEED_Bit_2_Not_Set:
;; Test bit 1 to see if size is at least 2
test bsize, 2
jz RDSEED_Bit_1_Not_Set
mov WORD PTR [buffer], ax
shr eax, 16
add buffer, 2
RDSEED_Bit_1_Not_Set:
;; Test bit 0 to see if size is at least 1
test bsize, 1
jz RDSEED_Bit_0_Not_Set
mov BYTE PTR [buffer], al
RDSEED_Bit_0_Not_Set:
;; We've hit all the bits
RDSEED_GenerateBlock_Return:
;; Clear artifacts
xor rax, rax
ret
MASM_RDSEED_GenerateBlock ENDP
;; OPTION PROLOGUE:PrologueDef
;; OPTION EPILOGUE:EpilogueDef
ENDIF ;; _M_X64
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END

View File

@ -176,9 +176,8 @@ int scoped_main(int argc, char *argv[])
// A hint to help locate TestData/ and TestVectors/ after install. // A hint to help locate TestData/ and TestVectors/ after install.
SetArgvPathHint(argv[0], g_argvPathHint); SetArgvPathHint(argv[0], g_argvPathHint);
// Set a seed for reproducible results. It can be set on the command line. // Set a seed for reproducible results. If the seed is too short then
// If the seed is short then it is padded with spaces. If the seed is // it is padded with spaces. If the seed is missing then time() is used.
// missing then time() is used.
// For example: // For example:
// ./cryptest.exe v seed=abcdefg // ./cryptest.exe v seed=abcdefg
SetGlobalSeed(argc, argv, s_globalSeed); SetGlobalSeed(argc, argv, s_globalSeed);