- #[cfg(target_os = "macos")]
- fn fallback_fill_bytes(v: &mut [u8]) {
- use crate::fs::File;
- use crate::io::Read;
-
- let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
- file.read_exact(v).expect("failed to read /dev/urandom")
- }
-
- // On iOS and MacOS `SecRandomCopyBytes` calls `CCRandomCopyBytes` with
- // `kCCRandomDefault`. `CCRandomCopyBytes` manages a CSPRNG which is seeded
- // from `/dev/random` and which runs on its own thread accessed via GCD.
- //
- // This is very heavyweight compared to the alternatives, but they may not be usable:
- // - `getentropy` was added in iOS 10, but we support a minimum of iOS 7
- // - `/dev/urandom` is not accessible inside the iOS app sandbox.
- //
- // Therefore `SecRandomCopyBytes` is only used on older iOS versions where no
- // better options are present.
- #[cfg(target_os = "ios")]
- fn fallback_fill_bytes(v: &mut [u8]) {
- use crate::ptr;
-
- enum SecRandom {}
-
- #[allow(non_upper_case_globals)]
- const kSecRandomDefault: *const SecRandom = ptr::null();
-
- extern "C" {
- fn SecRandomCopyBytes(rnd: *const SecRandom, count: size_t, bytes: *mut u8) -> c_int;
- }
-
- let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, v.len(), v.as_mut_ptr()) };
- if ret == -1 {
- panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
- }
- }
-
- // All supported versions of watchOS (>= 5) have support for `getentropy`.
- #[cfg(target_os = "watchos")]
- #[cold]
- fn fallback_fill_bytes(_: &mut [u8]) {
- unreachable!()
- }
-