@@ -137,9 +137,11 @@ mod imp {
137137 }
138138}
139139
140- #[ cfg( any ( target_os = "macos" , target_os = "ios" , target_os = "watchos" ) ) ]
140+ #[ cfg( target_os = "macos" ) ]
141141mod imp {
142- use crate :: io;
142+ use crate :: fs:: File ;
143+ use crate :: io:: Read ;
144+ use crate :: sys:: os:: errno;
143145 use crate :: sys:: weak:: weak;
144146 use libc:: { c_int, c_void, size_t} ;
145147
@@ -153,72 +155,22 @@ mod imp {
153155 for s in v. chunks_mut ( 256 ) {
154156 let ret = unsafe { f ( s. as_mut_ptr ( ) as * mut c_void , s. len ( ) ) } ;
155157 if ret == -1 {
156- panic ! ( "unexpected getentropy error: {}" , io :: Error :: last_os_error ( ) ) ;
158+ panic ! ( "unexpected getentropy error: {}" , errno ( ) ) ;
157159 }
158160 }
159161 true
160162 } )
161163 . unwrap_or ( false )
162164 }
163165
164- #[ cfg( target_os = "macos" ) ]
165- fn fallback_fill_bytes ( v : & mut [ u8 ] ) {
166- use crate :: fs:: File ;
167- use crate :: io:: Read ;
168-
169- let mut file = File :: open ( "/dev/urandom" ) . expect ( "failed to open /dev/urandom" ) ;
170- file. read_exact ( v) . expect ( "failed to read /dev/urandom" )
171- }
172-
173- // On iOS and MacOS `SecRandomCopyBytes` calls `CCRandomCopyBytes` with
174- // `kCCRandomDefault`. `CCRandomCopyBytes` manages a CSPRNG which is seeded
175- // from `/dev/random` and which runs on its own thread accessed via GCD.
176- //
177- // This is very heavyweight compared to the alternatives, but they may not be usable:
178- // - `getentropy` was added in iOS 10, but we support a minimum of iOS 7
179- // - `/dev/urandom` is not accessible inside the iOS app sandbox.
180- //
181- // Therefore `SecRandomCopyBytes` is only used on older iOS versions where no
182- // better options are present.
183- #[ cfg( target_os = "ios" ) ]
184- fn fallback_fill_bytes ( v : & mut [ u8 ] ) {
185- use crate :: ptr;
186-
187- enum SecRandom { }
188-
189- #[ allow( non_upper_case_globals) ]
190- const kSecRandomDefault: * const SecRandom = ptr:: null ( ) ;
191-
192- extern "C" {
193- fn SecRandomCopyBytes ( rnd : * const SecRandom , count : size_t , bytes : * mut u8 ) -> c_int ;
194- }
195-
196- let ret = unsafe { SecRandomCopyBytes ( kSecRandomDefault, v. len ( ) , v. as_mut_ptr ( ) ) } ;
197- if ret == -1 {
198- panic ! ( "couldn't generate random bytes: {}" , io:: Error :: last_os_error( ) ) ;
199- }
200- }
201-
202- // All supported versions of watchOS (>= 5) have support for `getentropy`.
203- #[ cfg( target_os = "watchos" ) ]
204- #[ cold]
205- fn fallback_fill_bytes ( _: & mut [ u8 ] ) {
206- unreachable ! ( )
207- }
208-
209166 pub fn fill_bytes ( v : & mut [ u8 ] ) {
210167 if getentropy_fill_bytes ( v) {
211168 return ;
212169 }
213170
214- // Older macOS versions (< 10.12) don't support `getentropy`. Fallback to
215- // reading from `/dev/urandom` on these systems.
216- //
217- // Older iOS versions (< 10) don't support it either. Fallback to
218- // `SecRandomCopyBytes` on these systems. On watchOS, this is unreachable
219- // because the minimum supported version is 5 while `getentropy` became accessible
220- // in 3.
221- fallback_fill_bytes ( v)
171+ // for older macos which doesn't support getentropy
172+ let mut file = File :: open ( "/dev/urandom" ) . expect ( "failed to open /dev/urandom" ) ;
173+ file. read_exact ( v) . expect ( "failed to read /dev/urandom" )
222174 }
223175}
224176
@@ -237,6 +189,36 @@ mod imp {
237189 }
238190}
239191
192+ // On iOS and MacOS `SecRandomCopyBytes` calls `CCRandomCopyBytes` with
193+ // `kCCRandomDefault`. `CCRandomCopyBytes` manages a CSPRNG which is seeded
194+ // from `/dev/random` and which runs on its own thread accessed via GCD.
195+ // This seems needlessly heavyweight for the purposes of generating two u64s
196+ // once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
197+ // only used on iOS where direct access to `/dev/urandom` is blocked by the
198+ // sandbox.
199+ #[ cfg( any( target_os = "ios" , target_os = "watchos" ) ) ]
200+ mod imp {
201+ use crate :: io;
202+ use crate :: ptr;
203+ use libc:: { c_int, size_t} ;
204+
205+ enum SecRandom { }
206+
207+ #[ allow( non_upper_case_globals) ]
208+ const kSecRandomDefault: * const SecRandom = ptr:: null ( ) ;
209+
210+ extern "C" {
211+ fn SecRandomCopyBytes ( rnd : * const SecRandom , count : size_t , bytes : * mut u8 ) -> c_int ;
212+ }
213+
214+ pub fn fill_bytes ( v : & mut [ u8 ] ) {
215+ let ret = unsafe { SecRandomCopyBytes ( kSecRandomDefault, v. len ( ) , v. as_mut_ptr ( ) ) } ;
216+ if ret == -1 {
217+ panic ! ( "couldn't generate random bytes: {}" , io:: Error :: last_os_error( ) ) ;
218+ }
219+ }
220+ }
221+
240222#[ cfg( any( target_os = "freebsd" , target_os = "netbsd" ) ) ]
241223mod imp {
242224 use crate :: ptr;
0 commit comments