@@ -11,31 +11,38 @@ use crate::Error;
1111use core:: mem;
1212use core:: arch:: x86_64:: _rdrand64_step;
1313use core:: num:: NonZeroU32 ;
14-
15- #[ cfg( not( target_feature = "rdrand" ) ) ]
16- compile_error ! ( "enable rdrand target feature!" ) ;
14+ use std_detect:: is_x86_feature_detected;
1715
1816// Recommendation from "Intel® Digital Random Number Generator (DRNG) Software
1917// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures
2018// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1.
2119const RETRY_LIMIT : usize = 10 ;
2220const WORD_SIZE : usize = mem:: size_of :: < u64 > ( ) ;
2321
24- fn rdrand ( ) -> Result < [ u8 ; WORD_SIZE ] , Error > {
22+ #[ target_feature( enable = "rdrand" ) ]
23+ unsafe fn rdrand ( ) -> Result < [ u8 ; WORD_SIZE ] , Error > {
2524 for _ in 0 ..RETRY_LIMIT {
26- unsafe {
27- // SAFETY: we've checked RDRAND support, and u64 can have any value.
28- let mut el = mem:: uninitialized ( ) ;
29- if _rdrand64_step ( & mut el) == 1 {
30- return Ok ( el. to_ne_bytes ( ) ) ;
31- }
32- } ;
25+ let mut el = mem:: uninitialized ( ) ;
26+ if _rdrand64_step ( & mut el) == 1 {
27+ return Ok ( el. to_ne_bytes ( ) ) ;
28+ }
3329 }
3430 error ! ( "RDRAND failed, CPU issue likely" ) ;
3531 Err ( Error :: UNKNOWN )
3632}
3733
3834pub fn getrandom_inner ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
35+ if !is_x86_feature_detected ! ( "rdrand" ) {
36+ return Err ( Error :: UNAVAILABLE ) ;
37+ }
38+
39+ // SAFETY: After this point, rdrand is supported, so calling the rdrand
40+ // functions is not undefined behavior.
41+ unsafe { rdrand_exact ( dest) }
42+ }
43+
44+ #[ target_feature( enable = "rdrand" ) ]
45+ unsafe fn rdrand_exact ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
3946 // We use chunks_exact_mut instead of chunks_mut as it allows almost all
4047 // calls to memcpy to be elided by the compiler.
4148 let mut chunks = dest. chunks_exact_mut ( WORD_SIZE ) ;
0 commit comments