1use crate::aws_lc::RAND_bytes;
29use crate::error::Unspecified;
30use crate::fips::indicator_check;
31use core::fmt::Debug;
32
33#[cfg(any(dev_tests_only, aws_lc_rs_docsrs))]
58#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "dev-tests-only")))]
59#[allow(unused_imports)]
60pub mod unsealed {
61 pub use super::sealed::*;
62}
63
64pub trait SecureRandom: sealed::SecureRandom {
66 fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified>;
71
72 #[cfg(any(test, dev_tests_only, aws_lc_rs_docsrs))]
79 #[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "dev-tests-only")))]
80 fn mut_fill(&mut self, dest: &mut [u8]) -> Result<(), Unspecified>;
81}
82
83impl<T> SecureRandom for T
84where
85 T: sealed::SecureRandom,
86{
87 #[inline]
88 fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
89 self.fill_impl(dest)
90 }
91
92 #[inline]
93 #[cfg(any(test, dev_tests_only, aws_lc_rs_docsrs))]
94 fn mut_fill(&mut self, dest: &mut [u8]) -> Result<(), Unspecified> {
95 self.fill_impl(dest)
96 }
97}
98
99pub struct Random<T: RandomlyConstructable>(T);
104
105impl<T: RandomlyConstructable> Random<T> {
106 #[inline]
108 pub fn expose(self) -> T {
109 self.0
110 }
111}
112
113#[inline]
118pub fn generate<T: RandomlyConstructable>(
119 rng: &dyn SecureRandom,
120) -> Result<Random<T>, Unspecified> {
121 let mut r = T::zero();
122 rng.fill(r.as_mut_bytes())?;
123 Ok(Random(r))
124}
125
126pub(crate) mod sealed {
127 use crate::error;
128
129 pub trait SecureRandom: core::fmt::Debug {
131 fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
136 }
137
138 pub trait RandomlyConstructable: Sized {
140 fn zero() -> Self;
142 fn as_mut_bytes(&mut self) -> &mut [u8];
144 }
145
146 impl<const T: usize> RandomlyConstructable for [u8; T] {
147 #[inline]
148 fn zero() -> Self {
149 [0; T]
150 }
151
152 #[inline]
153 fn as_mut_bytes(&mut self) -> &mut [u8] {
154 &mut self[..]
155 }
156 }
157}
158
159pub trait RandomlyConstructable: sealed::RandomlyConstructable {}
161
162impl<T> RandomlyConstructable for T where T: sealed::RandomlyConstructable {}
163
164#[derive(Clone, Debug)]
172pub struct SystemRandom(());
173
174const SYSTEM_RANDOM: SystemRandom = SystemRandom(());
175
176impl SystemRandom {
177 #[inline]
179 #[must_use]
180 pub fn new() -> Self {
181 Self::default()
182 }
183}
184
185impl Default for SystemRandom {
186 fn default() -> Self {
187 SYSTEM_RANDOM
188 }
189}
190
191impl sealed::SecureRandom for SystemRandom {
192 #[inline]
193 fn fill_impl(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
194 fill(dest)
195 }
196}
197
198pub fn fill(dest: &mut [u8]) -> Result<(), Unspecified> {
206 if 1 != indicator_check!(unsafe { RAND_bytes(dest.as_mut_ptr(), dest.len()) }) {
207 return Err(Unspecified);
208 }
209 Ok(())
210}
211
212#[cfg(test)]
213mod tests {
214 use crate::rand;
215 use core::array::IntoIter;
216
217 use crate::rand::{generate, SecureRandom, SystemRandom};
218
219 #[test]
220 fn test_secure_random_fill() {
221 let mut random_array = [0u8; 1009];
223 let rng = SystemRandom::new();
224 rng.fill(&mut random_array).unwrap();
225
226 let (mean, variance) = mean_variance(&mut random_array.into_iter());
227 assert!((106f64..150f64).contains(&mean), "Mean: {mean}");
228 assert!(variance > 8f64);
229 println!("Mean: {mean} Variance: {variance}");
230 }
231
232 #[test]
233 fn test_rand_fill() {
234 let mut random_array = [0u8; 1009];
236 rand::fill(&mut random_array).unwrap();
237
238 let (mean, variance) = mean_variance(&mut random_array.into_iter());
239 assert!((106f64..150f64).contains(&mean), "Mean: {mean}");
240 assert!(variance > 8f64);
241 println!("Mean: {mean} Variance: {variance}");
242 }
243
244 #[test]
245 fn test_randomly_constructable() {
246 let rando = SystemRandom::new();
247 let random_array = generate(&rando).unwrap();
248 let random_array: [u8; 1009] = random_array.expose();
250 let (mean, variance) = mean_variance(&mut random_array.into_iter());
251 assert!((106f64..150f64).contains(&mean), "Mean: {mean}");
252 assert!(variance > 8f64);
253 println!("Mean: {mean} Variance: {variance}");
254 }
255
256 fn mean_variance<T: Into<f64>, const N: usize>(iterable: &mut IntoIter<T, N>) -> (f64, f64) {
257 let iter = iterable;
258 let mean: Option<T> = iter.next();
259 let mut mean = mean.unwrap().into();
260 let mut var_squared = 0f64;
261 let mut count = 1f64;
262 for value in iter.by_ref() {
263 count += 1f64;
264 let value = value.into();
265 let prev_mean = mean;
266 mean = prev_mean + (value - prev_mean) / count;
267 var_squared =
268 var_squared + ((value - prev_mean) * (value - mean) - var_squared) / count;
269 }
270
271 (mean, var_squared.sqrt())
272 }
273}