aws_lc_rs/
rand.rs

1// Copyright 2015-2016 Brian Smith.
2// SPDX-License-Identifier: ISC
3// Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4// SPDX-License-Identifier: Apache-2.0 OR ISC
5
6//! Cryptographic pseudo-random number generation.
7//!
8//! An application should create a single `SystemRandom` and then use it for
9//! all randomness generation. See `SystemRandom`'s documentation for more
10//! details.
11
12//! # Example
13//! ```
14//! use aws_lc_rs::{rand, rand::SecureRandom};
15//!
16//! //  Using `rand::fill`
17//! let mut rand_bytes = [0u8; 32];
18//! rand::fill(&mut rand_bytes).unwrap();
19//!
20//! // Using `SystemRandom`
21//! let rng = rand::SystemRandom::new();
22//! rng.fill(&mut rand_bytes).unwrap();
23//!
24//! // Using `rand::generate`
25//! let random_array = rand::generate(&rng).unwrap();
26//! let more_rand_bytes: [u8; 64] = random_array.expose();
27//! ```
28use crate::aws_lc::RAND_bytes;
29use crate::error::Unspecified;
30use crate::fips::indicator_check;
31use core::fmt::Debug;
32
33/// Re-exports of sealed traits for development testing.
34#[cfg(dev_tests_only)]
35#[allow(unused_imports)]
36pub mod unsealed {
37    pub use super::sealed::*;
38}
39
40/// A secure random number generator.
41pub trait SecureRandom: sealed::SecureRandom {
42    /// Fills `dest` with random bytes.
43    ///
44    /// # Errors
45    /// `error::Unspecified` if unable to fill `dest`.
46    fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified>;
47
48    /// Fills `dest` with random bytes.
49    ///
50    /// # Errors
51    /// `error::Unspecified` if unable to fill `dest`.
52    #[cfg(any(test, dev_tests_only))]
53    fn mut_fill(&mut self, dest: &mut [u8]) -> Result<(), Unspecified>;
54}
55
56impl<T> SecureRandom for T
57where
58    T: sealed::SecureRandom,
59{
60    #[inline]
61    fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
62        self.fill_impl(dest)
63    }
64
65    #[inline]
66    #[cfg(any(test, dev_tests_only))]
67    fn mut_fill(&mut self, dest: &mut [u8]) -> Result<(), Unspecified> {
68        self.fill_impl(dest)
69    }
70}
71
72/// A random value constructed from a `SecureRandom` that hasn't been exposed
73/// through any safe Rust interface.
74///
75/// Intentionally does not implement any traits other than `Sized`.
76pub struct Random<T: RandomlyConstructable>(T);
77
78impl<T: RandomlyConstructable> Random<T> {
79    /// Expose the random value.
80    #[inline]
81    pub fn expose(self) -> T {
82        self.0
83    }
84}
85
86/// Generate the new random value using `rng`.
87///
88/// # Errors
89/// `error::Unspecified` if unable to fill buffer.
90#[inline]
91pub fn generate<T: RandomlyConstructable>(
92    rng: &dyn SecureRandom,
93) -> Result<Random<T>, Unspecified> {
94    let mut r = T::zero();
95    rng.fill(r.as_mut_bytes())?;
96    Ok(Random(r))
97}
98
99pub(crate) mod sealed {
100    use crate::error;
101
102    /// A sealed trait for secure random number generation.
103    pub trait SecureRandom: core::fmt::Debug {
104        /// Fills `dest` with random bytes.
105        ///
106        /// # Errors
107        /// Returns `error::Unspecified` if unable to fill `dest`.
108        fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
109    }
110
111    /// A sealed trait for types that can be randomly constructed.
112    pub trait RandomlyConstructable: Sized {
113        /// Returns a zeroed instance of the type.
114        fn zero() -> Self;
115        /// Returns a mutable byte slice of the value.
116        fn as_mut_bytes(&mut self) -> &mut [u8];
117    }
118
119    impl<const T: usize> RandomlyConstructable for [u8; T] {
120        #[inline]
121        fn zero() -> Self {
122            [0; T]
123        }
124
125        #[inline]
126        fn as_mut_bytes(&mut self) -> &mut [u8] {
127            &mut self[..]
128        }
129    }
130}
131
132/// A type that can be returned by `aws_lc_rs::rand::generate()`.
133pub trait RandomlyConstructable: sealed::RandomlyConstructable {}
134
135impl<T> RandomlyConstructable for T where T: sealed::RandomlyConstructable {}
136
137/// A secure random number generator where the random values come from the
138/// underlying *AWS-LC* libcrypto.
139///
140/// A single `SystemRandom` may be shared across multiple threads safely.
141//
142// # FIPS
143// Use this implementation for retrieving random bytes.
144#[derive(Clone, Debug)]
145pub struct SystemRandom(());
146
147const SYSTEM_RANDOM: SystemRandom = SystemRandom(());
148
149impl SystemRandom {
150    /// Constructs a new `SystemRandom`.
151    #[inline]
152    #[must_use]
153    pub fn new() -> Self {
154        Self::default()
155    }
156}
157
158impl Default for SystemRandom {
159    fn default() -> Self {
160        SYSTEM_RANDOM
161    }
162}
163
164impl sealed::SecureRandom for SystemRandom {
165    #[inline]
166    fn fill_impl(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
167        fill(dest)
168    }
169}
170
171/// Fills `dest` with random bytes.
172///
173// # FIPS
174// Use this for retrieving random bytes or [`SystemRandom`].
175//
176/// # Errors
177/// `error::Unspecified` if unable to fill `dest`.
178pub fn fill(dest: &mut [u8]) -> Result<(), Unspecified> {
179    if 1 != indicator_check!(unsafe { RAND_bytes(dest.as_mut_ptr(), dest.len()) }) {
180        return Err(Unspecified);
181    }
182    Ok(())
183}
184
185#[cfg(test)]
186mod tests {
187    use crate::rand;
188    use core::array::IntoIter;
189
190    use crate::rand::{generate, SecureRandom, SystemRandom};
191
192    #[test]
193    fn test_secure_random_fill() {
194        // Collect enough random values so that the assertions below should never fail again
195        let mut random_array = [0u8; 1009];
196        let rng = SystemRandom::new();
197        rng.fill(&mut random_array).unwrap();
198
199        let (mean, variance) = mean_variance(&mut random_array.into_iter());
200        assert!((106f64..150f64).contains(&mean), "Mean: {mean}");
201        assert!(variance > 8f64);
202        println!("Mean: {mean} Variance: {variance}");
203    }
204
205    #[test]
206    fn test_rand_fill() {
207        // Collect enough random values so that the assertions below should never fail again
208        let mut random_array = [0u8; 1009];
209        rand::fill(&mut random_array).unwrap();
210
211        let (mean, variance) = mean_variance(&mut random_array.into_iter());
212        assert!((106f64..150f64).contains(&mean), "Mean: {mean}");
213        assert!(variance > 8f64);
214        println!("Mean: {mean} Variance: {variance}");
215    }
216
217    #[test]
218    fn test_randomly_constructable() {
219        let rando = SystemRandom::new();
220        let random_array = generate(&rando).unwrap();
221        // Collect enough random values so that the assertions below should never fail again
222        let random_array: [u8; 1009] = random_array.expose();
223        let (mean, variance) = mean_variance(&mut random_array.into_iter());
224        assert!((106f64..150f64).contains(&mean), "Mean: {mean}");
225        assert!(variance > 8f64);
226        println!("Mean: {mean} Variance: {variance}");
227    }
228
229    fn mean_variance<T: Into<f64>, const N: usize>(iterable: &mut IntoIter<T, N>) -> (f64, f64) {
230        let iter = iterable;
231        let mean: Option<T> = iter.next();
232        let mut mean = mean.unwrap().into();
233        let mut var_squared = 0f64;
234        let mut count = 1f64;
235        for value in iter.by_ref() {
236            count += 1f64;
237            let value = value.into();
238            let prev_mean = mean;
239            mean = prev_mean + (value - prev_mean) / count;
240            var_squared =
241                var_squared + ((value - prev_mean) * (value - mean) - var_squared) / count;
242        }
243
244        (mean, var_squared.sqrt())
245    }
246}