VeraCrypt
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2019-10-29 23:15:28 (GMT)
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2019-10-30 07:52:55 (GMT)
commit7a35ecb154fc979d46dea8d97d0ad97fd4ae4140 (patch)
tree185a5ed69b1fd7cdde2d3b0e68841e76e1c13d8b
parent3b5d4771a0af5b4fc89ec77f43826b9ae2544949 (diff)
downloadVeraCrypt-7a35ecb154fc979d46dea8d97d0ad97fd4ae4140.zip
VeraCrypt-7a35ecb154fc979d46dea8d97d0ad97fd4ae4140.tar.gz
Windows: use separate assembly files for RDRAND and RDSEED in order to fix a mysterious crash when MASM_RDSEED_GenerateBlock is called after MASM_RDRAND_GenerateBlock.
-rw-r--r--src/Crypto/Crypto.vcxproj15
-rw-r--r--src/Crypto/Crypto.vcxproj.filters3
-rw-r--r--src/Crypto/Makefile.inc4
-rw-r--r--src/Crypto/Sources1
-rw-r--r--src/Crypto/rdrand_ml.asm266
-rw-r--r--src/Crypto/rdseed_ml.asm230
6 files changed, 291 insertions, 228 deletions
diff --git a/src/Crypto/Crypto.vcxproj b/src/Crypto/Crypto.vcxproj
index 027a87e..c6e0aac 100644
--- a/src/Crypto/Crypto.vcxproj
+++ b/src/Crypto/Crypto.vcxproj
@@ -403,6 +403,21 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
</CustomBuild>
+ <CustomBuild Include="rdseed_ml.asm">
+ <FileType>Document</FileType>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
+</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
+</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo %(Filename)%(Extension) &amp; ml.exe /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
+</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo %(Filename)%(Extension) &amp; ml.exe /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
+</Command>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
+ </CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/src/Crypto/Crypto.vcxproj.filters b/src/Crypto/Crypto.vcxproj.filters
index e7b3c3a..541a086 100644
--- a/src/Crypto/Crypto.vcxproj.filters
+++ b/src/Crypto/Crypto.vcxproj.filters
@@ -217,5 +217,8 @@
<CustomBuild Include="rdrand_ml.asm">
<Filter>Source Files</Filter>
</CustomBuild>
+ <CustomBuild Include="rdseed_ml.asm">
+ <Filter>Source Files</Filter>
+ </CustomBuild>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/Crypto/Makefile.inc b/src/Crypto/Makefile.inc
index 86b7a6f..c8d2dfd 100644
--- a/src/Crypto/Makefile.inc
+++ b/src/Crypto/Makefile.inc
@@ -60,4 +60,8 @@ TC_ASM_ERR_LOG = ..\Driver\build_errors_asm.log
"$(OBJ_PATH)\$(O)\rdrand_ml.obj": rdrand_ml.asm
$(VC_MLEXE) $(VC_MLFLAGS) /Fo "$@" /c rdrand_ml.asm 2>$(TC_ASM_ERR_LOG)
+
+"$(OBJ_PATH)\$(O)\rdseed_ml.obj": rdseed_ml.asm
+ $(VC_MLEXE) $(VC_MLFLAGS) /Fo "$@" /c rdseed_ml.asm 2>$(TC_ASM_ERR_LOG)
+
diff --git a/src/Crypto/Sources b/src/Crypto/Sources
index 2db68a7..9a1bef1 100644
--- a/src/Crypto/Sources
+++ b/src/Crypto/Sources
@@ -25,6 +25,7 @@ SOURCES = \
gost89_$(TC_ARCH).asm \
Aes_hw_cpu.asm \
rdrand_ml.asm \
+ rdseed_ml.asm \
Aeskey.c \
Aestab.c \
chacha-xmm.c \
diff --git a/src/Crypto/rdrand_ml.asm b/src/Crypto/rdrand_ml.asm
index 1579a15..4b85f7f 100644
--- a/src/Crypto/rdrand_ml.asm
+++ b/src/Crypto/rdrand_ml.asm
@@ -1,9 +1,9 @@
;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
;; Copyright assigned to the Crypto++ project.
-;; This ASM file provides RDRAND and 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.
+;; This ASM file provides RDRAND 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
@@ -13,11 +13,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-TITLE MASM_RDRAND_GenerateBlock and MASM_RDSEED_GenerateBlock
-SUBTITLE Microsoft specific ASM code to utilize RDRAND and RDSEED for down level Microsoft toolchains
+TITLE MASM_RDRAND_GenerateBlock source file
+SUBTITLE Microsoft specific ASM code to utilize RDRAND for down level Microsoft toolchains
PUBLIC MASM_RDRAND_GenerateBlock
-PUBLIC MASM_RDSEED_GenerateBlock
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -38,7 +37,6 @@ IFDEF _M_X86 ;; Set via the command line
;; Fastcall calling conventions exports
ALIAS <@MASM_RDRAND_GenerateBlock@8> = <MASM_RDRAND_GenerateBlock>
-ALIAS <@MASM_RDSEED_GenerateBlock@8> = <MASM_RDSEED_GenerateBlock>
ENDIF
@@ -63,13 +61,13 @@ MASM_RDRAND_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
bsize EQU edx
;; Top of While loop
-GenerateBlock_Top:
+RDRAND_GenerateBlock_Top:
;; Check remaining size
cmp bsize, 0
- je GenerateBlock_Return
+ je RDRAND_GenerateBlock_Return
-Call_RDRAND_EAX:
+RDRAND_Call_EAX:
;; RDRAND is not available prior to VS2012. Just emit
;; the byte codes using DB. This is `rdrand eax`.
DB 0Fh, 0C7h, 0F0h
@@ -78,46 +76,48 @@ Call_RDRAND_EAX:
;; If CF=0, a random number was not available.
;; Retry immediately
- jnc Call_RDRAND_EAX
+ jnc RDRAND_Call_EAX
RDRAND_succeeded:
cmp bsize, MWSIZE
- jb Partial_Machine_Word
+ jb RDRAND_Partial_Machine_Word
-Full_Machine_Word:
+RDRAND_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 GenerateBlock_Top
+ jmp RDRAND_GenerateBlock_Top
;; 1,2,3 bytes remain
-Partial_Machine_Word:
+RDRAND_Partial_Machine_Word:
;; Test bit 1 to see if size is at least 2
test bsize, 2
- jz Bit_1_Not_Set
+ jz RDRAND_Bit_1_Not_Set
mov WORD PTR [buffer], ax
shr eax, 16
add buffer, 2
-Bit_1_Not_Set:
+RDRAND_Bit_1_Not_Set:
;; Test bit 0 to see if size is at least 1
test bsize, 1
- jz Bit_0_Not_Set
+ jz RDRAND_Bit_0_Not_Set
mov BYTE PTR [buffer], al
+ ;; shr ax, 8
+ ;; add buffer, 1
-Bit_0_Not_Set:
+RDRAND_Bit_0_Not_Set:
;; We've hit all the bits
-GenerateBlock_Return:
+RDRAND_GenerateBlock_Return:
;; Clear artifacts
xor eax, eax
@@ -127,9 +127,6 @@ MASM_RDRAND_GenerateBlock ENDP
ENDIF ;; _M_X86
-OPTION PROLOGUE:PrologueDef
-OPTION EPILOGUE:EpilogueDef
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -151,13 +148,13 @@ MASM_RDRAND_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD
bsize EQU rdx
;; Top of While loop
-GenerateBlock_Top:
+RDRAND_GenerateBlock_Top:
;; Check remaining size
cmp bsize, 0
- je GenerateBlock_Return
+ je RDRAND_GenerateBlock_Return
-Call_RDRAND_RAX:
+RDRAND_Call_RAX:
;; RDRAND is not available prior to VS2012. Just emit
;; the byte codes using DB. This is `rdrand rax`.
DB 048h, 0Fh, 0C7h, 0F0h
@@ -166,254 +163,67 @@ Call_RDRAND_RAX:
;; If CF=0, a random number was not available.
;; Retry immediately
- jnc Call_RDRAND_RAX
+ jnc RDRAND_Call_RAX
RDRAND_succeeded:
cmp bsize, MWSIZE
- jb Partial_Machine_Word
-
-Full_Machine_Word:
-
- mov QWORD PTR [buffer], rax
- add buffer, MWSIZE
- sub bsize, MWSIZE
-
- ;; Continue
- jmp GenerateBlock_Top
-
- ;; 1,2,3,4,5,6,7 bytes remain
-Partial_Machine_Word:
-
- ;; Test bit 2 to see if size is at least 4
- test bsize, 4
- jz Bit_2_Not_Set
-
- mov DWORD PTR [buffer], eax
- shr rax, 32
- add buffer, 4
-
-Bit_2_Not_Set:
-
- ;; Test bit 1 to see if size is at least 2
- test bsize, 2
- jz Bit_1_Not_Set
-
- mov WORD PTR [buffer], ax
- shr eax, 16
- add buffer, 2
-
-Bit_1_Not_Set:
-
- ;; Test bit 0 to see if size is at least 1
- test bsize, 1
- jz Bit_0_Not_Set
-
- mov BYTE PTR [buffer], al
-
-Bit_0_Not_Set:
-
- ;; We've hit all the bits
-
-GenerateBlock_Return:
-
- ;; Clear artifacts
- xor rax, rax
- ret
-
-MASM_RDRAND_GenerateBlock ENDP
-
-ENDIF ;; _M_X64
-
-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
-GenerateBlock_Top:
-
- ;; Check remaining size
- cmp bsize, 0
- je GenerateBlock_Return
-
-Call_RDSEED_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 Call_RDSEED_EAX
-
-RDSEED_succeeded:
-
- cmp bsize, MWSIZE
- jb Partial_Machine_Word
-
-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 GenerateBlock_Top
-
- ;; 1,2,3 bytes remain
-Partial_Machine_Word:
-
- ;; Test bit 1 to see if size is at least 2
- test bsize, 2
- jz Bit_1_Not_Set
-
- mov WORD PTR [buffer], ax
- shr eax, 16
- add buffer, 2
-
-Bit_1_Not_Set:
-
- ;; Test bit 0 to see if size is at least 1
- test bsize, 1
- jz Bit_0_Not_Set
-
- mov BYTE PTR [buffer], al
-
-Bit_0_Not_Set:
-
- ;; We've hit all the bits
-
-GenerateBlock_Return:
-
- ;; Clear artifacts
- xor eax, eax
- ret
-
-MASM_RDSEED_GenerateBlock ENDP
-
-ENDIF ;; _M_X86
+ jb RDRAND_Partial_Machine_Word
-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
-GenerateBlock_Top:
-
- ;; Check remaining size
- cmp bsize, 0
- je GenerateBlock_Return
-
-Call_RDSEED_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 Call_RDSEED_RAX
-
-RDSEED_succeeded:
-
- cmp bsize, MWSIZE
- jb Partial_Machine_Word
-
-Full_Machine_Word:
+RDRAND_Full_Machine_Word:
mov QWORD PTR [buffer], rax
add buffer, MWSIZE
sub bsize, MWSIZE
;; Continue
- jmp GenerateBlock_Top
+ jmp RDRAND_GenerateBlock_Top
;; 1,2,3,4,5,6,7 bytes remain
-Partial_Machine_Word:
+RDRAND_Partial_Machine_Word:
;; Test bit 2 to see if size is at least 4
test bsize, 4
- jz Bit_2_Not_Set
+ jz RDRAND_Bit_2_Not_Set
mov DWORD PTR [buffer], eax
shr rax, 32
add buffer, 4
-Bit_2_Not_Set:
+RDRAND_Bit_2_Not_Set:
;; Test bit 1 to see if size is at least 2
test bsize, 2
- jz Bit_1_Not_Set
+ jz RDRAND_Bit_1_Not_Set
mov WORD PTR [buffer], ax
shr eax, 16
add buffer, 2
-Bit_1_Not_Set:
+RDRAND_Bit_1_Not_Set:
;; Test bit 0 to see if size is at least 1
test bsize, 1
- jz Bit_0_Not_Set
+ jz RDRAND_Bit_0_Not_Set
mov BYTE PTR [buffer], al
+ ;; shr ax, 8
+ ;; add buffer, 1
-Bit_0_Not_Set:
+RDRAND_Bit_0_Not_Set:
;; We've hit all the bits
-GenerateBlock_Return:
+RDRAND_GenerateBlock_Return:
;; Clear artifacts
xor rax, rax
ret
-MASM_RDSEED_GenerateBlock ENDP
+MASM_RDRAND_GenerateBlock ENDP
ENDIF ;; _M_X64
-OPTION PROLOGUE:PrologueDef
-OPTION EPILOGUE:EpilogueDef
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/src/Crypto/rdseed_ml.asm b/src/Crypto/rdseed_ml.asm
new file mode 100644
index 0000000..6070423
--- /dev/null
+++ b/src/Crypto/rdseed_ml.asm
@@ -0,0 +1,230 @@
+;; 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
+ ;; shr ax, 8
+ ;; add buffer, 1
+
+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
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+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
+ ;; shr ax, 8
+ ;; add buffer, 1
+
+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
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+END