quantica/ml_kem/rng.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Cédric Mesnil <cslashm@pm.me>
3
4/// Minimal cryptographic RNG trait and OS-backed implementation.
5///
6/// Provides the [`CryptoRng`] trait used throughout ML-KEM for obtaining
7/// random bytes, and [`OsRng`], a zero-dependency implementation backed
8/// by the operating system's entropy source.
9use super::MlKemError;
10
11/// Trait for cryptographic-quality random byte generation.
12///
13/// Implementations must provide bytes suitable for key material and nonces.
14/// The trait is intentionally minimal (a single method) to allow easy
15/// integration with external RNG libraries or hardware RNGs.
16///
17/// # Errors
18///
19/// Returns [`MlKemError::RngFailure`] if the underlying entropy source
20/// is unavailable or fails.
21pub trait CryptoRng {
22 /// Fill `dest` with cryptographically secure random bytes.
23 ///
24 /// # Errors
25 ///
26 /// Returns [`MlKemError::RngFailure`] on failure.
27 fn fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), MlKemError>;
28}
29
30/// OS-backed cryptographic RNG reading from `/dev/urandom` on Unix.
31///
32/// Only available with the `std` feature. In `no_std` builds, callers
33/// must supply their own [`CryptoRng`] implementation (typically
34/// wrapping a hardware RNG on embedded targets).
35#[cfg(feature = "std")]
36pub struct OsRng;
37
38#[cfg(feature = "std")]
39impl CryptoRng for OsRng {
40 /// Fill `dest` with random bytes from `/dev/urandom`.
41 fn fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), MlKemError> {
42 use std::io::Read;
43 let mut f = std::fs::File::open("/dev/urandom").map_err(|_| MlKemError::RngFailure)?;
44 f.read_exact(dest).map_err(|_| MlKemError::RngFailure)
45 }
46}