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

Move backend implementations to src/backends/ #538

Merged
merged 8 commits into from
Oct 28, 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
152 changes: 152 additions & 0 deletions src/backends.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
//! System-specific implementations.
//!
//! This module should provide `fill_inner` with the signature
//! `fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>`.
//! The function MUST fully initialize `dest` when `Ok(())` is returned.
//! The function MUST NOT ever write uninitialized bytes into `dest`,
//! regardless of what value it returns.

cfg_if! {
if #[cfg(getrandom_backend = "custom")] {
mod custom;
pub use custom::*;
} else if #[cfg(getrandom_backend = "linux_getrandom")] {
mod linux_android;
pub use linux_android::*;
} else if #[cfg(getrandom_backend = "linux_rustix")] {
mod linux_rustix;
pub use linux_rustix::*;
} else if #[cfg(getrandom_backend = "rdrand")] {
mod rdrand;
pub use rdrand::*;
} else if #[cfg(getrandom_backend = "rndr")] {
mod rndr;
pub use rndr::*;
} else if #[cfg(getrandom_backend = "wasm_js")] {
mod wasm_js;
pub use wasm_js::*;
} else if #[cfg(getrandom_backend = "esp_idf")] {
mod esp_idf;
pub use esp_idf::*;
} else if #[cfg(any(
target_os = "haiku",
target_os = "redox",
target_os = "nto",
target_os = "aix",
))] {
mod use_file;
pub use use_file::*;
} else if #[cfg(any(
target_os = "macos",
target_os = "openbsd",
target_os = "vita",
target_os = "emscripten",
))] {
mod getentropy;
pub use getentropy::*;
} else if #[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "hurd",
target_os = "illumos",
// Check for target_arch = "arm" to only include the 3DS. Does not
// include the Nintendo Switch (which is target_arch = "aarch64").
all(target_os = "horizon", target_arch = "arm"),
))] {
mod getrandom;
pub use getrandom::*;
} else if #[cfg(any(
// Rust supports Android API level 19 (KitKat) [0] and the next upgrade targets
// level 21 (Lollipop) [1], while `getrandom(2)` was added only in
// level 23 (Marshmallow). Note that it applies only to the "old" `target_arch`es,
// RISC-V Android targets sufficiently new API level, same will apply for potential
// new Android `target_arch`es.
// [0]: https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html
// [1]: https://github.com/rust-lang/rust/pull/120593
all(
target_os = "android",
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86",
target_arch = "x86_64",
),
),
// Only on these `target_arch`es Rust supports Linux kernel versions (3.2+)
// that precede the version (3.17) in which `getrandom(2)` was added:
// https://doc.rust-lang.org/stable/rustc/platform-support.html
all(
target_os = "linux",
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x",
target_arch = "x86",
target_arch = "x86_64",
// Minimum supported Linux kernel version for MUSL targets
// is not specified explicitly (as of Rust 1.77) and they
// are used in practice to target pre-3.17 kernels.
target_env = "musl",
),
)
))] {
mod use_file;
mod linux_android_with_fallback;
pub use linux_android_with_fallback::*;
} else if #[cfg(any(target_os = "android", target_os = "linux"))] {
mod linux_android;
pub use linux_android::*;
} else if #[cfg(target_os = "solaris")] {
mod solaris;
pub use solaris::*;
} else if #[cfg(target_os = "netbsd")] {
mod netbsd;
pub use netbsd::*;
} else if #[cfg(target_os = "fuchsia")] {
mod fuchsia;
pub use fuchsia::*;
} else if #[cfg(any(
target_os = "ios",
target_os = "visionos",
target_os = "watchos",
target_os = "tvos",
))] {
mod apple_other;
pub use apple_other::*;
} else if #[cfg(all(target_arch = "wasm32", target_os = "wasi"))] {
mod wasi;
pub use wasi::*;
} else if #[cfg(target_os = "hermit")] {
mod hermit;
pub use hermit::*;
} else if #[cfg(target_os = "vxworks")] {
mod vxworks;
pub use vxworks::*;
} else if #[cfg(target_os = "solid_asp3")] {
mod solid;
pub use solid::*;
} else if #[cfg(all(windows, target_vendor = "win7"))] {
mod windows7;
pub use windows7::*;
} else if #[cfg(windows)] {
mod windows;
pub use windows::*;
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
mod rdrand;
pub use rdrand::*;
} else if #[cfg(all(
any(target_arch = "wasm32", target_arch = "wasm64"),
target_os = "unknown",
))] {
compile_error!("the wasm*-unknown-unknown targets are not supported by \
default, you may need to enable the \"wasm_js\" \
configuration flag. For more information see: \
https://docs.rs/getrandom/#webassembly-support");
} else {
compile_error!("target is not supported. You may need to define \
a custom backend see: \
https://docs.rs/getrandom/#custom-backends");
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 5 additions & 2 deletions src/getentropy.rs → src/backends/getentropy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
//! - 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 crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

#[path = "../util_libc.rs"]
mod util_libc;

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
for chunk in dest.chunks_mut(256) {
let ret = unsafe { libc::getentropy(chunk.as_mut_ptr().cast::<c_void>(), chunk.len()) };
if ret != 0 {
return Err(last_os_error());
return Err(util_libc::last_os_error());
}
}
Ok(())
Expand Down
7 changes: 5 additions & 2 deletions src/getrandom.rs → src/backends/getrandom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@
//! 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.
use crate::{util_libc::sys_fill_exact, Error};
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

#[path = "../util_libc.rs"]
mod util_libc;

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
sys_fill_exact(dest, |buf| unsafe {
util_libc::sys_fill_exact(dest, |buf| unsafe {
libc::getrandom(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
})
}
File renamed without changes.
5 changes: 4 additions & 1 deletion src/linux_android.rs → src/backends/linux_android.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//! Implementation for Linux / Android without `/dev/urandom` fallback
use crate::{util_libc, Error};
use crate::Error;
use core::mem::MaybeUninit;

#[path = "../util_libc.rs"]
mod util_libc;

#[cfg(not(any(target_os = "android", target_os = "linux")))]
compile_error!("`linux_getrandom` backend can be enabled only for Linux/Android targets!");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Implementation for Linux / Android with `/dev/urandom` fallback
use crate::{use_file, util_libc, Error};
use super::use_file;
use crate::Error;
use core::{
ffi::c_void,
mem::{self, MaybeUninit},
ptr::{self, NonNull},
sync::atomic::{AtomicPtr, Ordering},
};
use use_file::util_libc;

type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;

Expand Down
File renamed without changes.
7 changes: 5 additions & 2 deletions src/netbsd.rs → src/backends/netbsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! `getrandom(2)` was introduced in NetBSD 10. To support older versions we
//! implement our own weak linkage to it, and provide a fallback based on the
//! KERN_ARND sysctl.
use crate::{util_libc::sys_fill_exact, Error};
use crate::Error;
use core::{
cmp,
ffi::c_void,
Expand All @@ -12,6 +12,9 @@ use core::{
sync::atomic::{AtomicPtr, Ordering},
};

#[path = "../util_libc.rs"]
mod util_libc;

unsafe extern "C" fn polyfill_using_kern_arand(
buf: *mut c_void,
buflen: libc::size_t,
Expand Down Expand Up @@ -69,7 +72,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
fptr = init();
}
let fptr = unsafe { mem::transmute::<*mut c_void, GetRandomFn>(fptr) };
sys_fill_exact(dest, |buf| unsafe {
util_libc::sys_fill_exact(dest, |buf| unsafe {
fptr(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
})
}
7 changes: 5 additions & 2 deletions src/rdrand.rs → src/backends/rdrand.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//! RDRAND backend for x86(-64) targets
use crate::{lazy::LazyBool, util::slice_as_uninit, Error};
use crate::{util::slice_as_uninit, Error};
use core::mem::{size_of, MaybeUninit};

#[path = "../lazy.rs"]
mod lazy;

#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
compile_error!("`rdrand` backend can be enabled only for x86 and x86-64 targets!");

Expand Down Expand Up @@ -97,7 +100,7 @@ fn is_rdrand_good() -> bool {
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
static RDRAND_GOOD: LazyBool = LazyBool::new();
static RDRAND_GOOD: lazy::LazyBool = lazy::LazyBool::new();
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
return Err(Error::NO_RDRAND);
}
Expand Down
4 changes: 2 additions & 2 deletions src/rndr.rs → src/backends/rndr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ fn is_rndr_available() -> bool {
(id_aa64isar0 >> 60) & 0xf >= 1
}

#[path = "../src/lazy.rs"] mod lazy;
#[path = "../lazy.rs"] mod lazy;
static RNDR_GOOD: lazy::LazyBool = lazy::LazyBool::new();
RNDR_GOOD.unsync_init(mrs_check)
} else if #[cfg(feature = "std")] {
extern crate std;
#[path = "../src/lazy.rs"] mod lazy;
#[path = "../lazy.rs"] mod lazy;
static RNDR_GOOD: lazy::LazyBool = lazy::LazyBool::new();
RNDR_GOOD.unsync_init(|| std::arch::is_aarch64_feature_detected!("rand"))
} else {
Expand Down
12 changes: 9 additions & 3 deletions src/solaris.rs → src/backends/solaris.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
//! For more information, see the man page linked in lib.rs and this blog post:
//! https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2
//! which also explains why this crate should not use getentropy(2).
use crate::{util_libc::last_os_error, Error};
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

#[path = "../util_libc.rs"]
mod util_libc;

const MAX_BYTES: usize = 1024;

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
Expand All @@ -24,8 +27,11 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// In case the man page has a typo, we also check for negative ret.
// If getrandom(2) succeeds, it should have completely filled chunk.
match usize::try_from(ret) {
Ok(ret) if ret == chunk.len() => {} // Good. Keep going.
Ok(0) => return Err(last_os_error()), // The syscall failed.
// Good. Keep going.
Ok(ret) if ret == chunk.len() => {}
// The syscall failed.
Ok(0) => return Err(util_libc::last_os_error()),
// All other cases should be impossible.
_ => return Err(Error::UNEXPECTED),
}
}
Expand Down
File renamed without changes.
14 changes: 7 additions & 7 deletions src/use_file.rs → src/backends/use_file.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//! Implementations that just need to read from a file
use crate::{
util_libc::{last_os_error, sys_fill_exact},
Error,
};
use crate::Error;
use core::{
ffi::c_void,
mem::MaybeUninit,
sync::atomic::{AtomicI32, Ordering},
};

#[path = "../util_libc.rs"]
pub(super) mod util_libc;

/// For all platforms, we use `/dev/urandom` rather than `/dev/random`.
/// For more information see the linked man pages in lib.rs.
/// - On Linux, "/dev/urandom is preferred and sufficient in all use cases".
Expand Down Expand Up @@ -42,7 +42,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
if fd == FD_UNINIT || fd == FD_ONGOING_INIT {
fd = open_or_wait()?;
}
sys_fill_exact(dest, |buf| unsafe {
util_libc::sys_fill_exact(dest, |buf| unsafe {
libc::read(fd, buf.as_mut_ptr().cast::<c_void>(), buf.len())
})
}
Expand All @@ -65,7 +65,7 @@ fn open_readonly(path: &[u8]) -> Result<libc::c_int, Error> {
if fd >= 0 {
return Ok(fd);
}
let err = last_os_error();
let err = util_libc::last_os_error();
// We should try again if open() was interrupted.
if err.raw_os_error() != Some(libc::EINTR) {
return Err(err);
Expand Down Expand Up @@ -142,7 +142,7 @@ mod sync {

#[cfg(any(target_os = "android", target_os = "linux"))]
mod sync {
use super::{last_os_error, open_readonly, Error, FD, FD_ONGOING_INIT};
use super::{open_readonly, util_libc::last_os_error, Error, FD, FD_ONGOING_INIT};

/// Wait for atomic `FD` to change value from `FD_ONGOING_INIT` to something else.
///
Expand Down
7 changes: 5 additions & 2 deletions src/vxworks.rs → src/backends/vxworks.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! Implementation for VxWorks
use crate::{util_libc::last_os_error, Error};
use crate::Error;
use core::{
cmp::Ordering::{Equal, Greater, Less},
mem::MaybeUninit,
sync::atomic::{AtomicBool, Ordering::Relaxed},
};

#[path = "../util_libc.rs"]
mod util_libc;

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
static RNG_INIT: AtomicBool = AtomicBool::new(false);
while !RNG_INIT.load(Relaxed) {
Expand All @@ -32,7 +35,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let p: *mut libc::c_uchar = chunk.as_mut_ptr().cast();
let ret = unsafe { libc::randABytes(p, chunk_len) };
if ret != 0 {
return Err(last_os_error());
return Err(util_libc::last_os_error());
}
}
Ok(())
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/wasm_js.rs → src/backends/wasm_js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ thread_local!(
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
);

pub(crate) fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
RNG_SOURCE.with(|result| {
let source = result.as_ref().map_err(|&e| e)?;

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading