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 = T::zero();
61 rng.fill(dest: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 = "haiku",
134 target_os = "hermit",
135 target_os = "illumos",
136 target_os = "ios",
137 target_os = "linux",
138 target_os = "macos",
139 target_os = "netbsd",
140 target_os = "openbsd",
141 target_os = "redox",
142 target_os = "solaris",
143 target_os = "tvos",
144 target_os = "vita",
145 target_os = "windows",
146 all(
147 target_arch = "wasm32",
148 any(
149 target_os = "wasi",
150 all(target_os = "unknown", feature = "wasm32_unknown_unknown_js")
151 )
152 ),
153))]
154impl sealed::SecureRandom for SystemRandom {
155 #[inline(always)]
156 fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
157 getrandom::getrandom(dest).map_err(|_| error::Unspecified)
158 }
159}
160