2016-02-04 14:20:33 -10:00
|
|
|
// Copyright 2015-2016 Brian Smith.
|
2015-08-26 16:46:40 -07:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2016-07-02 09:45:53 +01:00
|
|
|
//! Cryptographic pseudo-random number generation.
|
2016-05-19 08:59:31 -10:00
|
|
|
//!
|
2022-10-25 12:19:50 -07:00
|
|
|
//! *ring* functions that generate random bytes take a `&dyn SecureRandom`
|
|
|
|
//! parameter to make it clear which functions are non-deterministic.
|
2015-08-26 16:46:40 -07:00
|
|
|
|
2018-11-09 13:56:51 -10:00
|
|
|
use crate::error;
|
2016-08-21 11:32:52 -10:00
|
|
|
|
2016-04-25 06:39:15 -10:00
|
|
|
/// A secure random number generator.
|
2019-06-17 15:15:56 -10:00
|
|
|
pub trait SecureRandom: sealed::SecureRandom {
|
2016-04-25 06:39:15 -10:00
|
|
|
/// Fills `dest` with random bytes.
|
2016-08-10 14:23:16 -10:00
|
|
|
fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
|
2016-04-25 06:39:15 -10:00
|
|
|
}
|
|
|
|
|
2019-06-17 15:15:56 -10:00
|
|
|
impl<T> SecureRandom for T
|
|
|
|
where
|
|
|
|
T: sealed::SecureRandom,
|
|
|
|
{
|
|
|
|
#[inline(always)]
|
|
|
|
fn fill(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
|
|
|
|
self.fill_impl(dest)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-30 22:33:24 -10:00
|
|
|
/// 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>(
|
2019-07-03 10:42:16 -10:00
|
|
|
rng: &dyn SecureRandom,
|
2019-06-30 22:33:24 -10:00
|
|
|
) -> Result<Random<T>, error::Unspecified>
|
|
|
|
where
|
|
|
|
T: RandomlyConstructable,
|
|
|
|
{
|
|
|
|
let mut r = T::zero();
|
|
|
|
rng.fill(r.as_mut_bytes())?;
|
|
|
|
Ok(Random(r))
|
|
|
|
}
|
|
|
|
|
2019-06-17 15:15:56 -10:00
|
|
|
pub(crate) mod sealed {
|
|
|
|
use crate::error;
|
|
|
|
|
2019-07-16 11:03:10 -10:00
|
|
|
pub trait SecureRandom: core::fmt::Debug {
|
2019-06-17 15:15:56 -10:00
|
|
|
/// Fills `dest` with random bytes.
|
|
|
|
fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>;
|
|
|
|
}
|
|
|
|
|
2019-06-30 22:33:24 -10:00
|
|
|
pub trait RandomlyConstructable: Sized {
|
|
|
|
fn zero() -> Self; // `Default::default()`
|
|
|
|
fn as_mut_bytes(&mut self) -> &mut [u8]; // `AsMut<[u8]>::as_mut`
|
|
|
|
}
|
|
|
|
|
2022-10-20 13:01:04 -07:00
|
|
|
impl<const N: usize> RandomlyConstructable for [u8; N] {
|
|
|
|
#[inline]
|
|
|
|
fn zero() -> Self {
|
|
|
|
[0; N]
|
|
|
|
}
|
2019-06-30 22:33:24 -10:00
|
|
|
|
2022-10-20 13:01:04 -07:00
|
|
|
#[inline]
|
|
|
|
fn as_mut_bytes(&mut self) -> &mut [u8] {
|
|
|
|
&mut self[..]
|
2019-06-30 22:33:24 -10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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 {}
|
|
|
|
|
2016-04-25 06:39:15 -10:00
|
|
|
/// A secure random number generator where the random values come directly
|
|
|
|
/// from the operating system.
|
|
|
|
///
|
2022-10-25 12:10:29 -07:00
|
|
|
/// "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.
|
|
|
|
///
|
2016-05-19 13:39:03 -10:00
|
|
|
/// A single `SystemRandom` may be shared across multiple threads safely.
|
|
|
|
///
|
2016-05-17 14:46:40 -10:00
|
|
|
/// `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.
|
2019-07-16 11:03:10 -10:00
|
|
|
#[derive(Clone, Debug)]
|
2019-07-11 19:36:52 -10:00
|
|
|
pub struct SystemRandom(());
|
2016-04-25 06:39:15 -10:00
|
|
|
|
|
|
|
impl SystemRandom {
|
|
|
|
/// Constructs a new `SystemRandom`.
|
|
|
|
#[inline(always)]
|
2019-04-10 09:33:38 -10:00
|
|
|
pub fn new() -> Self {
|
2019-07-11 19:36:52 -10:00
|
|
|
Self(())
|
2019-04-10 09:33:38 -10:00
|
|
|
}
|
2016-04-25 06:39:15 -10:00
|
|
|
}
|
|
|
|
|
2019-06-30 22:33:24 -10:00
|
|
|
impl crate::sealed::Sealed for SystemRandom {}
|
2018-06-04 13:36:21 -10:00
|
|
|
|
2022-10-25 12:10:29 -07:00
|
|
|
// 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.
|
2018-11-15 15:40:24 -10:00
|
|
|
#[cfg(any(
|
2022-10-25 12:10:29 -07:00
|
|
|
target_os = "android",
|
2020-11-30 18:31:28 +00:00
|
|
|
target_os = "dragonfly",
|
2019-07-15 11:24:27 -10:00
|
|
|
target_os = "freebsd",
|
2023-05-09 20:55:00 +12:00
|
|
|
target_os = "haiku",
|
2020-11-24 00:29:10 -08:00
|
|
|
target_os = "illumos",
|
2022-10-25 12:10:29 -07:00
|
|
|
target_os = "ios",
|
2023-07-10 16:50:38 +01:00
|
|
|
target_os = "tvos",
|
2022-10-25 12:10:29 -07:00
|
|
|
target_os = "linux",
|
|
|
|
target_os = "macos",
|
2019-07-15 11:24:27 -10:00
|
|
|
target_os = "netbsd",
|
|
|
|
target_os = "openbsd",
|
2019-04-21 20:27:00 -06:00
|
|
|
target_os = "redox",
|
2020-09-22 22:47:01 +02:00
|
|
|
target_os = "solaris",
|
2022-10-25 12:10:29 -07:00
|
|
|
target_os = "windows",
|
2023-09-06 12:17:36 +03:00
|
|
|
target_os = "vita",
|
2019-07-15 11:24:27 -10:00
|
|
|
all(
|
2022-10-25 12:10:29 -07:00
|
|
|
feature = "wasm32_unknown_unknown_js",
|
|
|
|
target_arch = "wasm32",
|
|
|
|
target_os = "unknown",
|
2019-07-15 11:24:27 -10:00
|
|
|
),
|
|
|
|
))]
|
2022-10-25 12:10:29 -07:00
|
|
|
impl sealed::SecureRandom for SystemRandom {
|
|
|
|
#[inline(always)]
|
|
|
|
fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
|
|
|
|
getrandom::getrandom(dest).map_err(|_| error::Unspecified)
|
2019-01-16 21:22:35 -08:00
|
|
|
}
|
|
|
|
}
|