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 
20 use crate::error;
21 
22 /// A secure random number generator.
23 pub trait SecureRandom: sealed::SecureRandom {
24     /// Fills `dest` with random bytes.
fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>25     fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
26 }
27 
28 impl<T> SecureRandom for T
29 where
30     T: sealed::SecureRandom,
31 {
32     #[inline(always)]
fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>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`.
42 pub struct Random<T: RandomlyConstructable>(T);
43 
44 impl<T: RandomlyConstructable> Random<T> {
45     /// Expose the random value.
46     #[inline]
expose(self) -> T47     pub fn expose(self) -> T {
48         self.0
49     }
50 }
51 
52 /// Generate the new random value using `rng`.
53 #[inline]
generate<T: RandomlyConstructable>( rng: &dyn SecureRandom, ) -> Result<Random<T>, error::Unspecified> where T: RandomlyConstructable,54 pub fn generate<T: RandomlyConstructable>(
55     rng: &dyn SecureRandom,
56 ) -> Result<Random<T>, error::Unspecified>
57 where
58     T: RandomlyConstructable,
59 {
60     let mut r = T::zero();
61     rng.fill(r.as_mut_bytes())?;
62     Ok(Random(r))
63 }
64 
65 pub(crate) mod sealed {
66     use crate::error;
67 
68     pub trait SecureRandom: core::fmt::Debug {
69         /// Fills `dest` with random bytes.
fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>70         fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
71     }
72 
73     pub trait RandomlyConstructable: Sized {
zero() -> Self74         fn zero() -> Self; // `Default::default()`
as_mut_bytes(&mut self) -> &mut [u8]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]
zero() -> Self80         fn zero() -> Self {
81             [0; N]
82         }
83 
84         #[inline]
as_mut_bytes(&mut self) -> &mut [u8]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()`.
92 pub trait RandomlyConstructable: self::sealed::RandomlyConstructable {}
93 impl<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)]
112 pub struct SystemRandom(());
113 
114 impl SystemRandom {
115     /// Constructs a new `SystemRandom`.
116     #[inline(always)]
new() -> Self117     pub fn new() -> Self {
118         Self(())
119     }
120 }
121 
122 impl 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     target_os = "android",
129     target_os = "dragonfly",
130     target_os = "freebsd",
131     target_os = "haiku",
132     target_os = "illumos",
133     target_os = "ios",
134     target_os = "tvos",
135     target_os = "linux",
136     target_os = "macos",
137     target_os = "netbsd",
138     target_os = "openbsd",
139     target_os = "redox",
140     target_os = "solaris",
141     target_os = "windows",
142     target_os = "vita",
143     all(
144         feature = "wasm32_unknown_unknown_js",
145         target_arch = "wasm32",
146         target_os = "unknown",
147     ),
148 ))]
149 impl sealed::SecureRandom for SystemRandom {
150     #[inline(always)]
fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>151     fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
152         getrandom::getrandom(dest).map_err(|_| error::Unspecified)
153     }
154 }
155