From 7a35ecb154fc979d46dea8d97d0ad97fd4ae4140 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 30 Oct 2019 00:15:28 +0100 Subject: 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. --- src/Crypto/Crypto.vcxproj | 15 +++ src/Crypto/Crypto.vcxproj.filters | 3 + src/Crypto/Makefile.inc | 4 + src/Crypto/Sources | 1 + src/Crypto/rdrand_ml.asm | 266 ++++++-------------------------------- src/Crypto/rdseed_ml.asm | 230 ++++++++++++++++++++++++++++++++ 6 files changed, 291 insertions(+), 228 deletions(-) create mode 100644 src/Crypto/rdseed_ml.asm diff --git a/src/Crypto/Crypto.vcxproj b/src/Crypto/Crypto.vcxproj index 027a87e0..c6e0aac5 100644 --- a/src/Crypto/Crypto.vcxproj +++ b/src/Crypto/Crypto.vcxproj @@ -397,6 +397,21 @@ echo %(Filename)%(Extension) & ml.exe /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" echo %(Filename)%(Extension) & ml.exe /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) + + + Document + echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + echo %(Filename)%(Extension) & ml.exe /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + echo %(Filename)%(Extension) & ml.exe /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) diff --git a/src/Crypto/Crypto.vcxproj.filters b/src/Crypto/Crypto.vcxproj.filters index e7b3c3a5..541a0867 100644 --- a/src/Crypto/Crypto.vcxproj.filters +++ b/src/Crypto/Crypto.vcxproj.filters @@ -217,5 +217,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/src/Crypto/Makefile.inc b/src/Crypto/Makefile.inc index 86b7a6fa..c8d2dfdf 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 2db68a7a..9a1bef14 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 1579a155..4b85f7fc 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> = -ALIAS <@MASM_RDSEED_GenerateBlock@8> = 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 00000000..60704230 --- /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> = + +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 -- cgit v1.2.3