kernel/
random.rs

1//! # Kernel Random Number Generator
2//!
3//! This module provides a kernel-level random number generation facility.
4//! It abstracts away the underlying entropy sources and provides a unified
5//! interface for obtaining random numbers throughout the kernel.
6//!
7//! ## Architecture
8//!
9//! The RNG subsystem consists of:
10//! - A central RNG manager that coordinates entropy sources
11//! - Multiple entropy sources (e.g., virtio-rng, hardware RNG, timer jitter)
12//! - A buffered output that can be accessed via CharDevice interface
13//!
14//! ## Usage
15//!
16//! ```rust
17//! use crate::random::RandomManager;
18//!
19//! // Get random bytes
20//! let mut buffer = [0u8; 32];
21//! RandomManager::get_random_bytes(&mut buffer);
22//! ```
23
24use alloc::collections::VecDeque;
25use alloc::sync::Arc;
26use alloc::vec::Vec;
27use core::any::Any;
28use spin::{Mutex, Once};
29
30use crate::device::char::CharDevice;
31use crate::device::{Device, DeviceType};
32use crate::object::capability::{ControlOps, MemoryMappingOps, Selectable};
33
34/// Size of the internal random pool buffer
35const RANDOM_POOL_SIZE: usize = 4096;
36
37/// Trait for entropy sources that can provide random data
38pub trait EntropySource: Send + Sync {
39    /// Get a name for this entropy source
40    fn name(&self) -> &'static str;
41
42    /// Read random bytes from this source
43    ///
44    /// # Arguments
45    ///
46    /// * `buffer` - Buffer to fill with random data
47    ///
48    /// # Returns
49    ///
50    /// Number of bytes actually read
51    fn read_entropy(&self, buffer: &mut [u8]) -> usize;
52
53    /// Check if this source is available and ready
54    fn is_available(&self) -> bool;
55}
56
57/// Random number generator manager
58///
59/// This is the central component that manages entropy sources and provides
60/// random numbers to the rest of the kernel.
61pub struct RandomManager {
62    /// Registered entropy sources
63    sources: Mutex<Vec<Arc<dyn EntropySource>>>,
64    /// Internal random pool buffer
65    pool: Mutex<VecDeque<u8>>,
66}
67
68impl RandomManager {
69    /// Create a new RandomManager
70    fn new() -> Self {
71        Self {
72            sources: Mutex::new(Vec::new()),
73            pool: Mutex::new(VecDeque::with_capacity(RANDOM_POOL_SIZE)),
74        }
75    }
76
77    /// Get the global RandomManager instance
78    fn instance() -> &'static RandomManager {
79        static INSTANCE: Once<RandomManager> = Once::new();
80        INSTANCE.call_once(|| RandomManager::new())
81    }
82
83    /// Register an entropy source
84    ///
85    /// # Arguments
86    ///
87    /// * `source` - The entropy source to register
88    pub fn register_entropy_source(source: Arc<dyn EntropySource>) {
89        let manager = Self::instance();
90        let mut sources = manager.sources.lock();
91        crate::early_println!("[Random] Registering entropy source: {}", source.name());
92        sources.push(source);
93    }
94
95    /// Fill the internal pool with entropy from available sources
96    fn fill_pool(&self) -> Result<usize, &'static str> {
97        let sources = self.sources.lock();
98
99        if sources.is_empty() {
100            return Err("No entropy sources available");
101        }
102
103        let mut total_bytes = 0;
104        let mut temp_buffer = [0u8; 256];
105
106        // Try each source until we get some data
107        for source in sources.iter() {
108            if !source.is_available() {
109                continue;
110            }
111
112            let bytes_read = source.read_entropy(&mut temp_buffer);
113            if bytes_read > 0 {
114                let mut pool = self.pool.lock();
115                let available_space = RANDOM_POOL_SIZE.saturating_sub(pool.len());
116                let bytes_to_add = bytes_read.min(available_space);
117
118                if bytes_to_add < bytes_read {
119                    crate::early_println!(
120                        "[Random] Pool full, discarding {} entropy bytes",
121                        bytes_read - bytes_to_add
122                    );
123                }
124
125                for i in 0..bytes_to_add {
126                    pool.push_back(temp_buffer[i]);
127                }
128                total_bytes += bytes_to_add;
129                break; // Got data from one source, that's enough for now
130            }
131        }
132
133        if total_bytes == 0 {
134            Err("Failed to read from any entropy source")
135        } else {
136            Ok(total_bytes)
137        }
138    }
139
140    /// Get random bytes from the pool
141    ///
142    /// # Arguments
143    ///
144    /// * `buffer` - Buffer to fill with random data
145    ///
146    /// # Returns
147    ///
148    /// Number of bytes actually written
149    pub fn get_random_bytes(buffer: &mut [u8]) -> usize {
150        let manager = Self::instance();
151        let mut bytes_read = 0;
152
153        for i in 0..buffer.len() {
154            // Try to get byte from pool
155            let mut pool = manager.pool.lock();
156            if let Some(byte) = pool.pop_front() {
157                buffer[i] = byte;
158                bytes_read += 1;
159            } else {
160                // Pool is empty, try to refill while holding the lock
161                drop(pool);
162                if manager.fill_pool().is_err() {
163                    // Can't get more entropy
164                    return bytes_read;
165                }
166                // Try again after refill
167                pool = manager.pool.lock();
168                if let Some(byte) = pool.pop_front() {
169                    buffer[i] = byte;
170                    bytes_read += 1;
171                } else {
172                    // Still empty, give up
173                    drop(pool);
174                    return bytes_read;
175                }
176            }
177        }
178
179        bytes_read
180    }
181
182    /// Read a single random byte
183    pub fn get_random_byte() -> Option<u8> {
184        let mut buffer = [0u8; 1];
185        if Self::get_random_bytes(&mut buffer) == 1 {
186            Some(buffer[0])
187        } else {
188            None
189        }
190    }
191}
192
193/// Character device interface for /dev/random
194///
195/// This provides the /dev/random device that userspace can read from.
196pub struct RandomCharDevice;
197
198impl RandomCharDevice {
199    pub fn new() -> Self {
200        Self
201    }
202}
203
204impl Device for RandomCharDevice {
205    fn device_type(&self) -> DeviceType {
206        DeviceType::Char
207    }
208
209    fn name(&self) -> &'static str {
210        "random"
211    }
212
213    fn as_any(&self) -> &dyn Any {
214        self
215    }
216
217    fn as_any_mut(&mut self) -> &mut dyn Any {
218        self
219    }
220
221    fn as_char_device(&self) -> Option<&dyn CharDevice> {
222        Some(self)
223    }
224}
225
226impl CharDevice for RandomCharDevice {
227    fn read_byte(&self) -> Option<u8> {
228        RandomManager::get_random_byte()
229    }
230
231    fn write_byte(&self, _byte: u8) -> Result<(), &'static str> {
232        Err("Write not supported for random device")
233    }
234
235    fn can_read(&self) -> bool {
236        // Check if we have any entropy sources available
237        let manager = RandomManager::instance();
238        let sources = manager.sources.lock();
239        !sources.is_empty() && sources.iter().any(|s| s.is_available())
240    }
241
242    fn can_write(&self) -> bool {
243        false
244    }
245}
246
247impl ControlOps for RandomCharDevice {
248    fn control(&self, _command: u32, _arg: usize) -> Result<i32, &'static str> {
249        Err("Control operations not supported for random device")
250    }
251}
252
253impl MemoryMappingOps for RandomCharDevice {
254    fn get_mapping_info(
255        &self,
256        _offset: usize,
257        _length: usize,
258    ) -> Result<(usize, usize, bool), &'static str> {
259        Err("Memory mapping not supported for random device")
260    }
261}
262
263impl Selectable for RandomCharDevice {
264    fn wait_until_ready(
265        &self,
266        _interest: crate::object::capability::selectable::ReadyInterest,
267        _trapframe: &mut crate::arch::Trapframe,
268        _timeout_ticks: Option<u64>,
269    ) -> crate::object::capability::selectable::SelectWaitOutcome {
270        crate::object::capability::selectable::SelectWaitOutcome::Ready
271    }
272}