Skip to content

Commit

Permalink
Add "insecure" functions
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Nov 27, 2024
1 parent e694075 commit 6438bcc
Show file tree
Hide file tree
Showing 26 changed files with 232 additions and 124 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ jobs:
- run: cargo test --no-run --target=aarch64-apple-watchos -Zbuild-std --features=std
# visionOS requires Xcode 15.2+, GitHub Actions defaults to an older version.
- run: sudo xcode-select -switch /Applications/Xcode_15.2.app
- run: cargo test --no-run --target=aarch64-apple-visionos -Zbuild-std --features=std
# std is broken on visionOS right now
#- run: cargo test --no-run --target=aarch64-apple-visionos -Zbuild-std --features=std

cross:
name: Cross
Expand Down
4 changes: 2 additions & 2 deletions src/backends/apple_other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let dst_ptr = dest.as_mut_ptr().cast::<c_void>();
let ret = unsafe { libc::CCRandomGenerateBytes(dst_ptr, dest.len()) };
if ret == libc::kCCSuccess {
Expand Down
4 changes: 2 additions & 2 deletions src/backends/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
extern "Rust" {
fn __getrandom_v03_custom(dest: *mut u8, len: usize) -> Result<(), Error>;
}
Expand Down
33 changes: 23 additions & 10 deletions src/backends/esp_idf.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
//! Implementation for ESP-IDF
//! Implementation for ESP-IDF.
//!
//! Not that NOT enabling WiFi, BT, or the voltage noise entropy source
//! (via `bootloader_random_enable`) will cause ESP-IDF to return pseudo-random numbers based on
//! the voltage noise entropy, after the initial boot process:
//! https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html
//!
//! However tracking if some of these entropy sources is enabled is way too difficult
//! to implement here.
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64};

#[cfg(not(target_os = "espidf"))]
compile_error!("`esp_idf` backend can be enabled only for ESP-IDF targets!");

extern "C" {
fn esp_fill_random(buf: *mut c_void, len: usize) -> u32;
fn esp_random() -> u32;
fn esp_fill_random(buf: *mut c_void, len: usize);
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// Not that NOT enabling WiFi, BT, or the voltage noise entropy source (via `bootloader_random_enable`)
// will cause ESP-IDF to return pseudo-random numbers based on the voltage noise entropy, after the initial boot process:
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html
//
// However tracking if some of these entropy sources is enabled is way too difficult to implement here
unsafe { esp_fill_random(dest.as_mut_ptr().cast(), dest.len()) };
pub fn u32() -> Result<u32, Error> {
Ok(unsafe { esp_random() })
}

pub fn u64() -> Result<u64, Error> {
let (a, b) = unsafe { (esp_random(), esp_random()) };
let res = (u64::from(a) << 32) | u64::from(b);
Ok(res)
}

pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
unsafe { esp_fill_random(dest.as_mut_ptr().cast(), dest.len()) };
Ok(())
}
4 changes: 2 additions & 2 deletions src/backends/fuchsia.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

