Coverage Report

Created: 2026-11-12 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.16.3/src/rand.rs
Line
Count
Source
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
//! ```
28
use crate::aws_lc::RAND_bytes;
29
use crate::error::Unspecified;
30
use crate::fips::indicator_check;
31
use core::fmt::Debug;
32
33
/// Re-exports of sealed traits for development testing.
34
///
35
/// This module is only available when the `dev-tests-only` feature is enabled.
36
/// It exposes the [`SecureRandom`](unsealed::SecureRandom) trait, allowing consumers
37
/// to provide their own implementations (e.g., a deterministic RNG) for testing purposes.
38
///
39
/// # Example
40
///
41
/// ```ignore
42
/// use aws_lc_rs::rand::{unsealed, SecureRandom};
43
/// use aws_lc_rs::error::Unspecified;
44
///
45
/// #[derive(Debug)]
46
/// struct DeterministicRandom(u8);
47
///
48
/// impl unsealed::SecureRandom for DeterministicRandom {
49
///     fn fill_impl(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
50
///         for (i, byte) in dest.iter_mut().enumerate() {
51
///             *byte = self.0.wrapping_add(i as u8);
52
///         }
53
///         Ok(())
54
///     }
55
/// }
56
/// ```
57
#[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)]
60
pub mod unsealed {
61
    pub use super::sealed::*;
62
}
63
64
/// A secure random number generator.
65
pub trait SecureRandom: sealed::SecureRandom {
66
    /// Fills `dest` with random bytes.
67
    ///
68
    /// # Errors
69
    /// `error::Unspecified` if unable to fill `dest`.
70
    fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified>;
71
72
    /// Fills `dest` with random bytes.
73
    ///
74
    /// This method is only available when the `dev-tests-only` feature is enabled.
75
    ///
76
    /// # Errors
77
    /// `error::Unspecified` if unable to fill `dest`.
78
    #[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
83
impl<T> SecureRandom for T
84
where
85
    T: sealed::SecureRandom,
86
{
87
    #[inline]
88
0
    fn fill(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
89
0
        self.fill_impl(dest)
90
0
    }
Unexecuted instantiation: <aws_lc_rs::rand::SystemRandom as aws_lc_rs::rand::SecureRandom>::fill
Unexecuted instantiation: <_ as aws_lc_rs::rand::SecureRandom>::fill
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
99
/// A random value constructed from a `SecureRandom` that hasn't been exposed
100
/// through any safe Rust interface.
101
///
102
/// Intentionally does not implement any traits other than `Sized`.
103
pub struct Random<T: RandomlyConstructable>(T);
104
105
impl<T: RandomlyConstructable> Random<T> {
106
    /// Expose the random value.
107
    #[inline]
108
0
    pub fn expose(self) -> T {
109
0
        self.0
110
0
    }
111
}
112
113
/// Generate the new random value using `rng`.
114
///
115
/// # Errors
116
/// `error::Unspecified` if unable to fill buffer.
117
#[inline]
118
0
pub fn generate<T: RandomlyConstructable>(
119
0
    rng: &dyn SecureRandom,
120
0
) -> Result<Random<T>, Unspecified> {
121
0
    let mut r = T::zero();
122
0
    rng.fill(r.as_mut_bytes())?;
123
0
    Ok(Random(r))
124
0
}
125
126
pub(crate) mod sealed {
127
    use crate::error;
128
129
    /// A sealed trait for secure random number generation.
130
    pub trait SecureRandom: core::fmt::Debug {
131
        /// Fills `dest` with random bytes.
132
        ///
133
        /// # Errors
134
        /// Returns `error::Unspecified` if unable to fill `dest`.
135
        fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
136
    }
137
138
    /// A sealed trait for types that can be randomly constructed.
139
    pub trait RandomlyConstructable: Sized {
140
        /// Returns a zeroed instance of the type.
141
        fn zero() -> Self;
142
        /// Returns a mutable byte slice of the value.
143
        fn as_mut_bytes(&mut self) -> &mut [u8];
144
    }
145
146
    impl<const T: usize> RandomlyConstructable for [u8; T] {
147
        #[inline]
148
0
        fn zero() -> Self {
149
0
            [0; T]
150
0
        }
151
152
        #[inline]
153
0
        fn as_mut_bytes(&mut self) -> &mut [u8] {
154
0
            &mut self[..]
155
0
        }
156
    }
157
}
158
159
/// A type that can be returned by `aws_lc_rs::rand::generate()`.
160
pub trait RandomlyConstructable: sealed::RandomlyConstructable {}
161
162
impl<T> RandomlyConstructable for T where T: sealed::RandomlyConstructable {}
163
164
/// A secure random number generator where the random values come from the
165
/// underlying *AWS-LC* libcrypto.
166
///
167
/// A single `SystemRandom` may be shared across multiple threads safely.
168
//
169
// # FIPS
170
// Use this implementation for retrieving random bytes.
171
#[derive(Clone, Debug)]
172
pub struct SystemRandom(());
173
174
const SYSTEM_RANDOM: SystemRandom = SystemRandom(());
175
176
impl SystemRandom {
177
    /// Constructs a new `SystemRandom`.
178
    #[inline]
179
    #[must_use]
180
0
    pub fn new() -> Self {
181
0
        Self::default()
182
0
    }
Unexecuted instantiation: <aws_lc_rs::rand::SystemRandom>::new
Unexecuted instantiation: <aws_lc_rs::rand::SystemRandom>::new
183
}
184
185
impl Default for SystemRandom {
186
0
    fn default() -> Self {
187
0
        SYSTEM_RANDOM
188
0
    }
189
}
190
191
impl sealed::SecureRandom for SystemRandom {
192
    #[inline]
193
0
    fn fill_impl(&self, dest: &mut [u8]) -> Result<(), Unspecified> {
194
0
        fill(dest)
195
0
    }
Unexecuted instantiation: <aws_lc_rs::rand::SystemRandom as aws_lc_rs::rand::sealed::SecureRandom>::fill_impl
Unexecuted instantiation: <aws_lc_rs::rand::SystemRandom as aws_lc_rs::rand::sealed::SecureRandom>::fill_impl
196
}
197
198
/// Fills `dest` with random bytes.
199
///
200
// # FIPS
201
// Use this for retrieving random bytes or [`SystemRandom`].
202
//
203
/// # Errors
204
/// `error::Unspecified` if unable to fill `dest`.
205
0
pub fn fill(dest: &mut [u8]) -> Result<(), Unspecified> {
206
0
    if 1 != indicator_check!(unsafe { RAND_bytes(dest.as_mut_ptr(), dest.len()) }) {
207
0
        return Err(Unspecified);
208
0
    }
209
0
    Ok(())
210
0
}
211
212
#[cfg(test)]
213
mod 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
        // Collect enough random values so that the assertions below should never fail again
222
        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
        // Collect enough random values so that the assertions below should never fail again
235
        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
        // Collect enough random values so that the assertions below should never fail again
249
        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
}