1#[cfg(target_arch = "x86_64")]
12use core::arch::x86_64::{
13 _rdrand16_step, _rdrand32_step, _rdrand64_step, _rdseed16_step, _rdseed32_step, _rdseed64_step,
14};
15
16#[cfg(target_arch = "x86")]
17use core::arch::x86::{_rdrand16_step, _rdrand32_step, _rdseed16_step, _rdseed32_step};
18
19#[inline(always)]
24pub unsafe fn rdrand16(e: &mut u16) -> bool {
25 _rdrand16_step(e) == 1
26}
27
28#[inline(always)]
33pub unsafe fn rdrand32(e: &mut u32) -> bool {
34 _rdrand32_step(e) == 1
35}
36
37#[cfg(target_arch = "x86_64")]
42#[inline(always)]
43pub unsafe fn rdrand64(e: &mut u64) -> bool {
44 _rdrand64_step(e) == 1
45}
46
47pub trait RdRand {
49 unsafe fn fill_random(&mut self) -> bool;
54}
55
56impl RdRand for u8 {
57 unsafe fn fill_random(&mut self) -> bool {
62 let mut r: u16 = 0;
63 let ret = rdrand16(&mut r);
64 *self = r as u8;
65 ret
66 }
67}
68
69impl RdRand for u16 {
70 unsafe fn fill_random(&mut self) -> bool {
75 rdrand16(self)
76 }
77}
78
79impl RdRand for u32 {
80 unsafe fn fill_random(&mut self) -> bool {
85 rdrand32(self)
86 }
87}
88
89#[cfg(target_arch = "x86_64")]
90impl RdRand for u64 {
91 unsafe fn fill_random(&mut self) -> bool {
96 rdrand64(self)
97 }
98}
99
100pub unsafe fn rdrand_slice<T: RdRand>(buffer: &mut [T]) -> bool {
107 let mut worked = true;
108 for element in buffer {
109 worked &= element.fill_random();
110 }
111 worked
112}
113
114#[inline(always)]
119pub unsafe fn rdseed16(e: &mut u16) -> bool {
120 _rdseed16_step(e) == 1
121}
122
123#[inline(always)]
128pub unsafe fn rdseed32(e: &mut u32) -> bool {
129 _rdseed32_step(e) == 1
130}
131
132#[cfg(target_arch = "x86_64")]
137#[inline(always)]
138pub unsafe fn rdseed64(e: &mut u64) -> bool {
139 _rdseed64_step(e) == 1
140}
141
142pub trait RdSeed {
144 unsafe fn fill_random(&mut self) -> bool;
149}
150
151impl RdSeed for u8 {
152 unsafe fn fill_random(&mut self) -> bool {
157 let mut r: u16 = 0;
158 let ret = rdseed16(&mut r);
159 *self = r as u8;
160 ret
161 }
162}
163
164impl RdSeed for u16 {
165 unsafe fn fill_random(&mut self) -> bool {
170 rdseed16(self)
171 }
172}
173
174impl RdSeed for u32 {
175 unsafe fn fill_random(&mut self) -> bool {
180 rdseed32(self)
181 }
182}
183
184#[cfg(target_arch = "x86_64")]
185impl RdSeed for u64 {
186 unsafe fn fill_random(&mut self) -> bool {
191 rdseed64(self)
192 }
193}
194
195pub unsafe fn rdseed_slice<T: RdSeed>(buffer: &mut [T]) -> bool {
203 let mut worked = true;
204 for element in buffer {
205 worked &= element.fill_random();
206 }
207 worked
208}
209
210#[cfg(all(test, feature = "utest"))]
211mod test {
212 use super::*;
213
214 #[test]
215 fn rdrand_u64() {
216 let has_rdrand = crate::cpuid::CpuId::new()
217 .get_feature_info()
218 .map_or(false, |finfo| finfo.has_rdrand());
219 if !has_rdrand {
220 return;
221 }
222
223 unsafe {
224 let mut buf: [u64; 4] = [0, 0, 0, 0];
225 rdrand_slice(&mut buf);
226
227 assert_ne!(buf[0], 0);
228 assert_ne!(buf[1], 0);
229 assert_ne!(buf[2], 0);
230 assert_ne!(buf[3], 0);
231 }
232 }
233
234 #[test]
235 fn rdrand_u32() {
236 let has_rdrand = crate::cpuid::CpuId::new()
237 .get_feature_info()
238 .map_or(false, |finfo| finfo.has_rdrand());
239 if !has_rdrand {
240 return;
241 }
242
243 unsafe {
244 let mut buf: [u32; 4] = [0, 0, 0, 0];
245 rdrand_slice(&mut buf);
246
247 assert_ne!(buf[0], 0);
248 assert_ne!(buf[1], 0);
249 assert_ne!(buf[2], 0);
250 assert_ne!(buf[3], 0);
251 }
252 }
253
254 #[test]
255 fn rdrand_u16() {
256 let has_rdrand = crate::cpuid::CpuId::new()
257 .get_feature_info()
258 .map_or(false, |finfo| finfo.has_rdrand());
259 if !has_rdrand {
260 return;
261 }
262
263 unsafe {
264 let mut buf: [u16; 4] = [0, 0, 0, 0];
265 rdrand_slice(&mut buf);
266 assert_ne!(buf[0], 0);
267 assert_ne!(buf[1], 0);
268 assert_ne!(buf[2], 0);
269 assert_ne!(buf[3], 0);
270 }
271 }
272
273 #[test]
274 fn rdseed_u64() {
275 let has_rdseed = crate::cpuid::CpuId::new()
276 .get_extended_feature_info()
277 .map_or(false, |efinfo| efinfo.has_rdseed());
278 if !has_rdseed {
279 return;
280 }
281
282 unsafe {
283 let mut buf: [u64; 4] = [0, 0, 0, 0];
284 rdseed_slice(&mut buf);
285
286 assert_ne!(buf[0], 0);
287 assert_ne!(buf[1], 0);
288 assert_ne!(buf[2], 0);
289 assert_ne!(buf[3], 0);
290 }
291 }
292
293 #[test]
294 fn rdseed_u32() {
295 let has_rdseed = crate::cpuid::CpuId::new()
296 .get_extended_feature_info()
297 .map_or(false, |efinfo| efinfo.has_rdseed());
298 if !has_rdseed {
299 return;
300 }
301
302 unsafe {
303 let mut buf: [u32; 4] = [0, 0, 0, 0];
304 rdseed_slice(&mut buf);
305
306 assert_ne!(buf[0], 0);
307 assert_ne!(buf[1], 0);
308 assert_ne!(buf[2], 0);
309 assert_ne!(buf[3], 0);
310 }
311 }
312
313 #[test]
314 fn rdseed_u16() {
315 let has_rdseed = crate::cpuid::CpuId::new()
316 .get_extended_feature_info()
317 .map_or(false, |efinfo| efinfo.has_rdseed());
318 if !has_rdseed {
319 return;
320 }
321
322 unsafe {
323 let mut buf: [u16; 4] = [0, 0, 0, 0];
324 rdseed_slice(&mut buf);
325 assert!(buf[0] > 0 || buf[1] > 0 || buf[2] > 0 || buf[3] > 0);
327 }
328 }
329
330 #[test]
331 fn rdrand_u8() {
332 let has_rdseed = crate::cpuid::CpuId::new()
333 .get_extended_feature_info()
334 .map_or(false, |efinfo| efinfo.has_rdseed());
335 if !has_rdseed {
336 return;
337 }
338
339 unsafe {
340 let mut buf: [u8; 4] = [0, 0, 0, 0];
341 rdrand_slice(&mut buf);
342 assert!(buf[0] > 0 || buf[1] > 0 || buf[2] > 0 || buf[3] > 0);
344 }
345 }
346
347 #[test]
348 fn rdseed_u8() {
349 let has_rdseed = crate::cpuid::CpuId::new()
350 .get_extended_feature_info()
351 .map_or(false, |efinfo| efinfo.has_rdseed());
352 if !has_rdseed {
353 return;
354 }
355
356 unsafe {
357 let mut buf: [u8; 4] = [0, 0, 0, 0];
358 rdseed_slice(&mut buf);
359 assert!(buf[0] > 0 || buf[1] > 0 || buf[2] > 0 || buf[3] > 0);
361 }
362 }
363}