ring/
rand.rs

1// Copyright 2015-2016 Brian Smith.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15//! Cryptographic pseudo-random number generation.
16//!
17//! *ring* functions that generate random bytes take a `&dyn SecureRandom`
18//! parameter to make it clear which functions are non-deterministic.
19
20use crate::error;
21
22/// A secure random number generator.
23pub trait SecureRandom: sealed::SecureRandom {
24    /// Fills `dest` with random bytes.
25    fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
26}
27
28impl<T> SecureRandom for T
29where
30    T: sealed::SecureRandom,
31{
32    #[inline(always)]
33    fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
34        self.fill_impl(dest)
35    }
36}
37
38/// A random value constructed from a `SecureRandom` that hasn't been exposed
39/// through any safe Rust interface.
40///
41/// Intentionally does not implement any traits other than `Sized`.
42pub struct Random<T: RandomlyConstructable>(T);
43
44impl<T: RandomlyConstructable> Random<T> {
45    /// Expose the random value.
46    #[inline]
47    pub fn expose(self) -> T {
48        self.0
49    }
50}
51
52/// Generate the new random value using `rng`.
53#[inline]
54pub fn generate<T: RandomlyConstructable>(
55    rng: &dyn SecureRandom,
56) -> Result<Random<T>, error::Unspecified>
57where
58    T: RandomlyConstructable,
59{
60    let mut r = T::zero();
61    rng.fill(r.as_mut_bytes())?;
62    Ok(Random(r))
63}
64
65pub(crate) mod sealed {
66    use crate::error;
67
68    pub trait SecureRandom: core::fmt::Debug {
69        /// Fills `dest` with random bytes.
70        fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
71    }
72
73    pub trait RandomlyConstructable: Sized {
74        fn zero() -> Self; // `Default::default()`
75        fn as_mut_bytes(&mut self) -> &mut [u8]; // `AsMut<[u8]>::as_mut`
76    }
77
78    impl<const N: usize> RandomlyConstructable for [u8; N] {
79        #[inline]
80        fn zero() -> Self {
81            [0; N]
82        }
83
84        #[inline]
85        fn as_mut_bytes(&mut self) -> &mut [u8] {
86            &mut self[..]
87        }
88    }
89}
90
91/// A type that can be returned by `ring::rand::generate()`.
92pub trait RandomlyConstructable: self::sealed::RandomlyConstructable {}
93impl<T> RandomlyConstructable for T where T: self::sealed::RandomlyConstructable {}
94
95/// A secure random number generator where the random values come directly
96/// from the operating system.
97///
98/// "Directly from the operating system" here presently means "whatever the
99/// `getrandom` crate does" but that may change in the future. That roughly
100/// means calling libc's `getrandom` function or whatever is analogous to that;
101/// see the `getrandom` crate's documentation for more info.
102///
103/// A single `SystemRandom` may be shared across multiple threads safely.
104///
105/// `new()` is guaranteed to always succeed and to have low latency; it won't
106/// try to open or read from a file or do similar things. The first call to
107/// `fill()` may block a substantial amount of time since any and all
108/// initialization is deferred to it. Therefore, it may be a good idea to call
109/// `fill()` once at a non-latency-sensitive time to minimize latency for
110/// future calls.
111#[derive(Clone, Debug)]
112pub struct SystemRandom(());
113
114impl SystemRandom {
115    /// Constructs a new `SystemRandom`.
116    #[inline(always)]
117    pub fn new() -> Self {
118        Self(())
119    }
120}
121
122impl crate::sealed::Sealed for SystemRandom {}
123
124// Use the `getrandom` crate whenever it is using the environment's (operating
125// system's) CSPRNG. Avoid using it on targets where it uses the `rdrand`
126// implementation.
127#[cfg(any(
128    all(feature = "less-safe-getrandom-custom-or-rdrand", target_os = "none"),
129    target_os = "aix",
130    target_os = "android",
131    target_os = "dragonfly",
132    target_os = "freebsd",
133    target_os = "fuchsia",
134    target_os = "haiku",
135    target_os = "hermit",
136    target_os = "illumos",
137    target_os = "ios",
138    target_os = "linux",
139    target_os = "macos",
140    target_os = "netbsd",
141    target_os = "openbsd",
142    target_os = "redox",
143    target_os = "solaris",
144    target_os = "tvos",
145    target_os = "vita",
146    target_os = "windows",
147    all(
148        target_arch = "wasm32",
149        any(
150            target_os = "wasi",
151            all(target_os = "unknown", feature = "wasm32_unknown_unknown_js")
152        )
153    ),
154))]
155impl sealed::SecureRandom for SystemRandom {
156    #[inline(always)]
157    fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
158        getrandom::getrandom(dest).map_err(|_| error::Unspecified)
159    }
160}