155 lines
4.8 KiB
Rust
155 lines
4.8 KiB
Rust
// 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)
|
|
}
|
|
}
|