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