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 RDSEED 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 16TITLE MASM_RDSEED_GenerateBlock source file 17SUBTITLE Microsoft specific ASM code to utilize RDSEED for down level Microsoft toolchains 18 19PUBLIC MASM_RDSEED_GenerateBlock 20 21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 23 24;; C/C++ Function prototypes (both are fastcall) 25;; X86: 26;; extern "C" void __fastcall MASM_RDSEED_GenerateBlock(byte* ptr, size_t size); 27;; X64: 28;; extern "C" void __fastcall MASM_RDSEED_GenerateBlock(byte* ptr, size_t size); 29 30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32 33IFDEF _M_X86 ;; Set via the command line 34 35.486 36.MODEL FLAT 37 38;; Fastcall calling conventions exports 39ALIAS <@MASM_RDSEED_GenerateBlock@8> = <MASM_RDSEED_GenerateBlock> 40 41ENDIF 42 43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 45 46IFDEF _M_X86 ;; Set via the command line 47 48.CODE 49ALIGN 8 50OPTION PROLOGUE:NONE 51OPTION 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 57MASM_RDSEED_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 64RDSEED_GenerateBlock_Top: 65 66 ;; Check remaining size 67 cmp bsize, 0 68 je RDSEED_GenerateBlock_Return 69 70RDSEED_Call_EAX: 71 ;; RDSEED is not available prior to VS2012. Just emit 72 ;; the byte codes using DB. This is `rdseed eax`. 73 DB 0Fh, 0C7h, 0F8h 74 75 ;; If CF=1, the number returned by RDSEED is valid. 76 ;; If CF=0, a random number was not available. 77 78 ;; Retry immediately 79 jnc RDSEED_Call_EAX 80 81RDSEED_succeeded: 82 83 cmp bsize, MWSIZE 84 jb RDSEED_Partial_Machine_Word 85 86RDSEED_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 RDSEED_GenerateBlock_Top 94 95 ;; 1,2,3 bytes remain 96RDSEED_Partial_Machine_Word: 97 98 ;; Test bit 1 to see if size is at least 2 99 test bsize, 2 100 jz RDSEED_Bit_1_Not_Set 101 102 mov WORD PTR [buffer], ax 103 shr eax, 16 104 add buffer, 2 105 106RDSEED_Bit_1_Not_Set: 107 108 ;; Test bit 0 to see if size is at least 1 109 test bsize, 1 110 jz RDSEED_Bit_0_Not_Set 111 112 mov BYTE PTR [buffer], al 113 ;; shr ax, 8 114 ;; add buffer, 1 115 116RDSEED_Bit_0_Not_Set: 117 118 ;; We've hit all the bits 119 120RDSEED_GenerateBlock_Return: 121 122 ;; Clear artifacts 123 xor eax, eax 124 ret 125 126MASM_RDSEED_GenerateBlock ENDP 127 128ENDIF ;; _M_X86 129 130;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 131;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 132 133IFDEF _M_X64 ;; Set via the command line 134 135.CODE 136ALIGN 16 137OPTION PROLOGUE:NONE 138OPTION 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 144MASM_RDSEED_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD 145 146 MWSIZE EQU 08h ;; machine word size 147 buffer EQU rcx 148 bsize EQU rdx 149 150 ;; Top of While loop 151RDSEED_GenerateBlock_Top: 152 153 ;; Check remaining size 154 cmp bsize, 0 155 je RDSEED_GenerateBlock_Return 156 157RDSEED_Call_RAX: 158 ;; RDSEED is not available prior to VS2012. Just emit 159 ;; the byte codes using DB. This is `rdseed rax`. 160 DB 048h, 0Fh, 0C7h, 0F8h 161 162 ;; If CF=1, the number returned by RDSEED is valid. 163 ;; If CF=0, a random number was not available. 164 165 ;; Retry immediately 166 jnc RDSEED_Call_RAX 167 168RDSEED_succeeded: 169 170 cmp bsize, MWSIZE 171 jb RDSEED_Partial_Machine_Word 172 173RDSEED_Full_Machine_Word: 174 175 mov QWORD PTR [buffer], rax 176 add buffer, MWSIZE 177 sub bsize, MWSIZE 178 179 ;; Continue 180 jmp RDSEED_GenerateBlock_Top 181 182 ;; 1,2,3,4,5,6,7 bytes remain 183RDSEED_Partial_Machine_Word: 184 185 ;; Test bit 2 to see if size is at least 4 186 test bsize, 4 187 jz RDSEED_Bit_2_Not_Set 188 189 mov DWORD PTR [buffer], eax 190 shr rax, 32 191 add buffer, 4 192 193RDSEED_Bit_2_Not_Set: 194 195 ;; Test bit 1 to see if size is at least 2 196 test bsize, 2 197 jz RDSEED_Bit_1_Not_Set 198 199 mov WORD PTR [buffer], ax 200 shr eax, 16 201 add buffer, 2 202 203RDSEED_Bit_1_Not_Set: 204 205 ;; Test bit 0 to see if size is at least 1 206 test bsize, 1 207 jz RDSEED_Bit_0_Not_Set 208 209 mov BYTE PTR [buffer], al 210 ;; shr ax, 8 211 ;; add buffer, 1 212 213RDSEED_Bit_0_Not_Set: 214 215 ;; We've hit all the bits 216 217RDSEED_GenerateBlock_Return: 218 219 ;; Clear artifacts 220 xor rax, rax 221 ret 222 223MASM_RDSEED_GenerateBlock ENDP 224 225ENDIF ;; _M_X64 226 227;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 229 230END 231