Skip to main content

osom_lib_entropy/std/
mod.rs

1//! Holds the implementation of the standard entropy generator, based
2//! on the operating system's available entropy sources.
3
4mod fill_impl;
5
6use core::marker::PhantomData;
7
8use osom_lib_reprc::macros::reprc;
9
10use crate::traits::{EntropyConcreteGenerator, EntropyGenerator};
11
12/// An enum for handling various failures of entropy generation.
13#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
14#[reprc]
15#[repr(u8)]
16pub enum StdEntropyError {
17    GenericKernelError = 0,
18}
19
20/// The standard entropy generator. It uses various os available
21/// operations to generate entropy:
22///
23/// * `macos` <- it utilizes `getentropy` syscall
24/// * `linux` <- it utilizes `getrandom` syscall
25/// * `windows` <- it utilizes `ProcessPrng` syscall
26///
27/// Other platforms are not supported at the moment.
28#[derive(Debug, Default, Clone, Copy)]
29#[reprc]
30#[must_use]
31pub struct StdEntropyGenerator(PhantomData<()>);
32
33impl StdEntropyGenerator {
34    /// Creates a new instance of [`StdEntropyGenerator`]. This
35    /// method is basically free.
36    #[inline(always)]
37    pub const fn new() -> Self {
38        Self(PhantomData)
39    }
40}
41
42impl EntropyGenerator for StdEntropyGenerator {
43    type Error = StdEntropyError;
44
45    unsafe fn fill_raw(&mut self, buffer_ptr: *mut u8, buffer_len: usize) -> Result<(), Self::Error> {
46        fill_impl::fill(buffer_ptr, buffer_len)
47    }
48}
49
50#[inline]
51fn generate_random_t<T: Copy, TGen: EntropyGenerator>(gene: &mut TGen) -> Result<T, TGen::Error> {
52    let mut item = core::mem::MaybeUninit::<T>::uninit();
53    let item_ptr = item.as_mut_ptr();
54    let slice = unsafe { core::slice::from_raw_parts_mut(item_ptr.cast::<u8>(), size_of::<T>()) };
55    gene.fill(slice)?;
56    Ok(unsafe { item.assume_init() })
57}
58
59impl<const N: usize> EntropyConcreteGenerator<StdEntropyGenerator> for [u8; N] {
60    #[inline(always)]
61    fn generate(generator: &mut StdEntropyGenerator) -> Result<Self, StdEntropyError> {
62        if N == 0 {
63            return Ok([0u8; N]);
64        }
65        generate_random_t(generator)
66    }
67}
68
69macro_rules! concrete {
70    ( $t: ty ) => {
71        impl EntropyConcreteGenerator<StdEntropyGenerator> for $t {
72            #[inline(always)]
73            fn generate(generator: &mut StdEntropyGenerator) -> Result<Self, StdEntropyError>
74            {
75                generate_random_t(generator)
76            }
77        }
78    };
79    ( $t: ty, $($ts:ty),* $(,)?) => {
80        concrete!($t);
81        concrete!($($ts),*);
82    };
83}
84
85concrete!(i16, u16, i32, u32, i64, u64, i128, u128, usize, isize);