Crypto++ 8.0 Free C++ class library of cryptographic schemes

rdrand.asm
1 ;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
2 ;; Copyright assigned to the Crypto++ project.
3
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.
7
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
12
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
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
18
19 PUBLIC MASM_RDRAND_GenerateBlock
20 PUBLIC MASM_RDSEED_GenerateBlock
21
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24
25 ;; C/C++ Function prototypes (both are fastcall)
26 ;; X86:
27 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
28 ;; X64:
29 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
30
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33
34 IFDEF _M_X86 ;; Set via the command line
35
36 .486
37 .MODEL FLAT
38
39 ;; Fastcall calling conventions exports
40 ALIAS <@MASM_RDRAND_GenerateBlock@8> = <MASM_RDRAND_GenerateBlock>
41 ALIAS <@MASM_RDSEED_GenerateBlock@8> = <MASM_RDSEED_GenerateBlock>
42
43 ENDIF
44
45 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47
48 IFDEF _M_X86 ;; Set via the command line
49
50 .CODE
51 ALIGN 8
52 OPTION PROLOGUE:NONE
53 OPTION EPILOGUE:NONE
54
55 ;; No need for Load_Arguments due to fastcall
56 ;; ECX (in): arg1, byte* buffer
57 ;; EDX (in): arg2, size_t bsize
58
59 MASM_RDRAND_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
60
61 MWSIZE EQU 04h ;; machine word size
62 buffer EQU ecx
63 bsize EQU edx
64
65 ;; Top of While loop
66 GenerateBlock_Top:
67
68 ;; Check remaining size
69 cmp bsize, 0
70 je GenerateBlock_Return
71
72 Call_RDRAND_EAX:
73 ;; RDRAND is not available prior to VS2012. Just emit
74 ;; the byte codes using DB. This is `rdrand eax`.
75 DB 0Fh, 0C7h, 0F0h
76
77 ;; If CF=1, the number returned by RDRAND is valid.
78 ;; If CF=0, a random number was not available.
79
80 ;; Retry immediately
81 jnc Call_RDRAND_EAX
82
83 RDRAND_succeeded:
84
85 cmp bsize, MWSIZE
86 jb Partial_Machine_Word
87
88 Full_Machine_Word:
89
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
93
94 ;; Continue
95 jmp GenerateBlock_Top
96
97 ;; 1,2,3 bytes remain
98 Partial_Machine_Word:
99
100 ;; Test bit 1 to see if size is at least 2
101 test bsize, 2
102 jz Bit_1_Not_Set
103
104 mov WORD PTR [buffer], ax
105 shr eax, 16
106 add buffer, 2
107
108 Bit_1_Not_Set:
109
110 ;; Test bit 0 to see if size is at least 1
111 test bsize, 1
112 jz Bit_0_Not_Set
113
114 mov BYTE PTR [buffer], al
115
116 Bit_0_Not_Set:
117
118 ;; We've hit all the bits
119
120 GenerateBlock_Return:
121
122 ;; Clear artifacts
123 xor eax, eax
124 ret
125
126 MASM_RDRAND_GenerateBlock ENDP
127
128 ENDIF ;; _M_X86
129
130 OPTION PROLOGUE:PrologueDef
131 OPTION EPILOGUE:EpilogueDef
132
133 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
134 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
135
136 IFDEF _M_X64 ;; Set via the command line
137
138 .CODE
139 ALIGN 16
140 OPTION PROLOGUE:NONE
141 OPTION EPILOGUE:NONE
142
143 ;; No need for Load_Arguments due to fastcall
144 ;; RCX (in): arg1, byte* buffer
145 ;; RDX (in): arg2, size_t bsize
146
147 MASM_RDRAND_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD
148
149 MWSIZE EQU 08h ;; machine word size
150 buffer EQU rcx
151 bsize EQU rdx
152
153 ;; Top of While loop
154 GenerateBlock_Top:
155
156 ;; Check remaining size
157 cmp bsize, 0
158 je GenerateBlock_Return
159
160 Call_RDRAND_RAX:
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
164
165 ;; If CF=1, the number returned by RDRAND is valid.
166 ;; If CF=0, a random number was not available.
167
168 ;; Retry immediately
169 jnc Call_RDRAND_RAX
170
171 RDRAND_succeeded:
172
173 cmp bsize, MWSIZE
174 jb Partial_Machine_Word
175
176 Full_Machine_Word:
177
178 mov QWORD PTR [buffer], rax
179 add buffer, MWSIZE
180 sub bsize, MWSIZE
181
182 ;; Continue
183 jmp GenerateBlock_Top
184
185 ;; 1,2,3,4,5,6,7 bytes remain
186 Partial_Machine_Word:
187
188 ;; Test bit 2 to see if size is at least 4
189 test bsize, 4
190 jz Bit_2_Not_Set
191
192 mov DWORD PTR [buffer], eax
193 shr rax, 32
194 add buffer, 4
195
196 Bit_2_Not_Set:
197
198 ;; Test bit 1 to see if size is at least 2
199 test bsize, 2
200 jz Bit_1_Not_Set
201
202 mov WORD PTR [buffer], ax
203 shr eax, 16
204 add buffer, 2
205
206 Bit_1_Not_Set:
207
208 ;; Test bit 0 to see if size is at least 1
209 test bsize, 1
210 jz Bit_0_Not_Set
211
212 mov BYTE PTR [buffer], al
213
214 Bit_0_Not_Set:
215
216 ;; We've hit all the bits
217
218 GenerateBlock_Return:
219
220 ;; Clear artifacts
221 xor rax, rax
222 ret
223
224 MASM_RDRAND_GenerateBlock ENDP
225
226 ENDIF ;; _M_X64
227
228 OPTION PROLOGUE:PrologueDef
229 OPTION EPILOGUE:EpilogueDef
230
231 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
232 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
233
234 IFDEF _M_X86 ;; Set via the command line
235
236 .CODE
237 ALIGN 8
238 OPTION PROLOGUE:NONE
239 OPTION EPILOGUE:NONE
240
241 ;; No need for Load_Arguments due to fastcall
242 ;; ECX (in): arg1, byte* buffer
243 ;; EDX (in): arg2, size_t bsize
244
245 MASM_RDSEED_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
246
247 MWSIZE EQU 04h ;; machine word size
248 buffer EQU ecx
249 bsize EQU edx
250
251 ;; Top of While loop
252 GenerateBlock_Top:
253
254 ;; Check remaining size
255 cmp bsize, 0
256 je GenerateBlock_Return
257
258 Call_RDSEED_EAX:
259 ;; RDSEED is not available prior to VS2012. Just emit
260 ;; the byte codes using DB. This is `rdseed eax`.
261 DB 0Fh, 0C7h, 0F8h
262
263 ;; If CF=1, the number returned by RDSEED is valid.
264 ;; If CF=0, a random number was not available.
265
266 ;; Retry immediately
267 jnc Call_RDSEED_EAX
268
269 RDSEED_succeeded:
270
271 cmp bsize, MWSIZE
272 jb Partial_Machine_Word
273
274 Full_Machine_Word:
275
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
279
280 ;; Continue
281 jmp GenerateBlock_Top
282
283 ;; 1,2,3 bytes remain
284 Partial_Machine_Word:
285
286 ;; Test bit 1 to see if size is at least 2
287 test bsize, 2
288 jz Bit_1_Not_Set
289
290 mov WORD PTR [buffer], ax
291 shr eax, 16
292 add buffer, 2
293
294 Bit_1_Not_Set:
295
296 ;; Test bit 0 to see if size is at least 1
297 test bsize, 1
298 jz Bit_0_Not_Set
299
300 mov BYTE PTR [buffer], al
301
302 Bit_0_Not_Set:
303
304 ;; We've hit all the bits
305
306 GenerateBlock_Return:
307
308 ;; Clear artifacts
309 xor eax, eax
310 ret
311
312 MASM_RDSEED_GenerateBlock ENDP
313
314 ENDIF ;; _M_X86
315
316 OPTION PROLOGUE:PrologueDef
317 OPTION EPILOGUE:EpilogueDef
318
319 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
320 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
321
322 IFDEF _M_X64 ;; Set via the command line
323
324 .CODE
325 ALIGN 16
326 OPTION PROLOGUE:NONE
327 OPTION EPILOGUE:NONE
328
329 ;; No need for Load_Arguments due to fastcall
330 ;; RCX (in): arg1, byte* buffer
331 ;; RDX (in): arg2, size_t bsize
332
333 MASM_RDSEED_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD
334
335 MWSIZE EQU 08h ;; machine word size
336 buffer EQU rcx
337 bsize EQU rdx
338
339 ;; Top of While loop
340 GenerateBlock_Top:
341
342 ;; Check remaining size
343 cmp bsize, 0
344 je GenerateBlock_Return
345
346 Call_RDSEED_RAX:
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
350
351 ;; If CF=1, the number returned by RDSEED is valid.
352 ;; If CF=0, a random number was not available.
353
354 ;; Retry immediately
355 jnc Call_RDSEED_RAX
356
357 RDSEED_succeeded:
358
359 cmp bsize, MWSIZE
360 jb Partial_Machine_Word
361
362 Full_Machine_Word:
363
364 mov QWORD PTR [buffer], rax
365 add buffer, MWSIZE
366 sub bsize, MWSIZE
367
368 ;; Continue
369 jmp GenerateBlock_Top
370
371 ;; 1,2,3,4,5,6,7 bytes remain
372 Partial_Machine_Word:
373
374 ;; Test bit 2 to see if size is at least 4
375 test bsize, 4
376 jz Bit_2_Not_Set
377
378 mov DWORD PTR [buffer], eax
379 shr rax, 32
380 add buffer, 4
381
382 Bit_2_Not_Set:
383
384 ;; Test bit 1 to see if size is at least 2
385 test bsize, 2
386 jz Bit_1_Not_Set
387
388 mov WORD PTR [buffer], ax
389 shr eax, 16
390 add buffer, 2
391
392 Bit_1_Not_Set:
393
394 ;; Test bit 0 to see if size is at least 1
395 test bsize, 1
396 jz Bit_0_Not_Set
397
398 mov BYTE PTR [buffer], al
399
400 Bit_0_Not_Set:
401
402 ;; We've hit all the bits
403
404 GenerateBlock_Return:
405
406 ;; Clear artifacts
407 xor rax, rax
408 ret
409
410 MASM_RDSEED_GenerateBlock ENDP
411
412 ENDIF ;; _M_X64
413
414 OPTION PROLOGUE:PrologueDef
415 OPTION EPILOGUE:EpilogueDef
416
417 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
418 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
419
420 END