Crypto++  8.8
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 to downlevel Microsoft tool chains.
5 ;; Everything "just works" under Visual Studio. Other platforms will
6 ;; have to 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 source file
17 SUBTITLE Microsoft specific ASM code to utilize RDRAND for down level Microsoft toolchains
18 
19 PUBLIC MASM_RDRAND_GenerateBlock
20 
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 
24 ;; C/C++ Function prototypes (both are fastcall)
25 ;; X86:
26 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
27 ;; X64:
28 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
29 
30 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 
33 IFDEF _M_X86 ;; Set via the command line
34 
35 .486
36 .MODEL FLAT
37 
38 ;; Fastcall calling conventions exports
39 ALIAS <@MASM_RDRAND_GenerateBlock@8> = <MASM_RDRAND_GenerateBlock>
40 
41 ENDIF
42 
43 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45 
46 IFDEF _M_X86 ;; Set via the command line
47 
48 .CODE
49 ALIGN 8
50 OPTION PROLOGUE:NONE
51 OPTION EPILOGUE:NONE
52 
53 ;; No need for Load_Arguments due to fastcall
54 ;; ECX (in): arg1, byte* buffer
55 ;; EDX (in): arg2, size_t bsize
56 
57 MASM_RDRAND_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
58 
59  MWSIZE EQU 04h ;; machine word size
60  buffer EQU ecx
61  bsize EQU edx
62 
63  ;; Top of While loop
64 RDRAND_GenerateBlock_Top:
65 
66  ;; Check remaining size
67  cmp bsize, 0
68  je RDRAND_GenerateBlock_Return
69 
70 RDRAND_Call_EAX:
71  ;; RDRAND is not available prior to VS2012. Just emit
72  ;; the byte codes using DB. This is `rdrand eax`.
73  DB 0Fh, 0C7h, 0F0h
74 
75  ;; If CF=1, the number returned by RDRAND is valid.
76  ;; If CF=0, a random number was not available.
77 
78  ;; Retry immediately
79  jnc RDRAND_Call_EAX
80 
81 RDRAND_succeeded:
82 
83  cmp bsize, MWSIZE
84  jb RDRAND_Partial_Machine_Word
85 
86 RDRAND_Full_Machine_Word:
87 
88  mov DWORD PTR [buffer], eax
89  add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like
90  sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds
91 
92  ;; Continue
93  jmp RDRAND_GenerateBlock_Top
94 
95  ;; 1,2,3 bytes remain
96 RDRAND_Partial_Machine_Word:
97 
98  ;; Test bit 1 to see if size is at least 2
99  test bsize, 2
100  jz RDRAND_Bit_1_Not_Set
101 
102  mov WORD PTR [buffer], ax
103  shr eax, 16
104  add buffer, 2
105 
106 RDRAND_Bit_1_Not_Set:
107 
108  ;; Test bit 0 to see if size is at least 1
109  test bsize, 1
110  jz RDRAND_Bit_0_Not_Set
111 
112  mov BYTE PTR [buffer], al
113  ;; shr ax, 8
114  ;; add buffer, 1
115 
116 RDRAND_Bit_0_Not_Set:
117 
118  ;; We've hit all the bits
119 
120 RDRAND_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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
131 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
132 
133 IFDEF _M_X64 ;; Set via the command line
134 
135 .CODE
136 ALIGN 16
137 OPTION PROLOGUE:NONE
138 OPTION EPILOGUE:NONE
139 
140 ;; No need for Load_Arguments due to fastcall
141 ;; RCX (in): arg1, byte* buffer
142 ;; RDX (in): arg2, size_t bsize
143 
144 MASM_RDRAND_GenerateBlock PROC FRAME ;; arg1:QWORD, arg2:QWORD
145 
146  MWSIZE EQU 08h ;; machine word size
147  buffer EQU rcx
148  bsize EQU rdx
149 
150 .endprolog
151 
152  ;; Top of While loop
153 RDRAND_GenerateBlock_Top:
154 
155  ;; Check remaining size
156  cmp bsize, 0
157  je RDRAND_GenerateBlock_Return
158 
159 RDRAND_Call_RAX:
160  ;; RDRAND is not available prior to VS2012. Just emit
161  ;; the byte codes using DB. This is `rdrand rax`.
162  DB 048h, 0Fh, 0C7h, 0F0h
163 
164  ;; If CF=1, the number returned by RDRAND is valid.
165  ;; If CF=0, a random number was not available.
166 
167  ;; Retry immediately
168  jnc RDRAND_Call_RAX
169 
170 RDRAND_succeeded:
171 
172  cmp bsize, MWSIZE
173  jb RDRAND_Partial_Machine_Word
174 
175 RDRAND_Full_Machine_Word:
176 
177  mov QWORD PTR [buffer], rax
178  add buffer, MWSIZE
179  sub bsize, MWSIZE
180 
181  ;; Continue
182  jmp RDRAND_GenerateBlock_Top
183 
184  ;; 1,2,3,4,5,6,7 bytes remain
185 RDRAND_Partial_Machine_Word:
186 
187  ;; Test bit 2 to see if size is at least 4
188  test bsize, 4
189  jz RDRAND_Bit_2_Not_Set
190 
191  mov DWORD PTR [buffer], eax
192  shr rax, 32
193  add buffer, 4
194 
195 RDRAND_Bit_2_Not_Set:
196 
197  ;; Test bit 1 to see if size is at least 2
198  test bsize, 2
199  jz RDRAND_Bit_1_Not_Set
200 
201  mov WORD PTR [buffer], ax
202  shr eax, 16
203  add buffer, 2
204 
205 RDRAND_Bit_1_Not_Set:
206 
207  ;; Test bit 0 to see if size is at least 1
208  test bsize, 1
209  jz RDRAND_Bit_0_Not_Set
210 
211  mov BYTE PTR [buffer], al
212  ;; shr ax, 8
213  ;; add buffer, 1
214 
215 RDRAND_Bit_0_Not_Set:
216 
217  ;; We've hit all the bits
218 
219 RDRAND_GenerateBlock_Return:
220 
221  ;; Clear artifacts
222  xor rax, rax
223  ret
224 
225 MASM_RDRAND_GenerateBlock ENDP
226 
227 ENDIF ;; _M_X64
228 
229 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
230 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
231 
232 END