Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise minimum supported Apple OS versions #388

Merged
merged 1 commit into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed
- Raise minimum supported Apple OS versions to macOS 10.12 and iOS 10.

## [0.2.11] - 2023-11-08
### Added
- GNU/Hurd support [#370]
Expand Down
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)
BlackHoleFox marked this conversation as resolved.
Show resolved Hide resolved
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ impl Error {
pub const ERRNO_NOT_POSITIVE: Error = internal_error(1);
/// Encountered an unexpected situation which should not happen in practice.
pub const UNEXPECTED: Error = internal_error(2);
/// Call to iOS [`SecRandomCopyBytes`](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes) failed.
/// Call to [`CCRandomGenerateBytes`](https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html) failed
/// on iOS, tvOS, or waatchOS.
// TODO: Update this constant name in the next breaking release.
pub const IOS_SEC_RANDOM: Error = internal_error(3);
/// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
pub const WINDOWS_RTL_GEN_RANDOM: Error = internal_error(4);
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 @@ -179,7 +179,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 @@ -250,7 +250,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