| // Copyright 2015-2016 Brian Smith. |
| // |
| // Permission to use, copy, modify, and/or distribute this software for any |
| // purpose with or without fee is hereby granted, provided that the above |
| // copyright notice and this permission notice appear in all copies. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
| // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
| // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
| // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| //! Cryptographic pseudo-random number generation. |
| //! |
| //! *ring* functions that generate random bytes take a `&dyn SecureRandom` |
| //! parameter to make it clear which functions are non-deterministic. |
| |
| use crate::error; |
| |
| /// A secure random number generator. |
| pub trait SecureRandom: sealed::SecureRandom { |
| /// Fills `dest` with random bytes. |
| fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>; |
| } |
| |
| impl<T> SecureRandom for T |
| where |
| T: sealed::SecureRandom, |
| { |
| #[inline(always)] |
| fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> { |
| self.fill_impl(dest) |
| } |
| } |
| |
| /// A random value constructed from a `SecureRandom` that hasn't been exposed |
| /// through any safe Rust interface. |
| /// |
| /// Intentionally does not implement any traits other than `Sized`. |
| pub struct Random<T: RandomlyConstructable>(T); |
| |
| impl<T: RandomlyConstructable> Random<T> { |
| /// Expose the random value. |
| #[inline] |
| pub fn expose(self) -> T { |
| self.0 |
| } |
| } |
| |
| /// Generate the new random value using `rng`. |
| #[inline] |
| pub fn generate<T: RandomlyConstructable>( |
| rng: &dyn SecureRandom, |
| ) -> Result<Random<T>, error::Unspecified> |
| where |
| T: RandomlyConstructable, |
| { |
| let mut r = T::zero(); |
| rng.fill(r.as_mut_bytes())?; |
| Ok(Random(r)) |
| } |
| |
| pub(crate) mod sealed { |
| use crate::error; |
| |
| pub trait SecureRandom: core::fmt::Debug { |
| /// Fills `dest` with random bytes. |
| fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>; |
| } |
| |
| pub trait RandomlyConstructable: Sized { |
| fn zero() -> Self; // `Default::default()` |
| fn as_mut_bytes(&mut self) -> &mut [u8]; // `AsMut<[u8]>::as_mut` |
| } |
| |
| impl<const N: usize> RandomlyConstructable for [u8; N] { |
| #[inline] |
| fn zero() -> Self { |
| [0; N] |
| } |
| |
| #[inline] |
| fn as_mut_bytes(&mut self) -> &mut [u8] { |
| &mut self[..] |
| } |
| } |
| } |
| |
| /// A type that can be returned by `ring::rand::generate()`. |
| pub trait RandomlyConstructable: self::sealed::RandomlyConstructable {} |
| impl<T> RandomlyConstructable for T where T: self::sealed::RandomlyConstructable {} |
| |
| /// A secure random number generator where the random values come directly |
| /// from the operating system. |
| /// |
| /// "Directly from the operating system" here presently means "whatever the |
| /// `getrandom` crate does" but that may change in the future. That roughly |
| /// means calling libc's `getrandom` function or whatever is analogous to that; |
| /// see the `getrandom` crate's documentation for more info. |
| /// |
| /// A single `SystemRandom` may be shared across multiple threads safely. |
| /// |
| /// `new()` is guaranteed to always succeed and to have low latency; it won't |
| /// try to open or read from a file or do similar things. The first call to |
| /// `fill()` may block a substantial amount of time since any and all |
| /// initialization is deferred to it. Therefore, it may be a good idea to call |
| /// `fill()` once at a non-latency-sensitive time to minimize latency for |
| /// future calls. |
| #[derive(Clone, Debug)] |
| pub struct SystemRandom(()); |
| |
| impl SystemRandom { |
| /// Constructs a new `SystemRandom`. |
| #[inline(always)] |
| pub fn new() -> Self { |
| Self(()) |
| } |
| } |
| |
| impl crate::sealed::Sealed for SystemRandom {} |
| |
| // Use the `getrandom` crate whenever it is using the environment's (operating |
| // system's) CSPRNG. Avoid using it on targets where it uses the `rdrand` |
| // implementation. |
| #[cfg(any( |
| target_os = "android", |
| target_os = "dragonfly", |
| target_os = "freebsd", |
| target_os = "haiku", |
| target_os = "illumos", |
| target_os = "ios", |
| target_os = "tvos", |
| target_os = "linux", |
| target_os = "macos", |
| target_os = "netbsd", |
| target_os = "openbsd", |
| target_os = "redox", |
| target_os = "solaris", |
| target_os = "windows", |
| target_os = "vita", |
| all( |
| feature = "wasm32_unknown_unknown_js", |
| target_arch = "wasm32", |
| target_os = "unknown", |
| ), |
| ))] |
| impl sealed::SecureRandom for SystemRandom { |
| #[inline(always)] |
| fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> { |
| getrandom::getrandom(dest).map_err(|_| error::Unspecified) |
| } |
| } |