1
+ #include <intrin.h>
2
+
3
+ #define true 1
4
+ #define false 0
5
+ #define bool unsigned __int8
6
+
7
+ #define uint8 unsigned __int8
8
+ #define uint32 unsigned __int32
9
+ #define uint16 unsigned __int16
10
+ #define uint64 unsigned __int64
11
+
12
+ // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
13
+
14
+ typedef struct {
15
+ uint32 EAX ;
16
+ uint32 EBX ;
17
+ uint32 ECX ;
18
+ uint32 EDX ;
19
+ } CPUID ;
20
+
21
+ // 1 = all supported
22
+ // 2 = only rdrand
23
+ // 0 = none
24
+
25
+ __declspec(dllexport ) uint32 GetSupportedInstructions ()
26
+ {
27
+ bool rdrand ;
28
+ bool rdseed ;
29
+ CPUID cpuId = { 0 , 0 , 0 , 0 };
30
+
31
+ __cpuid ((uint32 * )& cpuId , 1 );
32
+ rdrand = (cpuId .ECX & ((uint32 )1 << 30 )) != 0 ;
33
+
34
+ __cpuid ((uint32 * )& cpuId , 7 );
35
+ rdseed = (cpuId .EBX & ((uint32 )1 << 18 )) != 0 ;
36
+
37
+ if (rdseed ) return 1 ;
38
+ if (!rdseed && rdrand ) return 2 ;
39
+ return 0 ;
40
+ }
41
+
42
+ // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
43
+
44
+ __declspec(dllexport ) bool ReadSeed16 (uint16 * random )
45
+ {
46
+ uint16 counter = 0 ;
47
+
48
+ RETRY :
49
+ if (_rdseed16_step (random )) return 1 ;
50
+
51
+ if (++ counter == 128 ) return 0 ;
52
+ else goto RETRY ;
53
+ }
54
+
55
+ __declspec(dllexport ) bool ReadSeed32 (uint32 * random )
56
+ {
57
+ uint16 counter = 0 ;
58
+
59
+ RETRY :
60
+ if (_rdseed32_step (random )) return 1 ;
61
+
62
+ if (++ counter == 128 ) return 0 ;
63
+ else goto RETRY ;
64
+ }
65
+
66
+ __declspec(dllexport ) bool ReadSeed64 (uint64 * random )
67
+ {
68
+ uint16 counter = 0 ;
69
+
70
+ RETRY :
71
+ if (_rdseed64_step (random )) return 1 ;
72
+
73
+ if (++ counter == 128 ) return 0 ;
74
+ else goto RETRY ;
75
+ }
76
+
77
+ __declspec(dllexport ) bool ReadRandom16 (uint16 * random )
78
+ {
79
+ uint16 counter = 0 ;
80
+
81
+ RETRY :
82
+ if (_rdrand16_step (random )) return 1 ;
83
+
84
+ if (++ counter == 128 ) return 0 ;
85
+ else goto RETRY ;
86
+ }
87
+
88
+ __declspec(dllexport ) bool ReadRandom32 (uint32 * random )
89
+ {
90
+ uint16 counter = 0 ;
91
+
92
+ RETRY :
93
+ if (_rdrand32_step (random )) return 1 ;
94
+
95
+ if (++ counter == 128 ) return 0 ;
96
+ else goto RETRY ;
97
+ }
98
+
99
+ __declspec(dllexport ) bool ReadRandom64 (uint64 * random )
100
+ {
101
+ uint16 counter = 0 ;
102
+
103
+ RETRY :
104
+ if (_rdrand64_step (random )) return 1 ;
105
+
106
+ if (++ counter == 128 ) return 0 ;
107
+ else goto RETRY ;
108
+ }
109
+
110
+ // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
111
+
112
+ typedef union
113
+ {
114
+ uint64 Input64 ;
115
+ uint32 Input32 ;
116
+ uint16 Input16 ;
117
+
118
+ char Output [8 ];
119
+ } UInt64ByteView ;
120
+
121
+ __declspec(dllexport ) bool SeedNextBytes (char * buffer , uint64 offset , uint64 count )
122
+ {
123
+ if (count == 0 ) return 1 ;
124
+
125
+ UInt64ByteView dataView ;
126
+
127
+ uint64 counter = offset ;
128
+ uint64 counterMax = offset + count ;
129
+
130
+ do
131
+ {
132
+ if (counter + 8 <= counterMax )
133
+ {
134
+ if (!ReadSeed64 (& dataView .Input64 )) return false;
135
+
136
+ buffer [counter ] = dataView .Output [0 ];
137
+ buffer [++ counter ] = dataView .Output [1 ];
138
+ buffer [++ counter ] = dataView .Output [2 ];
139
+ buffer [++ counter ] = dataView .Output [3 ];
140
+ buffer [++ counter ] = dataView .Output [4 ];
141
+ buffer [++ counter ] = dataView .Output [5 ];
142
+ buffer [++ counter ] = dataView .Output [6 ];
143
+ buffer [++ counter ] = dataView .Output [7 ];
144
+ }
145
+ else if (counter + 4 <= counterMax )
146
+ {
147
+ if (!ReadSeed32 (& dataView .Input32 )) return false;
148
+
149
+ buffer [counter ] = dataView .Output [0 ];
150
+ buffer [++ counter ] = dataView .Output [1 ];
151
+ buffer [++ counter ] = dataView .Output [2 ];
152
+ buffer [++ counter ] = dataView .Output [3 ];
153
+ }
154
+ else if (counter + 2 <= counterMax )
155
+ {
156
+ if (!ReadSeed16 (& dataView .Input16 )) return false;
157
+
158
+ buffer [counter ] = dataView .Output [0 ];
159
+ buffer [++ counter ] = dataView .Output [1 ];
160
+ }
161
+ else
162
+ {
163
+ if (!ReadSeed16 (& dataView .Input16 )) return false;
164
+
165
+ buffer [counter ] = dataView .Output [0 ];
166
+ }
167
+
168
+ ++ counter ;
169
+ }
170
+ while (counter < counterMax );
171
+
172
+ return true;
173
+ }
174
+
175
+ __declspec(dllexport ) bool NextBytes (char * buffer , uint64 offset , uint64 count )
176
+ {
177
+ if (count == 0 ) return 1 ;
178
+
179
+ UInt64ByteView dataView ;
180
+
181
+ uint64 counter = offset ;
182
+ uint64 counterMax = offset + count ;
183
+
184
+ do
185
+ {
186
+ if (counter + 8 <= counterMax )
187
+ {
188
+ if (!ReadRandom64 (& dataView .Input64 )) return false;
189
+
190
+ buffer [counter ] = dataView .Output [0 ];
191
+ buffer [++ counter ] = dataView .Output [1 ];
192
+ buffer [++ counter ] = dataView .Output [2 ];
193
+ buffer [++ counter ] = dataView .Output [3 ];
194
+ buffer [++ counter ] = dataView .Output [4 ];
195
+ buffer [++ counter ] = dataView .Output [5 ];
196
+ buffer [++ counter ] = dataView .Output [6 ];
197
+ buffer [++ counter ] = dataView .Output [7 ];
198
+ }
199
+ else if (counter + 4 <= counterMax )
200
+ {
201
+ if (!ReadRandom32 (& dataView .Input32 )) return false;
202
+
203
+ buffer [counter ] = dataView .Output [0 ];
204
+ buffer [++ counter ] = dataView .Output [1 ];
205
+ buffer [++ counter ] = dataView .Output [2 ];
206
+ buffer [++ counter ] = dataView .Output [3 ];
207
+ }
208
+ else if (counter + 2 <= counterMax )
209
+ {
210
+ if (!ReadRandom16 (& dataView .Input16 )) return false;
211
+
212
+ buffer [counter ] = dataView .Output [0 ];
213
+ buffer [++ counter ] = dataView .Output [1 ];
214
+ }
215
+ else
216
+ {
217
+ if (!ReadRandom16 (& dataView .Input16 )) return false;
218
+
219
+ buffer [counter ] = dataView .Output [0 ];
220
+ }
221
+
222
+ ++ counter ;
223
+ } while (counter < counterMax );
224
+
225
+ return true;
226
+ }
0 commit comments