|
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