Skip to main content

ic_rustls/
random.rs

1//! Randomness.
2//!
3//! Signing lives in `crate::sign`; this module used to hold a `KeyProvider`
4//! that refused every key, and no longer needs to.
5
6use rustls::crypto::{GetRandomFailed, SecureRandom};
7
8/// The SP 800-90A HMAC\_DRBG, seeded from the operating system.
9///
10/// rustls draws the client and server randoms, session identifiers and ticket
11/// nonces through this. A fresh generator per call is deliberate: the
12/// alternative is one shared instance behind a lock, which would either
13/// serialise every handshake in the process or need care about fork safety that
14/// a per-call draw does not.
15#[derive(Debug)]
16pub struct Random;
17
18impl SecureRandom for Random {
19    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
20        let mut rng = ic_drbg::Rng::from_os().map_err(|_| GetRandomFailed)?;
21        rng.fill(buf).map_err(|_| GetRandomFailed)
22    }
23
24    /// Always false; see the crate documentation.
25    fn fips(&self) -> bool {
26        false
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    /// The generator must generate.
35    ///
36    /// Two draws being equal would mean a fixed output, which for a client
37    /// random is the difference between a handshake and a replay.
38    #[test]
39    fn the_random_source_produces_fresh_bytes() {
40        let mut a = [0u8; 32];
41        let mut b = [0u8; 32];
42        Random.fill(&mut a).unwrap();
43        Random.fill(&mut b).unwrap();
44        assert_ne!(a, b, "two draws were identical");
45        assert_ne!(a, [0u8; 32], "the buffer was left untouched");
46
47        // An empty request is not an error, and a large one is filled.
48        Random.fill(&mut []).unwrap();
49        let mut big = alloc::vec![0u8; 4096];
50        Random.fill(&mut big).unwrap();
51        assert!(big.iter().any(|b| *b != 0));
52    }
53
54    #[test]
55    fn the_random_source_claims_no_fips_validation() {
56        assert!(!Random.fips());
57    }
58}