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").