#[link(name = "zircon")]
extern "C" {
fn zx_cprng_draw(buffer: *mut u8, length: usize);
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
unsafe { zx_cprng_draw(dest.as_mut_ptr().cast::<u8>(), dest.len()) }
Ok(())
}
4 changes: 2 additions & 2 deletions src/backends/getentropy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

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

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(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 {
Expand Down
4 changes: 2 additions & 2 deletions src/backends/getrandom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

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

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
util_libc::sys_fill_exact(dest, |buf| unsafe {
libc::getrandom(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
})
Expand Down
8 changes: 5 additions & 3 deletions src/backends/hermit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64};

extern "C" {
fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize;
// Note that `sys_secure_rand32/64` are implemented using `sys_read_entropy`:
Expand All @@ -12,7 +14,7 @@ extern "C" {
fn sys_secure_rand64(value: *mut u64) -> i32;
}

pub fn inner_u32() -> Result<u32, Error> {
pub fn u32() -> Result<u32, Error> {
let mut res = MaybeUninit::uninit();
let ret = unsafe { sys_secure_rand32(res.as_mut_ptr()) };
match ret {
Expand All @@ -22,7 +24,7 @@ pub fn inner_u32() -> Result<u32, Error> {
}
}

pub fn inner_u64() -> Result<u64, Error> {
pub fn u64() -> Result<u64, Error> {
let mut res = MaybeUninit::uninit();
let ret = unsafe { sys_secure_rand64(res.as_mut_ptr()) };
match ret {
Expand All @@ -32,7 +34,7 @@ pub fn inner_u64() -> Result<u64, Error> {
}
}

pub fn fill_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
while !dest.is_empty() {
let res = unsafe { sys_read_entropy(dest.as_mut_ptr().cast::<u8>(), dest.len(), 0) };
match res {
Expand Down
4 changes: 2 additions & 2 deletions src/backends/linux_android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

#[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!");

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
util_libc::sys_fill_exact(dest, |buf| unsafe {
libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0)
})
Expand Down
6 changes: 3 additions & 3 deletions src/backends/linux_android_with_fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::{
};
use use_file::util_libc;

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

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

Expand Down Expand Up @@ -56,10 +56,10 @@ fn init() -> NonNull<c_void> {
// prevent inlining of the fallback implementation
#[inline(never)]
fn use_file_fallback(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
use_file::fill_inner(dest)
use_file::fill_uninit(dest)
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// Despite being only a single atomic variable, we still cannot always use
// Ordering::Relaxed, as we need to make sure a successful call to `init`
// is "ordered before" any data read through the returned pointer (which
Expand Down
4 changes: 2 additions & 2 deletions src/backends/linux_rustix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
use crate::{Error, MaybeUninit};
use rustix::rand::{getrandom_uninit, GetRandomFlags};

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

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

pub fn fill_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
loop {
let res = getrandom_uninit(dest, GetRandomFlags::empty()).map(|(res, _)| res.len());
match res {
Expand Down
4 changes: 2 additions & 2 deletions src/backends/netbsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use core::{
sync::atomic::{AtomicPtr, Ordering},
};

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

#[path = "../util_libc.rs"]
mod util_libc;
Expand Down Expand Up @@ -62,7 +62,7 @@ fn init() -> *mut c_void {
ptr
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// Despite being only a single atomic variable, we still cannot always use
// Ordering::Relaxed, as we need to make sure a successful call to `init`
// is "ordered before" any data read through the returned pointer (which
Expand Down
8 changes: 5 additions & 3 deletions src/backends/rdrand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
use crate::{util::slice_as_uninit, Error};
use core::mem::{size_of, MaybeUninit};

pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64};

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

Expand Down Expand Up @@ -147,23 +149,23 @@ unsafe fn rdrand_u64() -> Option<u64> {
Some((u64::from(a) << 32) || u64::from(b))
}

pub fn inner_u32() -> Result<u32, Error> {
pub fn u32() -> Result<u32, Error> {
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
return Err(Error::NO_RDRAND);
}
// SAFETY: After this point, we know rdrand is supported.
unsafe { rdrand_u32() }.ok_or(Error::FAILED_RDRAND)
}

pub fn inner_u64() -> Result<u64, Error> {
pub fn u64() -> Result<u64, Error> {
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
return Err(Error::NO_RDRAND);
}
// SAFETY: After this point, we know rdrand is supported.
unsafe { rdrand_u64() }.ok_or(Error::FAILED_RDRAND)
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
return Err(Error::NO_RDRAND);
}
Expand Down
8 changes: 5 additions & 3 deletions src/backends/rndr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::{
use core::arch::asm;
use core::mem::{size_of, MaybeUninit};

pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64};

#[cfg(not(target_arch = "aarch64"))]
compile_error!("the `rndr` backend can be enabled only for AArch64 targets!");

Expand Down Expand Up @@ -104,7 +106,7 @@ fn is_rndr_available() -> bool {
}
}

pub fn inner_u32() -> Result<u32, Error> {
pub fn u32() -> Result<u32, Error> {
if is_rndr_available() {
// SAFETY: after this point, we know the `rand` target feature is enabled
let res = unsafe { rndr() };
Expand All @@ -114,7 +116,7 @@ pub fn inner_u32() -> Result<u32, Error> {
}
}

pub fn inner_u64() -> Result<u64, Error> {
pub fn u64() -> Result<u64, Error> {
if is_rndr_available() {
// SAFETY: after this point, we know the `rand` target feature is enabled
let res = unsafe { rndr() };
Expand All @@ -124,7 +126,7 @@ pub fn inner_u64() -> Result<u64, Error> {
}
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
if is_rndr_available() {
// SAFETY: after this point, we know the `rand` target feature is enabled
unsafe { rndr_fill(dest).ok_or(Error::RNDR_FAILURE) }
Expand Down
4 changes: 2 additions & 2 deletions src/backends/solaris.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
use crate::Error;
use core::{ffi::c_void, mem::MaybeUninit};

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

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

const MAX_BYTES: usize = 1024;

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
for chunk in dest.chunks_mut(MAX_BYTES) {
let ptr = chunk.as_mut_ptr().cast::<c_void>();
let ret = unsafe { libc::getrandom(ptr, chunk.len(), libc::GRND_RANDOM) };
Expand Down
4 changes: 2 additions & 2 deletions src/backends/solid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

extern "C" {
pub fn SOLID_RNG_SampleRandomBytes(buffer: *mut u8, length: usize) -> i32;
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let ret = unsafe { SOLID_RNG_SampleRandomBytes(dest.as_mut_ptr().cast::<u8>(), dest.len()) };
if ret >= 0 {
Ok(())
Expand Down
4 changes: 2 additions & 2 deletions src/backends/use_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use core::{
};

#[cfg(not(any(target_os = "android", target_os = "linux")))]
pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

#[path = "../util_libc.rs"]
pub(super) mod util_libc;
Expand Down Expand Up @@ -40,7 +40,7 @@ const FD_ONGOING_INIT: libc::c_int = -2;
// `Ordering::Acquire` to synchronize with it.
static FD: AtomicI32 = AtomicI32::new(FD_UNINIT);

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
let mut fd = FD.load(Ordering::Acquire);
if fd == FD_UNINIT || fd == FD_ONGOING_INIT {
fd = open_or_wait()?;
Expand Down
4 changes: 2 additions & 2 deletions src/backends/vxworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use core::{
#[path = "../util_libc.rs"]
mod util_libc;

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
static RNG_INIT: AtomicBool = AtomicBool::new(false);
while !RNG_INIT.load(Relaxed) {
let ret = unsafe { libc::randSecure() };
Expand Down
4 changes: 2 additions & 2 deletions src/backends/wasi_p1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::Error;
use core::mem::MaybeUninit;

pub use crate::util::{inner_u32, inner_u64};
pub use crate::default_impls::{insecure_fill_uninit, insecure_u32, insecure_u64, u32, u64};

// This linking is vendored from the wasi crate:
// https://docs.rs/wasi/0.11.0+wasi-snapshot-preview1/src/wasi/lib_generated.rs.html#2344-2350
Expand All @@ -11,7 +11,7 @@ extern "C" {
fn random_get(arg0: i32, arg1: i32) -> i32;
}

pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
// Based on the wasi code:
// https://docs.rs/wasi/0.11.0+wasi-snapshot-preview1/src/wasi/lib_generated.rs.html#2046-2062
// Note that size of an allocated object can not be bigger than isize::MAX bytes.
Expand Down
Loading

0 comments on commit 6438bcc

Please sign in to comment.