1 ;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
2 ;; Copyright assigned to the Crypto++ project.
4 ;; This ASM file provides RDRAND and RDSEED to downlevel Microsoft tool chains.
5 ;; Everything "just works" under Visual Studio. Other platforms will have to
6 ;; run MASM/MASM-64 and then link to the object files.
8 ;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
9 ;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi
10 ;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\ml.exe" %ASFLAGS% /Fo rdrand-x86.obj /c rdrand.asm
11 ;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\amd64\ml64.exe" %ASFLAGS64% /Fo rdrand-x64.obj /c rdrand.asm
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16 TITLE MASM_RDRAND_GenerateBlock and MASM_RDSEED_GenerateBlock
17 SUBTITLE Microsoft specific ASM code to utilize RDRAND and RDSEED for down level Microsoft toolchains
19 PUBLIC MASM_RDRAND_GenerateBlock
20 PUBLIC MASM_RDSEED_GenerateBlock
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25 ;; C/C++ Function prototypes (both are fastcall)
27 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
29 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34 IFDEF _M_X86 ;; Set via the command line
39 ;; Fastcall calling conventions exports
40 ALIAS <@MASM_RDRAND_GenerateBlock@8> = <MASM_RDRAND_GenerateBlock>
41 ALIAS <@MASM_RDSEED_GenerateBlock@8> = <MASM_RDSEED_GenerateBlock>
45 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48 IFDEF _M_X86 ;; Set via the command line
55 ;; No need for Load_Arguments due to fastcall
56 ;; ECX (in): arg1, byte* buffer
57 ;; EDX (in): arg2, size_t bsize
59 MASM_RDRAND_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
61 MWSIZE EQU 04h ;; machine word size
68 ;; Check remaining size
70 je GenerateBlock_Return
73 ;; RDRAND is not available prior to VS2012. Just emit
74 ;; the byte codes using DB. This is `rdrand eax`.
77 ;; If CF=1, the number returned by RDRAND is valid.
78 ;; If CF=0, a random number was not available.
86 jb Partial_Machine_Word
90 mov DWORD PTR [buffer], eax
91 add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like
92 sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds
100 ;; Test bit 1 to see if size is at least 2
104 mov WORD PTR [buffer], ax
110 ;; Test bit 0 to see if size is at least 1
114 mov BYTE PTR [buffer], al
118 ;; We've hit all the bits
120 GenerateBlock_Return:
126 MASM_RDRAND_GenerateBlock ENDP
130 OPTION PROLOGUE:PrologueDef
131 OPTION EPILOGUE:EpilogueDef
133 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
134 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
136 IFDEF _M_X64 ;; Set via the command line
143 ;; No need for Load_Arguments due to fastcall
144 ;; RCX (in): arg1, byte* buffer
145 ;; RDX (in): arg2, size_t bsize
147 MASM_RDRAND_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD
149 MWSIZE EQU 08h ;; machine word size
156 ;; Check remaining size
158 je GenerateBlock_Return
161 ;; RDRAND is not available prior to VS2012. Just emit
162 ;; the byte codes using DB. This is `rdrand rax`.
163 DB 048h, 0Fh, 0C7h, 0F0h
165 ;; If CF=1, the number returned by RDRAND is valid.
166 ;; If CF=0, a random number was not available.
174 jb Partial_Machine_Word
178 mov QWORD PTR [buffer], rax
183 jmp GenerateBlock_Top
185 ;; 1,2,3,4,5,6,7 bytes remain
186 Partial_Machine_Word:
188 ;; Test bit 2 to see if size is at least 4
192 mov DWORD PTR [buffer], eax
198 ;; Test bit 1 to see if size is at least 2
202 mov WORD PTR [buffer], ax
208 ;; Test bit 0 to see if size is at least 1
212 mov BYTE PTR [buffer], al
216 ;; We've hit all the bits
218 GenerateBlock_Return:
224 MASM_RDRAND_GenerateBlock ENDP
228 OPTION PROLOGUE:PrologueDef
229 OPTION EPILOGUE:EpilogueDef
231 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
232 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
234 IFDEF _M_X86 ;; Set via the command line
241 ;; No need for Load_Arguments due to fastcall
242 ;; ECX (in): arg1, byte* buffer
243 ;; EDX (in): arg2, size_t bsize
245 MASM_RDSEED_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
247 MWSIZE EQU 04h ;; machine word size
254 ;; Check remaining size
256 je GenerateBlock_Return
259 ;; RDSEED is not available prior to VS2012. Just emit
260 ;; the byte codes using DB. This is `rdseed eax`.
263 ;; If CF=1, the number returned by RDSEED is valid.
264 ;; If CF=0, a random number was not available.
272 jb Partial_Machine_Word
276 mov DWORD PTR [buffer], eax
277 add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like
278 sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds
281 jmp GenerateBlock_Top
283 ;; 1,2,3 bytes remain
284 Partial_Machine_Word:
286 ;; Test bit 1 to see if size is at least 2
290 mov WORD PTR [buffer], ax
296 ;; Test bit 0 to see if size is at least 1
300 mov BYTE PTR [buffer], al
304 ;; We've hit all the bits
306 GenerateBlock_Return:
312 MASM_RDSEED_GenerateBlock ENDP
316 OPTION PROLOGUE:PrologueDef
317 OPTION EPILOGUE:EpilogueDef
319 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
320 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
322 IFDEF _M_X64 ;; Set via the command line
329 ;; No need for Load_Arguments due to fastcall
330 ;; RCX (in): arg1, byte* buffer
331 ;; RDX (in): arg2, size_t bsize
333 MASM_RDSEED_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD
335 MWSIZE EQU 08h ;; machine word size
342 ;; Check remaining size
344 je GenerateBlock_Return
347 ;; RDSEED is not available prior to VS2012. Just emit
348 ;; the byte codes using DB. This is `rdseed rax`.
349 DB 048h, 0Fh, 0C7h, 0F8h
351 ;; If CF=1, the number returned by RDSEED is valid.
352 ;; If CF=0, a random number was not available.
360 jb Partial_Machine_Word
364 mov QWORD PTR [buffer], rax
369 jmp GenerateBlock_Top
371 ;; 1,2,3,4,5,6,7 bytes remain
372 Partial_Machine_Word:
374 ;; Test bit 2 to see if size is at least 4
378 mov DWORD PTR [buffer], eax
384 ;; Test bit 1 to see if size is at least 2
388 mov WORD PTR [buffer], ax
394 ;; Test bit 0 to see if size is at least 1
398 mov BYTE PTR [buffer], al
402 ;; We've hit all the bits
404 GenerateBlock_Return:
410 MASM_RDSEED_GenerateBlock ENDP
414 OPTION PROLOGUE:PrologueDef
415 OPTION EPILOGUE:EpilogueDef
417 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
418 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;