From 7f909f0da8e8105b54d9b1b99d7d4b53571786aa Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Mon, 6 May 2024 00:12:32 -0700 Subject: [PATCH] Use libc::getrandom on Solaris and update docs. https://github.com/rust-random/getrandom/pull/417 used `getentropy(2)` on Solaris, but after looking at [the blog post introducing `getrandom()` and `getentropy()`](https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2), it seems like we should prefer using `getrandom` based on this quote: > On Solaris the output of getentropy(2) is entropy and should not be used where randomness is needed, in particular it must not be used where an IV or nonce is needed when calling a cryptographic operation. It is intended only for seeding a user space RBG (Random Bit Generator) system. More specifically the data returned by getentropy(2) has not had the required FIPS 140-2 processing for the DRBG applied to it. I also updated some of the documentation explaining: - Why we ever use `getentropy(2)` - Why we don't ever set `GRND_RANDOM` Signed-off-by: Joe Richey --- src/getentropy.rs | 4 +++- src/getrandom.rs | 28 +++++++++++++++++++++++----- src/lib.rs | 8 ++++---- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/getentropy.rs b/src/getentropy.rs index 1d35b572..41bab8fe 100644 --- a/src/getentropy.rs +++ b/src/getentropy.rs @@ -1,10 +1,12 @@ -//! Implementation using libc::getentropy +//! Implementation using getentropy(2) //! //! Available since: //! - macOS 10.12 //! - OpenBSD 5.6 //! - Emscripten 2.0.5 //! - vita newlib since Dec 2021 +//! +//! For these targets, we use getentropy(2) because getrandom(2) doesn't exist. use crate::{util_libc::last_os_error, Error}; use core::mem::MaybeUninit; diff --git a/src/getrandom.rs b/src/getrandom.rs index 3b2cde15..c0ab092e 100644 --- a/src/getrandom.rs +++ b/src/getrandom.rs @@ -1,4 +1,4 @@ -//! Implementation using `libc::getrandom`. +//! Implementation using getrandom(2). //! //! Available since: //! - Linux Kernel 3.17, Glibc 2.25, Musl 1.1.20 @@ -6,15 +6,33 @@ //! - NetBSD 10.0 //! - FreeBSD 12.0 //! - Solaris 11.3 -//! - Illumos since Dec 2018 +//! - illumos since Dec 2018 //! - DragonFly 5.7 //! - Hurd Glibc 2.31 //! - shim-3ds since Feb 2022 +//! +//! For all platforms, we always use the default entropy pool and never set the +//! GRND_RANDOM flag to use the /dev/random pool. On Linux/Android/Hurd, using +//! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does +//! nothing. On illumos, the default pool is used to implement getentropy(2), +//! so we assume it is acceptable here. On Solaris, the story is less clear, +//! but both pools use standard DRBGs (FIPS 140-2 and NIST SP-900-90A), so we +//! use the default pool. For more information on Solaris see this blog post: +//! https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2 use crate::{util_libc::sys_fill_exact, Error}; use core::mem::MaybeUninit; +// On Solaris 11.3, if bufsz > 1024 (> 133120 on Solaris 11.4) calls to +// getrandom(2) will always fail, so we chunk the buffer if it is too long. +#[cfg(target_os = "solaris")] +const MAX_BYTES: usize = 1024; +#[cfg(not(target_os = "solaris"))] +const MAX_BYTES: usize = usize::MAX; + pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - sys_fill_exact(dest, |buf| unsafe { - libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, buf.len(), 0) - }) + for chunk in dest.chunks_mut(MAX_BYTES) { + sys_fill_exact(dest, |buf| unsafe { + libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, buf.len(), 0) + }) + } } diff --git a/src/lib.rs b/src/lib.rs index c30e95bb..e1fef463 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,8 +12,8 @@ //! | OpenBSD | `*‑openbsd` | [`getentropy`][7] //! | NetBSD | `*‑netbsd` | [`getrandom`][16] if available, otherwise [`kern.arandom`][8] //! | Dragonfly BSD | `*‑dragonfly` | [`getrandom`][9] -//! | Solaris | `*‑solaris` | [`getentropy`][11] -//! | Illumos | `*‑illumos` | [`getrandom`][12] +//! | Solaris | `*‑solaris` | [`getrandom`][11] +//! | illumos | `*‑illumos` | [`getrandom`][12] //! | Fuchsia OS | `*‑fuchsia` | [`cprng_draw`] //! | Redox | `*‑redox` | `/dev/urandom` //! | Haiku | `*‑haiku` | `/dev/urandom` (identical to `/dev/random`) @@ -173,7 +173,7 @@ //! [7]: https://man.openbsd.org/getentropy.2 //! [8]: https://man.netbsd.org/sysctl.7 //! [9]: https://leaf.dragonflybsd.org/cgi/web-man?command=getrandom -//! [11]: https://docs.oracle.com/cd/E88353_01/html/E37841/getentropy-2.html +//! [11]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html //! [12]: https://illumos.org/man/2/getrandom //! [13]: https://github.com/emscripten-core/emscripten/pull/12240 //! [14]: https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.utilities/topic/r/random.html @@ -238,7 +238,6 @@ cfg_if! { } else if #[cfg(any( target_os = "macos", target_os = "openbsd", - target_os = "solaris", target_os = "vita", target_os = "emscripten", ))] { @@ -248,6 +247,7 @@ cfg_if! { target_os = "dragonfly", target_os = "freebsd", target_os = "hurd", + target_os = "solaris", target_os = "illumos", // Check for target_arch = "arm" to only include the 3DS. Does not // include the Nintendo Switch (which is target_arch = "aarch64").