1use crate::rng::{SecureYARandGenerator, YARandGenerator};
2use chacha20::{
3 rand_core::{RngCore, SeedableRng},
4 ChaCha8Rng,
5};
6use core::{mem::size_of, ptr::write_volatile, sync::atomic};
7
8#[derive(Debug)]
13pub struct SecureRng {
14 internal: ChaCha8Rng,
15}
16
17impl Drop for SecureRng {
22 fn drop(&mut self) {
23 let self_ptr = (self as *mut Self).cast::<u8>();
24 for i in 0..size_of::<SecureRng>() {
25 unsafe {
27 write_volatile(self_ptr.add(i), 0);
28 }
29 }
30 atomic::compiler_fence(atomic::Ordering::SeqCst);
31 }
32}
33
34impl SecureYARandGenerator for SecureRng {
35 #[inline(never)]
36 fn fill_bytes(&mut self, dest: &mut [u8]) {
37 self.internal.fill_bytes(dest);
38 }
39}
40
41impl YARandGenerator for SecureRng {
42 fn try_new() -> Result<Self, getrandom::Error> {
43 const SEED_LEN: usize = 32;
44 const STREAM_LEN: usize = 12;
45 let mut data = [0; SEED_LEN + STREAM_LEN];
47 getrandom::fill(&mut data)?;
48 let seed: [u8; SEED_LEN] = data[..SEED_LEN].try_into().unwrap();
50 let stream: [u8; STREAM_LEN] = data[SEED_LEN..].try_into().unwrap();
51 let mut internal = ChaCha8Rng::from_seed(seed);
52 internal.set_stream(stream);
53 Ok(Self { internal })
54 }
55
56 #[cfg_attr(feature = "inline", inline)]
57 fn u64(&mut self) -> u64 {
58 self.internal.next_u64()
59 }
60}