Skip to content

Commit 5fe3c8e

Browse files
authored
Raise minimum supported Apple OS versions (#388)
1 parent 8aa4efb commit 5fe3c8e

File tree

6 files changed

+38
-38
lines changed

6 files changed

+38
-38
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [Unreleased]
8+
9+
### Changed
10+
- Raise minimum supported Apple OS versions to macOS 10.12 and iOS 10.
11+
712
## [0.2.11] - 2023-11-08
813
### Added
914
- GNU/Hurd support [#370]

src/apple-other.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
1-
// Copyright 2018 Developers of the Rand project.
1+
// Copyright 2023 Developers of the Rand project.
22
//
33
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
44
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
55
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

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

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`.
1415
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;
1622
}
1723

1824
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.
2227
if ret != 0 {
2328
Err(Error::IOS_SEC_RANDOM)
2429
} else {

src/error.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ impl Error {
3737
pub const ERRNO_NOT_POSITIVE: Error = internal_error(1);
3838
/// Encountered an unexpected situation which should not happen in practice.
3939
pub const UNEXPECTED: Error = internal_error(2);
40-
/// Call to iOS [`SecRandomCopyBytes`](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes) failed.
40+
/// Call to [`CCRandomGenerateBytes`](https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html) failed
41+
/// on iOS, tvOS, or waatchOS.
42+
// TODO: Update this constant name in the next breaking release.
4143
pub const IOS_SEC_RANDOM: Error = internal_error(3);
4244
/// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
4345
pub const WINDOWS_RTL_GEN_RANDOM: Error = internal_error(4);

src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
//! | ----------------- | ------------------ | --------------
1515
//! | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
1616
//! | Windows | `*‑windows‑*` | [`BCryptGenRandom`]
17-
//! | macOS | `*‑apple‑darwin` | [`getentropy`][3] if available, otherwise [`/dev/urandom`][4] (identical to `/dev/random`)
18-
//! | iOS, tvOS, watchOS | `*‑apple‑ios`, `*-apple-tvos`, `*-apple-watchos` | [`SecRandomCopyBytes`]
17+
//! | macOS | `*‑apple‑darwin` | [`getentropy`][3]
18+
//! | iOS, tvOS, watchOS | `*‑apple‑ios`, `*-apple-tvos`, `*-apple-watchos` | [`CCRandomGenerateBytes`]
1919
//! | FreeBSD | `*‑freebsd` | [`getrandom`][5] if available, otherwise [`kern.arandom`][6]
2020
//! | OpenBSD | `*‑openbsd` | [`getentropy`][7]
2121
//! | NetBSD | `*‑netbsd` | [`getrandom`][16] if available, otherwise [`kern.arandom`][8]
@@ -179,7 +179,7 @@
179179
//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
180180
//! [`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
181181
//! [`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
182-
//! [`SecRandomCopyBytes`]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
182+
//! [`CCRandomGenerateBytes`]: https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html
183183
//! [`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
184184
//! [`crypto.randomFillSync`]: https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size
185185
//! [`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t
@@ -250,7 +250,6 @@ cfg_if! {
250250
#[path = "apple-other.rs"] mod imp;
251251
} else if #[cfg(target_os = "macos")] {
252252
mod util_libc;
253-
mod use_file;
254253
#[path = "macos.rs"] mod imp;
255254
} else if #[cfg(target_os = "openbsd")] {
256255
mod util_libc;

src/macos.rs

+12-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 Developers of the Rand project.
1+
// Copyright 2023 Developers of the Rand project.
22
//
33
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
44
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@@ -7,30 +7,20 @@
77
// except according to those terms.
88

99
//! Implementation for macOS
10-
use crate::{
11-
use_file,
12-
util_libc::{last_os_error, Weak},
13-
Error,
14-
};
15-
use core::mem::{self, MaybeUninit};
10+
use crate::{util_libc::last_os_error, Error};
11+
use core::mem::MaybeUninit;
1612

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

1918
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
20-
// getentropy(2) was added in 10.12, Rust supports 10.7+
21-
static GETENTROPY: Weak = unsafe { Weak::new("getentropy\0") };
22-
if let Some(fptr) = GETENTROPY.ptr() {
23-
let func: GetEntropyFn = unsafe { mem::transmute(fptr) };
24-
for chunk in dest.chunks_mut(256) {
25-
let ret = unsafe { func(chunk.as_mut_ptr() as *mut u8, chunk.len()) };
26-
if ret != 0 {
27-
return Err(last_os_error());
28-
}
19+
for chunk in dest.chunks_mut(256) {
20+
let ret = unsafe { getentropy(chunk.as_mut_ptr() as *mut u8, chunk.len()) };
21+
if ret != 0 {
22+
return Err(last_os_error());
2923
}
30-
Ok(())
31-
} else {
32-
// We fallback to reading from /dev/random instead of SecRandomCopyBytes
33-
// to avoid high startup costs and linking the Security framework.
34-
use_file::getrandom_inner(dest)
3524
}
25+
Ok(())
3626
}

src/use_file.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018 Developers of the Rand project.
1+
// Copyright 2023 Developers of the Rand project.
22
//
33
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
44
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@@ -20,7 +20,7 @@ use core::{
2020
// We prefer using /dev/urandom and only use /dev/random if the OS
2121
// documentation indicates that /dev/urandom is insecure.
2222
// On Solaris/Illumos, see src/solaris_illumos.rs
23-
// On Dragonfly, Haiku, macOS, and QNX Neutrino the devices are identical.
23+
// On Dragonfly, Haiku, and QNX Neutrino the devices are identical.
2424
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
2525
const FILE_PATH: &str = "/dev/random\0";
2626
#[cfg(any(
@@ -30,7 +30,6 @@ const FILE_PATH: &str = "/dev/random\0";
3030
target_os = "redox",
3131
target_os = "dragonfly",
3232
target_os = "haiku",
33-
target_os = "macos",
3433
target_os = "nto",
3534
))]
3635
const FILE_PATH: &str = "/dev/urandom\0";

0 commit comments

Comments
 (0)