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}