|
1 | | -// Copyright 2018 Developers of the Rand project. |
| 1 | +// Copyright 2023 Developers of the Rand project. |
2 | 2 | // |
3 | 3 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
4 | 4 | // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
5 | 5 | // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your |
6 | 6 | // option. This file may not be copied, modified, or distributed |
7 | 7 | // except according to those terms. |
8 | 8 |
|
9 | | -//! Implementation for iOS |
| 9 | +//! Implementation for iOS, tvOS, and watchOS where `getentropy` is unavailable. |
10 | 10 | use crate::Error; |
11 | | -use core::{ffi::c_void, mem::MaybeUninit, ptr::null}; |
| 11 | +use core::{ffi::c_void, mem::MaybeUninit}; |
12 | 12 |
|
13 | | -#[link(name = "Security", kind = "framework")] |
| 13 | +// libsystem contains the libc of Darwin, and every binary ends up linked against it either way. This |
| 14 | +// makes it a more lightweight choice compared to `Security.framework`. |
14 | 15 | extern "C" { |
15 | | - fn SecRandomCopyBytes(rnd: *const c_void, count: usize, bytes: *mut u8) -> i32; |
| 16 | + // This RNG uses a thread-local CSPRNG to provide data, which is seeded by the operating system's root CSPRNG. |
| 17 | + // Its the best option after `getentropy` on modern Darwin-based platforms that also avoids the |
| 18 | + // high startup costs and linking of Security.framework. |
| 19 | + // |
| 20 | + // While its just an implementation detail, `Security.framework` just calls into this anyway. |
| 21 | + fn CCRandomGenerateBytes(bytes: *mut c_void, size: usize) -> i32; |
16 | 22 | } |
17 | 23 |
|
18 | 24 | pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> { |
19 | | - // Apple's documentation guarantees kSecRandomDefault is a synonym for NULL. |
20 | | - let ret = unsafe { SecRandomCopyBytes(null(), dest.len(), dest.as_mut_ptr() as *mut u8) }; |
21 | | - // errSecSuccess (from SecBase.h) is always zero. |
| 25 | + let ret = unsafe { CCRandomGenerateBytes(dest.as_mut_ptr() as *mut c_void, dest.len()) }; |
| 26 | + // kCCSuccess (from CommonCryptoError.h) is always zero. |
22 | 27 | if ret != 0 { |
23 | 28 | Err(Error::IOS_SEC_RANDOM) |
24 | 29 | } else { |
|
0 commit comments