Skip to content

Commit

Permalink
Raise minimum supported Apple OS versions
Browse files Browse the repository at this point in the history
  • Loading branch information
BlackHoleFox committed Dec 19, 2023
1 parent 7249e6e commit 6dc685f
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 37 deletions.
21 changes: 13 additions & 8 deletions src/apple-other.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
// Copyright 2018 Developers of the Rand project.
// Copyright 2023 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation for iOS
//! Implementation for iOS, tvOS, and watchOS where `getentropy` is unavailable.
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit, ptr::null};
use core::{ffi::c_void, mem::MaybeUninit};

#[link(name = "Security", kind = "framework")]
// libsystem contains the libc of Darwin, and every binary ends up linked against it either way. This
// makes it a more lightweight choice compared to `Security.framework`.
extern "C" {
fn SecRandomCopyBytes(rnd: *const c_void, count: usize, bytes: *mut u8) -> i32;
// This RNG uses a thread-local CSPRNG to provide data, which is seeded by the operating system's root CSPRNG.
// Its the best option after `getentropy` on modern Darwin-based platforms that also avoids the
// high startup costs and linking of Security.framework.
//
// While its just an implementation detail, `Security.framework` just calls into this anyway.
fn CCRandomGenerateBytes(bytes: *mut c_void, size: usize) -> i32;
}

pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// Apple's documentation guarantees kSecRandomDefault is a synonym for NULL.
let ret = unsafe { SecRandomCopyBytes(null(), dest.len(), dest.as_mut_ptr() as *mut u8) };
// errSecSuccess (from SecBase.h) is always zero.
let ret = unsafe { CCRandomGenerateBytes(dest.as_mut_ptr() as *mut c_void, dest.len()) };
// kCCSuccess (from CommonCryptoError.h) is always zero.
if ret != 0 {
Err(Error::IOS_SEC_RANDOM)
} else {
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
//! | ----------------- | ------------------ | --------------
//! | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
//! | Windows | `*‑windows‑*` | [`BCryptGenRandom`]
//! | macOS | `*‑apple‑darwin` | [`getentropy`][3] if available, otherwise [`/dev/urandom`][4] (identical to `/dev/random`)
//! | iOS, tvOS, watchOS | `*‑apple‑ios`, `*-apple-tvos`, `*-apple-watchos` | [`SecRandomCopyBytes`]
//! | macOS | `*‑apple‑darwin` | [`getentropy`][3]
//! | iOS, tvOS, watchOS | `*‑apple‑ios`, `*-apple-tvos`, `*-apple-watchos` | [`CCRandomGenerateBytes`]
//! | FreeBSD | `*‑freebsd` | [`getrandom`][5] if available, otherwise [`kern.arandom`][6]
//! | OpenBSD | `*‑openbsd` | [`getentropy`][7]
//! | NetBSD | `*‑netbsd` | [`getrandom`][16] if available, otherwise [`kern.arandom`][8]
Expand Down Expand Up @@ -172,7 +172,7 @@
//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
//! [`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
//! [`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
//! [`SecRandomCopyBytes`]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
//! [`CCRandomGenerateBytes`]: https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html
//! [`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
//! [`crypto.randomFillSync`]: https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size
//! [`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t
Expand Down Expand Up @@ -243,7 +243,6 @@ cfg_if! {
#[path = "apple-other.rs"] mod imp;
} else if #[cfg(target_os = "macos")] {
mod util_libc;
mod use_file;
#[path = "macos.rs"] mod imp;
} else if #[cfg(target_os = "openbsd")] {
mod util_libc;
Expand Down
34 changes: 12 additions & 22 deletions src/macos.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 Developers of the Rand project.
// Copyright 2023 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
Expand All @@ -7,30 +7,20 @@
// except according to those terms.

//! Implementation for macOS
use crate::{
use_file,
util_libc::{last_os_error, Weak},
Error,
};
use core::mem::{self, MaybeUninit};
use crate::{util_libc::last_os_error, Error};
use core::mem::MaybeUninit;

type GetEntropyFn = unsafe extern "C" fn(*mut u8, libc::size_t) -> libc::c_int;
extern "C" {
// Supported as of macOS 10.12+.
fn getentropy(buf: *mut u8, size: libc::size_t) -> libc::c_int;
}

pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// getentropy(2) was added in 10.12, Rust supports 10.7+
static GETENTROPY: Weak = unsafe { Weak::new("getentropy\0") };
if let Some(fptr) = GETENTROPY.ptr() {
let func: GetEntropyFn = unsafe { mem::transmute(fptr) };
for chunk in dest.chunks_mut(256) {
let ret = unsafe { func(chunk.as_mut_ptr() as *mut u8, chunk.len()) };
if ret != 0 {
return Err(last_os_error());
}
for chunk in dest.chunks_mut(256) {
let ret = unsafe { getentropy(chunk.as_mut_ptr() as *mut u8, chunk.len()) };
if ret != 0 {
return Err(last_os_error());
}
Ok(())
} else {
// We fallback to reading from /dev/random instead of SecRandomCopyBytes
// to avoid high startup costs and linking the Security framework.
use_file::getrandom_inner(dest)
}
Ok(())
}
5 changes: 2 additions & 3 deletions src/use_file.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018 Developers of the Rand project.
// Copyright 2023 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
Expand All @@ -20,7 +20,7 @@ use core::{
// We prefer using /dev/urandom and only use /dev/random if the OS
// documentation indicates that /dev/urandom is insecure.
// On Solaris/Illumos, see src/solaris_illumos.rs
// On Dragonfly, Haiku, macOS, and QNX Neutrino the devices are identical.
// On Dragonfly, Haiku, and QNX Neutrino the devices are identical.
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
const FILE_PATH: &str = "/dev/random\0";
#[cfg(any(
Expand All @@ -30,7 +30,6 @@ const FILE_PATH: &str = "/dev/random\0";
target_os = "redox",
target_os = "dragonfly",
target_os = "haiku",
target_os = "macos",
target_os = "nto",
))]
const FILE_PATH: &str = "/dev/urandom\0";
Expand Down

0 comments on commit 6dc685f

Please sign in to comment.