hermit/syscalls/
entropy.rs#[cfg(not(feature = "newlib"))]
use core::mem::size_of;
use core::slice;
use hermit_sync::TicketMutex;
use crate::arch;
use crate::entropy::{self, Flags};
use crate::errno::EINVAL;
static PARK_MILLER_LEHMER_SEED: TicketMutex<u32> = TicketMutex::new(0);
const RAND_MAX: u64 = 2_147_483_647;
fn generate_park_miller_lehmer_random_number() -> u32 {
let mut seed = PARK_MILLER_LEHMER_SEED.lock();
let random = ((u64::from(*seed) * 48271) % RAND_MAX) as u32;
*seed = random;
random
}
unsafe fn read_entropy(buf: *mut u8, len: usize, flags: u32) -> isize {
let Some(flags) = Flags::from_bits(flags) else {
return -EINVAL as isize;
};
let buf = unsafe {
let len = usize::min(len, isize::MAX as usize);
buf.write_bytes(0, len);
slice::from_raw_parts_mut(buf, len)
};
let ret = entropy::read(buf, flags);
if ret < 0 {
warn!("Unable to read entropy! Fallback to a naive implementation!");
for i in &mut *buf {
*i = (generate_park_miller_lehmer_random_number() & 0xFF)
.try_into()
.unwrap();
}
buf.len().try_into().unwrap()
} else {
ret
}
}
unsafe extern "C" fn __sys_read_entropy(buf: *mut u8, len: usize, flags: u32) -> isize {
unsafe { read_entropy(buf, len, flags) }
}
#[no_mangle]
pub unsafe extern "C" fn sys_read_entropy(buf: *mut u8, len: usize, flags: u32) -> isize {
unsafe { kernel_function!(__sys_read_entropy(buf, len, flags)) }
}
#[cfg(not(feature = "newlib"))]
#[hermit_macro::system]
#[no_mangle]
pub unsafe extern "C" fn sys_secure_rand32(value: *mut u32) -> i32 {
let mut buf = value.cast();
let mut len = size_of::<u32>();
while len != 0 {
let res = unsafe { read_entropy(buf, len, 0) };
if res < 0 {
return -1;
}
buf = unsafe { buf.add(res as usize) };
len -= res as usize;
}
0
}
#[cfg(not(feature = "newlib"))]
#[hermit_macro::system]
#[no_mangle]
pub unsafe extern "C" fn sys_secure_rand64(value: *mut u64) -> i32 {
let mut buf = value.cast();
let mut len = size_of::<u64>();
while len != 0 {
let res = unsafe { read_entropy(buf, len, 0) };
if res < 0 {
return -1;
}
buf = unsafe { buf.add(res as usize) };
len -= res as usize;
}
0
}
#[hermit_macro::system]
#[no_mangle]
pub extern "C" fn sys_rand() -> u32 {
generate_park_miller_lehmer_random_number()
}
#[hermit_macro::system]
#[no_mangle]
pub extern "C" fn sys_srand(seed: u32) {
*(PARK_MILLER_LEHMER_SEED.lock()) = seed;
}
pub(crate) fn init_entropy() {
let seed: u32 = arch::processor::get_timestamp() as u32;
*PARK_MILLER_LEHMER_SEED.lock() = seed;
}