From da70bb439b7258d48637669ec98e5a4fe70f547d Mon Sep 17 00:00:00 2001 From: Josh Simmons Date: Mon, 2 Dec 2024 22:45:10 +0100 Subject: [PATCH] narcissus-core: Add platform secure random API --- engine/narcissus-core/src/crypto_random.rs | 60 ++++++++++++++++++++++ engine/narcissus-core/src/lib.rs | 1 + engine/narcissus-core/src/libc.rs | 7 ++- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 engine/narcissus-core/src/crypto_random.rs diff --git a/engine/narcissus-core/src/crypto_random.rs b/engine/narcissus-core/src/crypto_random.rs new file mode 100644 index 0000000..b0df874 --- /dev/null +++ b/engine/narcissus-core/src/crypto_random.rs @@ -0,0 +1,60 @@ +use std::ffi::c_void; + +use crate::{errno, libc}; + +/// Fill `bytes` with output from the system's cryptographically secure PRNG. +/// +/// Linux +/// --- +/// +/// Utilizes libc's `getrandom` API in blocking mode. +pub fn fill_random(bytes: &mut [u8]) { + #[cfg(not(target_os = "linux"))] + const _: () = panic!("unsupported os"); + + #[cfg(target_os = "linux")] + unsafe { + loop { + let res = libc::getrandom(bytes.as_mut_ptr() as *mut c_void, bytes.len(), 0); + if res == bytes.len() as isize { + break; + } + + if res < 0 && errno::errno().0 != errno::unix::EINTR { + panic!(); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::fill_random; + + #[test] + fn generate_random_small() { + let mut data_0 = [0; 256]; + let mut data_1 = [0; 256]; + + fill_random(&mut data_0); + fill_random(&mut data_1); + + assert!(!data_0.iter().all(|&byte| byte == 0)); + assert!(!data_1.iter().all(|&byte| byte == 0)); + assert_ne!(data_0, data_1); + } + + #[test] + fn generate_random_large() { + const MIB: usize = 1024 * 1024; + let mut data_0 = vec![0; 64 * MIB]; + let mut data_1 = vec![0; 64 * MIB]; + + fill_random(&mut data_0); + fill_random(&mut data_1); + + assert!(!data_0.iter().all(|&byte| byte == 0)); + assert!(!data_1.iter().all(|&byte| byte == 0)); + assert_ne!(data_0, data_1); + } +} diff --git a/engine/narcissus-core/src/lib.rs b/engine/narcissus-core/src/lib.rs index ce07276..30ad466 100644 --- a/engine/narcissus-core/src/lib.rs +++ b/engine/narcissus-core/src/lib.rs @@ -1,5 +1,6 @@ mod arena; mod bitset; +pub mod crypto_random; pub mod dds; mod directory; pub mod errno; diff --git a/engine/narcissus-core/src/libc.rs b/engine/narcissus-core/src/libc.rs index d963b91..24ec081 100644 --- a/engine/narcissus-core/src/libc.rs +++ b/engine/narcissus-core/src/libc.rs @@ -2,7 +2,10 @@ #![allow(non_upper_case_globals)] #![allow(unused)] -use std::os::raw::{c_int, c_long, c_void}; +use std::{ + ffi::c_uint, + os::raw::{c_int, c_long, c_void}, +}; pub type size_t = usize; pub type ptrdiff_t = isize; @@ -443,4 +446,6 @@ extern "C" { #[cfg_attr(target_os = "linux", link_name = "__errno_location")] pub fn errno_location() -> *mut c_int; + + pub fn getrandom(buf: *mut c_void, buf_len: size_t, flags: c_uint) -> isize; } -- 2.49.0