1#![allow(dead_code)]
6use alloc::{vec, vec::Vec};
20
21use spin::Mutex;
22
23use super::CryptoResult;
24use crate::sync::once_lock::OnceLock;
25
26const RESEED_INTERVAL: u64 = 4096;
28
29pub(crate) struct SecureRandom {
31 state: Mutex<RandomState>,
32}
33
34struct RandomState {
35 key: [u8; 32],
37 nonce: [u8; 12],
39 counter: u32,
41 buffer: [u8; 64],
43 buffer_pos: usize,
45 reseed_counter: u64,
47 entropy_pool: [u8; 32],
49 pool_idx: usize,
51}
52
53impl SecureRandom {
54 pub(crate) fn new() -> CryptoResult<Self> {
56 let seed = Self::get_entropy()?;
58
59 let key_material = super::hash::sha256(&seed);
61 let nonce_input = {
62 let mut input = [0u8; 33];
63 input[..32].copy_from_slice(&seed);
64 input[32] = 0x01; input
66 };
67 let nonce_material = super::hash::sha256(&nonce_input);
68
69 let mut key = [0u8; 32];
70 key.copy_from_slice(key_material.as_bytes());
71
72 let mut nonce = [0u8; 12];
73 nonce.copy_from_slice(&nonce_material.as_bytes()[..12]);
74
75 let buffer = Self::chacha20_block_static(&key, &nonce, 0);
77
78 Ok(Self {
79 state: Mutex::new(RandomState {
80 key,
81 nonce,
82 counter: 1, buffer,
84 buffer_pos: 0,
85 reseed_counter: 0,
86 entropy_pool: [0u8; 32],
87 pool_idx: 0,
88 }),
89 })
90 }
91
92 pub(crate) fn fill_bytes(&self, dest: &mut [u8]) -> CryptoResult<()> {
94 let mut state = self.state.lock();
95
96 state.reseed_counter += 1;
98 if state.reseed_counter >= RESEED_INTERVAL {
99 Self::reseed_state(&mut state);
100 }
101
102 let mut i = 0;
104 while i < dest.len() {
105 if state.buffer_pos >= 64 {
106 state.buffer = Self::chacha20_block_static(&state.key, &state.nonce, state.counter);
108 state.counter = state.counter.wrapping_add(1);
109 state.buffer_pos = 0;
110
111 if state.counter.is_multiple_of(256) {
113 Self::mix_entropy_into_key(&mut state);
114 }
115 }
116 dest[i] = state.buffer[state.buffer_pos];
117 state.buffer_pos += 1;
118 i += 1;
119 }
120
121 Ok(())
122 }
123
124 pub(crate) fn next_u64(&self) -> u64 {
126 let mut bytes = [0u8; 8];
127 if let Err(_e) = self.fill_bytes(&mut bytes) {
128 crate::println!("[CSPRNG] Warning: fill_bytes failed in next_u64: {:?}", _e);
129 }
130 u64::from_le_bytes(bytes)
131 }
132
133 pub(crate) fn next_u32(&self) -> u32 {
135 let mut bytes = [0u8; 4];
136 if let Err(_e) = self.fill_bytes(&mut bytes) {
137 crate::println!("[CSPRNG] Warning: fill_bytes failed in next_u32: {:?}", _e);
138 }
139 u32::from_le_bytes(bytes)
140 }
141
142 #[inline]
148 fn qr(state: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize) {
149 state[a] = state[a].wrapping_add(state[b]);
150 state[d] ^= state[a];
151 state[d] = state[d].rotate_left(16);
152
153 state[c] = state[c].wrapping_add(state[d]);
154 state[b] ^= state[c];
155 state[b] = state[b].rotate_left(12);
156
157 state[a] = state[a].wrapping_add(state[b]);
158 state[d] ^= state[a];
159 state[d] = state[d].rotate_left(8);
160
161 state[c] = state[c].wrapping_add(state[d]);
162 state[b] ^= state[c];
163 state[b] = state[b].rotate_left(7);
164 }
165
166 fn chacha20_block_static(key: &[u8; 32], nonce: &[u8; 12], counter: u32) -> [u8; 64] {
168 let mut state: [u32; 16] = [
169 0x61707865,
170 0x3320646e,
171 0x79622d32,
172 0x6b206574, u32::from_le_bytes([key[0], key[1], key[2], key[3]]),
174 u32::from_le_bytes([key[4], key[5], key[6], key[7]]),
175 u32::from_le_bytes([key[8], key[9], key[10], key[11]]),
176 u32::from_le_bytes([key[12], key[13], key[14], key[15]]),
177 u32::from_le_bytes([key[16], key[17], key[18], key[19]]),
178 u32::from_le_bytes([key[20], key[21], key[22], key[23]]),
179 u32::from_le_bytes([key[24], key[25], key[26], key[27]]),
180 u32::from_le_bytes([key[28], key[29], key[30], key[31]]),
181 counter,
182 u32::from_le_bytes([nonce[0], nonce[1], nonce[2], nonce[3]]),
183 u32::from_le_bytes([nonce[4], nonce[5], nonce[6], nonce[7]]),
184 u32::from_le_bytes([nonce[8], nonce[9], nonce[10], nonce[11]]),
185 ];
186
187 let initial_state = state;
188
189 let mut round = 0;
191 while round < 10 {
192 Self::qr(&mut state, 0, 4, 8, 12);
194 Self::qr(&mut state, 1, 5, 9, 13);
195 Self::qr(&mut state, 2, 6, 10, 14);
196 Self::qr(&mut state, 3, 7, 11, 15);
197 Self::qr(&mut state, 0, 5, 10, 15);
199 Self::qr(&mut state, 1, 6, 11, 12);
200 Self::qr(&mut state, 2, 7, 8, 13);
201 Self::qr(&mut state, 3, 4, 9, 14);
202 round += 1;
203 }
204
205 let mut i = 0;
207 while i < 16 {
208 state[i] = state[i].wrapping_add(initial_state[i]);
209 i += 1;
210 }
211
212 let mut output = [0u8; 64];
214 i = 0;
215 while i < 16 {
216 let bytes = state[i].to_le_bytes();
217 output[i * 4] = bytes[0];
218 output[i * 4 + 1] = bytes[1];
219 output[i * 4 + 2] = bytes[2];
220 output[i * 4 + 3] = bytes[3];
221 i += 1;
222 }
223 output
224 }
225
226 fn get_entropy() -> CryptoResult<[u8; 32]> {
232 use crate::arch::entropy;
233
234 let mut result = [0u8; 32];
235
236 if entropy::try_hardware_rng(&mut result) {
238 return Ok(result);
239 }
240
241 entropy::collect_timer_entropy(&mut result);
243 Ok(result)
244 }
245
246 fn reseed_state(state: &mut RandomState) {
248 use crate::arch::entropy;
249
250 state.reseed_counter = 0;
251
252 let mut fresh_entropy = [0u8; 32];
254 if !entropy::try_hardware_rng(&mut fresh_entropy) {
255 entropy::collect_timer_entropy(&mut fresh_entropy);
256 }
257
258 let mut mix_input = [0u8; 64];
260 mix_input[..32].copy_from_slice(&state.key);
261 mix_input[32..].copy_from_slice(&fresh_entropy);
262 let new_key = super::hash::sha256(&mix_input);
263 state.key.copy_from_slice(new_key.as_bytes());
264
265 let mut nonce_input = [0u8; 44];
267 nonce_input[..32].copy_from_slice(&fresh_entropy);
268 nonce_input[32..36].copy_from_slice(&state.counter.to_le_bytes());
269 nonce_input[36..44].copy_from_slice(&state.reseed_counter.to_le_bytes());
270 let nonce_hash = super::hash::sha256(&nonce_input);
271 state.nonce.copy_from_slice(&nonce_hash.as_bytes()[..12]);
272
273 state.counter = 0;
275 state.buffer = Self::chacha20_block_static(&state.key, &state.nonce, 0);
276 state.counter = 1;
277 state.buffer_pos = 0;
278 }
279
280 fn mix_entropy_into_key(state: &mut RandomState) {
282 use crate::arch::entropy;
283
284 let sample = entropy::read_timestamp();
286
287 let sample_bytes = sample.to_le_bytes();
289 let mut j = 0;
290 while j < 8 {
291 state.entropy_pool[(state.pool_idx + j) % 32] ^= sample_bytes[j];
292 j += 1;
293 }
294 state.pool_idx = (state.pool_idx + 8) % 32;
295
296 if state.counter.is_multiple_of(1024) {
298 let mut mix = [0u8; 64];
299 mix[..32].copy_from_slice(&state.key);
300 mix[32..].copy_from_slice(&state.entropy_pool);
301 let new_key = super::hash::sha256(&mix);
302 state.key.copy_from_slice(new_key.as_bytes());
303 }
304 }
305}
306
307impl Default for SecureRandom {
308 fn default() -> Self {
309 Self::new().expect("Failed to initialize SecureRandom")
310 }
311}
312
313static RNG_STORAGE: OnceLock<SecureRandom> = OnceLock::new();
315
316pub(crate) fn init() -> CryptoResult<()> {
318 let rng = SecureRandom::new()?;
319 let _ = RNG_STORAGE.set(rng);
320 Ok(())
321}
322
323pub(crate) fn get_random() -> &'static SecureRandom {
325 RNG_STORAGE.get_or_init(|| SecureRandom::new().expect("Failed to create RNG"))
326}
327
328pub(crate) fn random_bytes(count: usize) -> Vec<u8> {
330 let mut bytes = vec![0u8; count];
331
332 let rng = get_random();
333 if let Err(_e) = rng.fill_bytes(&mut bytes) {
334 crate::println!(
335 "[CSPRNG] Warning: fill_bytes failed in random_bytes: {:?}",
336 _e
337 );
338 }
339
340 bytes
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346
347 #[test]
348 fn test_random_generation() {
349 let rng = SecureRandom::new().unwrap();
350 let mut bytes1 = [0u8; 16];
351 let mut bytes2 = [0u8; 16];
352
353 rng.fill_bytes(&mut bytes1).unwrap();
354 rng.fill_bytes(&mut bytes2).unwrap();
355
356 assert_ne!(bytes1, bytes2);
358 }
359}