aboutsummaryrefslogtreecommitdiff
path: root/rand/src/rngs
diff options
context:
space:
mode:
Diffstat (limited to 'rand/src/rngs')
-rw-r--r--rand/src/rngs/adapter/mod.rs15
-rw-r--r--rand/src/rngs/adapter/read.rs137
-rw-r--r--rand/src/rngs/adapter/reseeding.rs370
-rw-r--r--rand/src/rngs/entropy.rs249
-rw-r--r--rand/src/rngs/jitter.rs885
-rw-r--r--rand/src/rngs/mock.rs59
-rw-r--r--rand/src/rngs/mod.rs182
-rw-r--r--rand/src/rngs/small.rs105
-rw-r--r--rand/src/rngs/std.rs81
-rw-r--r--rand/src/rngs/thread.rs141
10 files changed, 0 insertions, 2224 deletions
diff --git a/rand/src/rngs/adapter/mod.rs b/rand/src/rngs/adapter/mod.rs
deleted file mode 100644
index 60b832e..0000000
--- a/rand/src/rngs/adapter/mod.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Wrappers / adapters forming RNGs
-
-#[cfg(feature="std")] #[doc(hidden)] pub mod read;
-mod reseeding;
-
-#[cfg(feature="std")] pub use self::read::ReadRng;
-pub use self::reseeding::ReseedingRng;
diff --git a/rand/src/rngs/adapter/read.rs b/rand/src/rngs/adapter/read.rs
deleted file mode 100644
index 30b6de6..0000000
--- a/rand/src/rngs/adapter/read.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-// Copyright 2013 The Rust Project Developers.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A wrapper around any Read to treat it as an RNG.
-
-use std::io::Read;
-
-use rand_core::{RngCore, Error, ErrorKind, impls};
-
-
-/// An RNG that reads random bytes straight from any type supporting
-/// `std::io::Read`, for example files.
-///
-/// This will work best with an infinite reader, but that is not required.
-///
-/// This can be used with `/dev/urandom` on Unix but it is recommended to use
-/// [`OsRng`] instead.
-///
-/// # Panics
-///
-/// `ReadRng` uses `std::io::read_exact`, which retries on interrupts. All other
-/// errors from the underlying reader, including when it does not have enough
-/// data, will only be reported through [`try_fill_bytes`]. The other
-/// [`RngCore`] methods will panic in case of an error.
-///
-/// # Example
-///
-/// ```
-/// use rand::Rng;
-/// use rand::rngs::adapter::ReadRng;
-///
-/// let data = vec![1, 2, 3, 4, 5, 6, 7, 8];
-/// let mut rng = ReadRng::new(&data[..]);
-/// println!("{:x}", rng.gen::<u32>());
-/// ```
-///
-/// [`OsRng`]: ../struct.OsRng.html
-/// [`RngCore`]: ../../trait.RngCore.html
-/// [`try_fill_bytes`]: ../../trait.RngCore.html#method.tymethod.try_fill_bytes
-#[derive(Debug)]
-pub struct ReadRng<R> {
- reader: R
-}
-
-impl<R: Read> ReadRng<R> {
- /// Create a new `ReadRng` from a `Read`.
- pub fn new(r: R) -> ReadRng<R> {
- ReadRng {
- reader: r
- }
- }
-}
-
-impl<R: Read> RngCore for ReadRng<R> {
- fn next_u32(&mut self) -> u32 {
- impls::next_u32_via_fill(self)
- }
-
- fn next_u64(&mut self) -> u64 {
- impls::next_u64_via_fill(self)
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- self.try_fill_bytes(dest).unwrap_or_else(|err|
- panic!("reading random bytes from Read implementation failed; error: {}", err));
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- if dest.len() == 0 { return Ok(()); }
- // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`.
- self.reader.read_exact(dest).map_err(|err| {
- match err.kind() {
- ::std::io::ErrorKind::UnexpectedEof => Error::with_cause(
- ErrorKind::Unavailable,
- "not enough bytes available, reached end of source", err),
- _ => Error::with_cause(ErrorKind::Unavailable,
- "error reading from Read source", err)
- }
- })
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::ReadRng;
- use {RngCore, ErrorKind};
-
- #[test]
- fn test_reader_rng_u64() {
- // transmute from the target to avoid endianness concerns.
- let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
- 0 , 0, 0, 0, 0, 0, 0, 2,
- 0, 0, 0, 0, 0, 0, 0, 3];
- let mut rng = ReadRng::new(&v[..]);
-
- assert_eq!(rng.next_u64(), 1_u64.to_be());
- assert_eq!(rng.next_u64(), 2_u64.to_be());
- assert_eq!(rng.next_u64(), 3_u64.to_be());
- }
-
- #[test]
- fn test_reader_rng_u32() {
- let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
- let mut rng = ReadRng::new(&v[..]);
-
- assert_eq!(rng.next_u32(), 1_u32.to_be());
- assert_eq!(rng.next_u32(), 2_u32.to_be());
- assert_eq!(rng.next_u32(), 3_u32.to_be());
- }
-
- #[test]
- fn test_reader_rng_fill_bytes() {
- let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let mut w = [0u8; 8];
-
- let mut rng = ReadRng::new(&v[..]);
- rng.fill_bytes(&mut w);
-
- assert!(v == w);
- }
-
- #[test]
- fn test_reader_rng_insufficient_bytes() {
- let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let mut w = [0u8; 9];
-
- let mut rng = ReadRng::new(&v[..]);
-
- assert!(rng.try_fill_bytes(&mut w).err().unwrap().kind == ErrorKind::Unavailable);
- }
-}
diff --git a/rand/src/rngs/adapter/reseeding.rs b/rand/src/rngs/adapter/reseeding.rs
deleted file mode 100644
index 016afab..0000000
--- a/rand/src/rngs/adapter/reseeding.rs
+++ /dev/null
@@ -1,370 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-// Copyright 2013 The Rust Project Developers.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A wrapper around another PRNG that reseeds it after it
-//! generates a certain number of random bytes.
-
-use core::mem::size_of;
-
-use rand_core::{RngCore, CryptoRng, SeedableRng, Error, ErrorKind};
-use rand_core::block::{BlockRngCore, BlockRng};
-
-/// A wrapper around any PRNG that implements [`BlockRngCore`], that adds the
-/// ability to reseed it.
-///
-/// `ReseedingRng` reseeds the underlying PRNG in the following cases:
-///
-/// - On a manual call to [`reseed()`].
-/// - After `clone()`, the clone will be reseeded on first use.
-/// - After a process is forked, the RNG in the child process is reseeded within
-/// the next few generated values, depending on the block size of the
-/// underlying PRNG. For [`ChaChaCore`] and [`Hc128Core`] this is a maximum of
-/// 15 `u32` values before reseeding.
-/// - After the PRNG has generated a configurable number of random bytes.
-///
-/// # When should reseeding after a fixed number of generated bytes be used?
-///
-/// Reseeding after a fixed number of generated bytes is never strictly
-/// *necessary*. Cryptographic PRNGs don't have a limited number of bytes they
-/// can output, or at least not a limit reachable in any practical way. There is
-/// no such thing as 'running out of entropy'.
-///
-/// Occasionally reseeding can be seen as some form of 'security in depth'. Even
-/// if in the future a cryptographic weakness is found in the CSPRNG being used,
-/// or a flaw in the implementation, occasionally reseeding should make
-/// exploiting it much more difficult or even impossible.
-///
-/// Use [`ReseedingRng::new`] with a `threshold` of `0` to disable reseeding
-/// after a fixed number of generated bytes.
-///
-/// # Error handling
-///
-/// Although unlikely, reseeding the wrapped PRNG can fail. `ReseedingRng` will
-/// never panic but try to handle the error intelligently through some
-/// combination of retrying and delaying reseeding until later.
-/// If handling the source error fails `ReseedingRng` will continue generating
-/// data from the wrapped PRNG without reseeding.
-///
-/// Manually calling [`reseed()`] will not have this retry or delay logic, but
-/// reports the error.
-///
-/// # Example
-///
-/// ```
-/// # extern crate rand;
-/// # extern crate rand_chacha;
-/// # fn main() {
-/// use rand::prelude::*;
-/// use rand_chacha::ChaChaCore; // Internal part of ChaChaRng that
-/// // implements BlockRngCore
-/// use rand::rngs::OsRng;
-/// use rand::rngs::adapter::ReseedingRng;
-///
-/// let prng = ChaChaCore::from_entropy();
-// FIXME: it is better to use EntropyRng as reseeder, but that doesn't implement
-// clone yet.
-/// let reseeder = OsRng::new().unwrap();
-/// let mut reseeding_rng = ReseedingRng::new(prng, 0, reseeder);
-///
-/// println!("{}", reseeding_rng.gen::<u64>());
-///
-/// let mut cloned_rng = reseeding_rng.clone();
-/// assert!(reseeding_rng.gen::<u64>() != cloned_rng.gen::<u64>());
-/// # }
-/// ```
-///
-/// [`ChaChaCore`]: ../../../rand_chacha/struct.ChaChaCore.html
-/// [`Hc128Core`]: ../../../rand_hc/struct.Hc128Core.html
-/// [`BlockRngCore`]: ../../../rand_core/block/trait.BlockRngCore.html
-/// [`ReseedingRng::new`]: struct.ReseedingRng.html#method.new
-/// [`reseed()`]: struct.ReseedingRng.html#method.reseed
-#[derive(Debug)]
-pub struct ReseedingRng<R, Rsdr>(BlockRng<ReseedingCore<R, Rsdr>>)
-where R: BlockRngCore + SeedableRng,
- Rsdr: RngCore;
-
-impl<R, Rsdr> ReseedingRng<R, Rsdr>
-where R: BlockRngCore + SeedableRng,
- Rsdr: RngCore
-{
- /// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG
- /// to use as reseeder.
- ///
- /// `threshold` sets the number of generated bytes after which to reseed the
- /// PRNG. Set it to zero to never reseed based on the number of generated
- /// values.
- pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
- ReseedingRng(BlockRng::new(ReseedingCore::new(rng, threshold, reseeder)))
- }
-
- /// Reseed the internal PRNG.
- pub fn reseed(&mut self) -> Result<(), Error> {
- self.0.core.reseed()
- }
-}
-
-// TODO: this should be implemented for any type where the inner type
-// implements RngCore, but we can't specify that because ReseedingCore is private
-impl<R, Rsdr: RngCore> RngCore for ReseedingRng<R, Rsdr>
-where R: BlockRngCore<Item = u32> + SeedableRng,
- <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
-{
- #[inline(always)]
- fn next_u32(&mut self) -> u32 {
- self.0.next_u32()
- }
-
- #[inline(always)]
- fn next_u64(&mut self) -> u64 {
- self.0.next_u64()
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- self.0.fill_bytes(dest)
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- self.0.try_fill_bytes(dest)
- }
-}
-
-impl<R, Rsdr> Clone for ReseedingRng<R, Rsdr>
-where R: BlockRngCore + SeedableRng + Clone,
- Rsdr: RngCore + Clone
-{
- fn clone(&self) -> ReseedingRng<R, Rsdr> {
- // Recreating `BlockRng` seems easier than cloning it and resetting
- // the index.
- ReseedingRng(BlockRng::new(self.0.core.clone()))
- }
-}
-
-impl<R, Rsdr> CryptoRng for ReseedingRng<R, Rsdr>
-where R: BlockRngCore + SeedableRng + CryptoRng,
- Rsdr: RngCore + CryptoRng {}
-
-#[derive(Debug)]
-struct ReseedingCore<R, Rsdr> {
- inner: R,
- reseeder: Rsdr,
- threshold: i64,
- bytes_until_reseed: i64,
- fork_counter: usize,
-}
-
-impl<R, Rsdr> BlockRngCore for ReseedingCore<R, Rsdr>
-where R: BlockRngCore + SeedableRng,
- Rsdr: RngCore
-{
- type Item = <R as BlockRngCore>::Item;
- type Results = <R as BlockRngCore>::Results;
-
- fn generate(&mut self, results: &mut Self::Results) {
- let global_fork_counter = fork::get_fork_counter();
- if self.bytes_until_reseed <= 0 ||
- self.is_forked(global_fork_counter) {
- // We get better performance by not calling only `reseed` here
- // and continuing with the rest of the function, but by directly
- // returning from a non-inlined function.
- return self.reseed_and_generate(results, global_fork_counter);
- }
- let num_bytes = results.as_ref().len() * size_of::<Self::Item>();
- self.bytes_until_reseed -= num_bytes as i64;
- self.inner.generate(results);
- }
-}
-
-impl<R, Rsdr> ReseedingCore<R, Rsdr>
-where R: BlockRngCore + SeedableRng,
- Rsdr: RngCore
-{
- /// Create a new `ReseedingCore`.
- fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
- use ::core::i64::MAX;
- fork::register_fork_handler();
-
- // Because generating more values than `i64::MAX` takes centuries on
- // current hardware, we just clamp to that value.
- // Also we set a threshold of 0, which indicates no limit, to that
- // value.
- let threshold =
- if threshold == 0 { MAX }
- else if threshold <= MAX as u64 { threshold as i64 }
- else { MAX };
-
- ReseedingCore {
- inner: rng,
- reseeder,
- threshold: threshold as i64,
- bytes_until_reseed: threshold as i64,
- fork_counter: 0,
- }
- }
-
- /// Reseed the internal PRNG.
- fn reseed(&mut self) -> Result<(), Error> {
- R::from_rng(&mut self.reseeder).map(|result| {
- self.bytes_until_reseed = self.threshold;
- self.inner = result
- })
- }
-
- fn is_forked(&self, global_fork_counter: usize) -> bool {
- // In theory, on 32-bit platforms, it is possible for
- // `global_fork_counter` to wrap around after ~4e9 forks.
- //
- // This check will detect a fork in the normal case where
- // `fork_counter < global_fork_counter`, and also when the difference
- // between both is greater than `isize::MAX` (wrapped around).
- //
- // It will still fail to detect a fork if there have been more than
- // `isize::MAX` forks, without any reseed in between. Seems unlikely
- // enough.
- (self.fork_counter.wrapping_sub(global_fork_counter) as isize) < 0
- }
-
- #[inline(never)]
- fn reseed_and_generate(&mut self,
- results: &mut <Self as BlockRngCore>::Results,
- global_fork_counter: usize)
- {
- if self.is_forked(global_fork_counter) {
- info!("Fork detected, reseeding RNG");
- } else {
- trace!("Reseeding RNG (periodic reseed)");
- }
-
- let num_bytes =
- results.as_ref().len() * size_of::<<R as BlockRngCore>::Item>();
-
- let threshold = if let Err(e) = self.reseed() {
- let delay = match e.kind {
- ErrorKind::Transient => num_bytes as i64,
- kind @ _ if kind.should_retry() => self.threshold >> 8,
- _ => self.threshold,
- };
- warn!("Reseeding RNG delayed reseeding by {} bytes due to \
- error from source: {}", delay, e);
- delay
- } else {
- self.fork_counter = global_fork_counter;
- self.threshold
- };
-
- self.bytes_until_reseed = threshold - num_bytes as i64;
- self.inner.generate(results);
- }
-}
-
-impl<R, Rsdr> Clone for ReseedingCore<R, Rsdr>
-where R: BlockRngCore + SeedableRng + Clone,
- Rsdr: RngCore + Clone
-{
- fn clone(&self) -> ReseedingCore<R, Rsdr> {
- ReseedingCore {
- inner: self.inner.clone(),
- reseeder: self.reseeder.clone(),
- threshold: self.threshold,
- bytes_until_reseed: 0, // reseed clone on first use
- fork_counter: self.fork_counter,
- }
- }
-}
-
-impl<R, Rsdr> CryptoRng for ReseedingCore<R, Rsdr>
-where R: BlockRngCore + SeedableRng + CryptoRng,
- Rsdr: RngCore + CryptoRng {}
-
-
-#[cfg(all(feature="std", unix, not(target_os="emscripten")))]
-mod fork {
- extern crate libc;
-
- use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
- use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
-
- // Fork protection
- //
- // We implement fork protection on Unix using `pthread_atfork`.
- // When the process is forked, we increment `RESEEDING_RNG_FORK_COUNTER`.
- // Every `ReseedingRng` stores the last known value of the static in
- // `fork_counter`. If the cached `fork_counter` is less than
- // `RESEEDING_RNG_FORK_COUNTER`, it is time to reseed this RNG.
- //
- // If reseeding fails, we don't deal with this by setting a delay, but just
- // don't update `fork_counter`, so a reseed is attempted as soon as
- // possible.
-
- static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
-
- pub fn get_fork_counter() -> usize {
- RESEEDING_RNG_FORK_COUNTER.load(Ordering::Relaxed)
- }
-
- static FORK_HANDLER_REGISTERED: AtomicBool = ATOMIC_BOOL_INIT;
-
- extern fn fork_handler() {
- // Note: fetch_add is defined to wrap on overflow
- // (which is what we want).
- RESEEDING_RNG_FORK_COUNTER.fetch_add(1, Ordering::Relaxed);
- }
-
- pub fn register_fork_handler() {
- if FORK_HANDLER_REGISTERED.load(Ordering::Relaxed) == false {
- unsafe { libc::pthread_atfork(None, None, Some(fork_handler)) };
- FORK_HANDLER_REGISTERED.store(true, Ordering::Relaxed);
- }
- }
-}
-
-#[cfg(not(all(feature="std", unix, not(target_os="emscripten"))))]
-mod fork {
- pub fn get_fork_counter() -> usize { 0 }
- pub fn register_fork_handler() {}
-}
-
-
-#[cfg(test)]
-mod test {
- use {Rng, SeedableRng};
- use rand_chacha::ChaChaCore;
- use rngs::mock::StepRng;
- use super::ReseedingRng;
-
- #[test]
- fn test_reseeding() {
- let mut zero = StepRng::new(0, 0);
- let rng = ChaChaCore::from_rng(&mut zero).unwrap();
- let mut reseeding = ReseedingRng::new(rng, 32*4, zero);
-
- // Currently we only support for arrays up to length 32.
- // TODO: cannot generate seq via Rng::gen because it uses different alg
- let mut buf = [0u32; 32]; // Needs to be a multiple of the RNGs result
- // size to test exactly.
- reseeding.fill(&mut buf);
- let seq = buf;
- for _ in 0..10 {
- reseeding.fill(&mut buf);
- assert_eq!(buf, seq);
- }
- }
-
- #[test]
- fn test_clone_reseeding() {
- let mut zero = StepRng::new(0, 0);
- let rng = ChaChaCore::from_rng(&mut zero).unwrap();
- let mut rng1 = ReseedingRng::new(rng, 32*4, zero);
-
- let first: u32 = rng1.gen();
- for _ in 0..10 { let _ = rng1.gen::<u32>(); }
-
- let mut rng2 = rng1.clone();
- assert_eq!(first, rng2.gen::<u32>());
- }
-}
diff --git a/rand/src/rngs/entropy.rs b/rand/src/rngs/entropy.rs
deleted file mode 100644
index 372b4d7..0000000
--- a/rand/src/rngs/entropy.rs
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Entropy generator, or wrapper around external generators
-
-use rand_core::{RngCore, CryptoRng, Error, ErrorKind, impls};
-#[allow(unused)]
-use rngs;
-
-/// An interface returning random data from external source(s), provided
-/// specifically for securely seeding algorithmic generators (PRNGs).
-///
-/// Where possible, `EntropyRng` retrieves random data from the operating
-/// system's interface for random numbers ([`OsRng`]); if that fails it will
-/// fall back to the [`JitterRng`] entropy collector. In the latter case it will
-/// still try to use [`OsRng`] on the next usage.
-///
-/// If no secure source of entropy is available `EntropyRng` will panic on use;
-/// i.e. it should never output predictable data.
-///
-/// This is either a little slow ([`OsRng`] requires a system call) or extremely
-/// slow ([`JitterRng`] must use significant CPU time to generate sufficient
-/// jitter); for better performance it is common to seed a local PRNG from
-/// external entropy then primarily use the local PRNG ([`thread_rng`] is
-/// provided as a convenient, local, automatically-seeded CSPRNG).
-///
-/// # Panics
-///
-/// On most systems, like Windows, Linux, macOS and *BSD on common hardware, it
-/// is highly unlikely for both [`OsRng`] and [`JitterRng`] to fail. But on
-/// combinations like webassembly without Emscripten or stdweb both sources are
-/// unavailable. If both sources fail, only [`try_fill_bytes`] is able to
-/// report the error, and only the one from `OsRng`. The other [`RngCore`]
-/// methods will panic in case of an error.
-///
-/// [`OsRng`]: struct.OsRng.html
-/// [`JitterRng`]: jitter/struct.JitterRng.html
-/// [`thread_rng`]: ../fn.thread_rng.html
-/// [`RngCore`]: ../trait.RngCore.html
-/// [`try_fill_bytes`]: ../trait.RngCore.html#method.tymethod.try_fill_bytes
-#[derive(Debug)]
-pub struct EntropyRng {
- source: Source,
-}
-
-#[derive(Debug)]
-enum Source {
- Os(Os),
- Custom(Custom),
- Jitter(Jitter),
- None,
-}
-
-impl EntropyRng {
- /// Create a new `EntropyRng`.
- ///
- /// This method will do no system calls or other initialization routines,
- /// those are done on first use. This is done to make `new` infallible,
- /// and `try_fill_bytes` the only place to report errors.
- pub fn new() -> Self {
- EntropyRng { source: Source::None }
- }
-}
-
-impl Default for EntropyRng {
- fn default() -> Self {
- EntropyRng::new()
- }
-}
-
-impl RngCore for EntropyRng {
- fn next_u32(&mut self) -> u32 {
- impls::next_u32_via_fill(self)
- }
-
- fn next_u64(&mut self) -> u64 {
- impls::next_u64_via_fill(self)
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- self.try_fill_bytes(dest).unwrap_or_else(|err|
- panic!("all entropy sources failed; first error: {}", err))
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- let mut reported_error = None;
-
- if let Source::Os(ref mut os_rng) = self.source {
- match os_rng.fill(dest) {
- Ok(()) => return Ok(()),
- Err(err) => {
- warn!("EntropyRng: OsRng failed \
- [trying other entropy sources]: {}", err);
- reported_error = Some(err);
- },
- }
- } else if Os::is_supported() {
- match Os::new_and_fill(dest) {
- Ok(os_rng) => {
- debug!("EntropyRng: using OsRng");
- self.source = Source::Os(os_rng);
- return Ok(());
- },
- Err(err) => { reported_error = reported_error.or(Some(err)) },
- }
- }
-
- if let Source::Custom(ref mut rng) = self.source {
- match rng.fill(dest) {
- Ok(()) => return Ok(()),
- Err(err) => {
- warn!("EntropyRng: custom entropy source failed \
- [trying other entropy sources]: {}", err);
- reported_error = Some(err);
- },
- }
- } else if Custom::is_supported() {
- match Custom::new_and_fill(dest) {
- Ok(custom) => {
- debug!("EntropyRng: using custom entropy source");
- self.source = Source::Custom(custom);
- return Ok(());
- },
- Err(err) => { reported_error = reported_error.or(Some(err)) },
- }
- }
-
- if let Source::Jitter(ref mut jitter_rng) = self.source {
- match jitter_rng.fill(dest) {
- Ok(()) => return Ok(()),
- Err(err) => {
- warn!("EntropyRng: JitterRng failed: {}", err);
- reported_error = Some(err);
- },
- }
- } else if Jitter::is_supported() {
- match Jitter::new_and_fill(dest) {
- Ok(jitter_rng) => {
- debug!("EntropyRng: using JitterRng");
- self.source = Source::Jitter(jitter_rng);
- return Ok(());
- },
- Err(err) => { reported_error = reported_error.or(Some(err)) },
- }
- }
-
- if let Some(err) = reported_error {
- Err(Error::with_cause(ErrorKind::Unavailable,
- "All entropy sources failed",
- err))
- } else {
- Err(Error::new(ErrorKind::Unavailable,
- "No entropy sources available"))
- }
- }
-}
-
-impl CryptoRng for EntropyRng {}
-
-
-
-trait EntropySource {
- fn new_and_fill(dest: &mut [u8]) -> Result<Self, Error>
- where Self: Sized;
-
- fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error>;
-
- fn is_supported() -> bool { true }
-}
-
-#[allow(unused)]
-#[derive(Clone, Debug)]
-struct NoSource;
-
-#[allow(unused)]
-impl EntropySource for NoSource {
- fn new_and_fill(dest: &mut [u8]) -> Result<Self, Error> {
- Err(Error::new(ErrorKind::Unavailable, "Source not supported"))
- }
-
- fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- unreachable!()
- }
-
- fn is_supported() -> bool { false }
-}
-
-
-#[cfg(feature="rand_os")]
-#[derive(Clone, Debug)]
-pub struct Os(rngs::OsRng);
-
-#[cfg(feature="rand_os")]
-impl EntropySource for Os {
- fn new_and_fill(dest: &mut [u8]) -> Result<Self, Error> {
- let mut rng = rngs::OsRng::new()?;
- rng.try_fill_bytes(dest)?;
- Ok(Os(rng))
- }
-
- fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- self.0.try_fill_bytes(dest)
- }
-}
-
-#[cfg(not(feature="std"))]
-type Os = NoSource;
-
-
-type Custom = NoSource;
-
-
-#[cfg(not(target_arch = "wasm32"))]
-#[derive(Clone, Debug)]
-pub struct Jitter(rngs::JitterRng);
-
-#[cfg(not(target_arch = "wasm32"))]
-impl EntropySource for Jitter {
- fn new_and_fill(dest: &mut [u8]) -> Result<Self, Error> {
- let mut rng = rngs::JitterRng::new()?;
- rng.try_fill_bytes(dest)?;
- Ok(Jitter(rng))
- }
-
- fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- self.0.try_fill_bytes(dest)
- }
-}
-
-#[cfg(target_arch = "wasm32")]
-type Jitter = NoSource;
-
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn test_entropy() {
- let mut rng = EntropyRng::new();
- let n = (rng.next_u32() ^ rng.next_u32()).count_ones();
- assert!(n >= 2); // p(failure) approx 1e-7
- }
-}
diff --git a/rand/src/rngs/jitter.rs b/rand/src/rngs/jitter.rs
deleted file mode 100644
index 3e93477..0000000
--- a/rand/src/rngs/jitter.rs
+++ /dev/null
@@ -1,885 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-// Based on jitterentropy-library, http://www.chronox.de/jent.html.
-// Copyright Stephan Mueller <smueller@chronox.de>, 2014 - 2017.
-//
-// With permission from Stephan Mueller to relicense the Rust translation under
-// the MIT license.
-
-//! Non-physical true random number generator based on timing jitter.
-
-// Note: the C implementation of `Jitterentropy` relies on being compiled
-// without optimizations. This implementation goes through lengths to make the
-// compiler not optimize out code which does influence timing jitter, but is
-// technically dead code.
-
-use rand_core::{RngCore, CryptoRng, Error, ErrorKind, impls};
-
-use core::{fmt, mem, ptr};
-#[cfg(all(feature="std", not(target_arch = "wasm32")))]
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
-
-const MEMORY_BLOCKS: usize = 64;
-const MEMORY_BLOCKSIZE: usize = 32;
-const MEMORY_SIZE: usize = MEMORY_BLOCKS * MEMORY_BLOCKSIZE;
-
-/// A true random number generator based on jitter in the CPU execution time,
-/// and jitter in memory access time.
-///
-/// This is a true random number generator, as opposed to pseudo-random
-/// generators. Random numbers generated by `JitterRng` can be seen as fresh
-/// entropy. A consequence is that is orders of magnitude slower than [`OsRng`]
-/// and PRNGs (about 10<sup>3</sup>..10<sup>6</sup> slower).
-///
-/// There are very few situations where using this RNG is appropriate. Only very
-/// few applications require true entropy. A normal PRNG can be statistically
-/// indistinguishable, and a cryptographic PRNG should also be as impossible to
-/// predict.
-///
-/// Use of `JitterRng` is recommended for initializing cryptographic PRNGs when
-/// [`OsRng`] is not available.
-///
-/// `JitterRng` can be used without the standard library, but not conveniently,
-/// you must provide a high-precision timer and carefully have to follow the
-/// instructions of [`new_with_timer`].
-///
-/// This implementation is based on
-/// [Jitterentropy](http://www.chronox.de/jent.html) version 2.1.0.
-///
-/// Note: There is no accurate timer available on Wasm platforms, to help
-/// prevent fingerprinting or timing side-channel attacks. Therefore
-/// [`JitterRng::new()`] is not available on Wasm.
-///
-/// # Quality testing
-///
-/// [`JitterRng::new()`] has build-in, but limited, quality testing, however
-/// before using `JitterRng` on untested hardware, or after changes that could
-/// effect how the code is optimized (such as a new LLVM version), it is
-/// recommend to run the much more stringent
-/// [NIST SP 800-90B Entropy Estimation Suite](
-/// https://github.com/usnistgov/SP800-90B_EntropyAssessment).
-///
-/// Use the following code using [`timer_stats`] to collect the data:
-///
-/// ```no_run
-/// use rand::rngs::JitterRng;
-/// #
-/// # use std::error::Error;
-/// # use std::fs::File;
-/// # use std::io::Write;
-/// #
-/// # fn try_main() -> Result<(), Box<Error>> {
-/// let mut rng = JitterRng::new()?;
-///
-/// // 1_000_000 results are required for the
-/// // NIST SP 800-90B Entropy Estimation Suite
-/// const ROUNDS: usize = 1_000_000;
-/// let mut deltas_variable: Vec<u8> = Vec::with_capacity(ROUNDS);
-/// let mut deltas_minimal: Vec<u8> = Vec::with_capacity(ROUNDS);
-///
-/// for _ in 0..ROUNDS {
-/// deltas_variable.push(rng.timer_stats(true) as u8);
-/// deltas_minimal.push(rng.timer_stats(false) as u8);
-/// }
-///
-/// // Write out after the statistics collection loop, to not disturb the
-/// // test results.
-/// File::create("jitter_rng_var.bin")?.write(&deltas_variable)?;
-/// File::create("jitter_rng_min.bin")?.write(&deltas_minimal)?;
-/// #
-/// # Ok(())
-/// # }
-/// #
-/// # fn main() {
-/// # try_main().unwrap();
-/// # }
-/// ```
-///
-/// This will produce two files: `jitter_rng_var.bin` and `jitter_rng_min.bin`.
-/// Run the Entropy Estimation Suite in three configurations, as outlined below.
-/// Every run has two steps. One step to produce an estimation, another to
-/// validate the estimation.
-///
-/// 1. Estimate the expected amount of entropy that is at least available with
-/// each round of the entropy collector. This number should be greater than
-/// the amount estimated with `64 / test_timer()`.
-/// ```sh
-/// python noniid_main.py -v jitter_rng_var.bin 8
-/// restart.py -v jitter_rng_var.bin 8 <min-entropy>
-/// ```
-/// 2. Estimate the expected amount of entropy that is available in the last 4
-/// bits of the timer delta after running noice sources. Note that a value of
-/// `3.70` is the minimum estimated entropy for true randomness.
-/// ```sh
-/// python noniid_main.py -v -u 4 jitter_rng_var.bin 4
-/// restart.py -v -u 4 jitter_rng_var.bin 4 <min-entropy>
-/// ```
-/// 3. Estimate the expected amount of entropy that is available to the entropy
-/// collector if both noice sources only run their minimal number of times.
-/// This measures the absolute worst-case, and gives a lower bound for the
-/// available entropy.
-/// ```sh
-/// python noniid_main.py -v -u 4 jitter_rng_min.bin 4
-/// restart.py -v -u 4 jitter_rng_min.bin 4 <min-entropy>
-/// ```
-///
-/// [`OsRng`]: struct.OsRng.html
-/// [`JitterRng::new()`]: struct.JitterRng.html#method.new
-/// [`new_with_timer`]: struct.JitterRng.html#method.new_with_timer
-/// [`timer_stats`]: struct.JitterRng.html#method.timer_stats
-pub struct JitterRng {
- data: u64, // Actual random number
- // Number of rounds to run the entropy collector per 64 bits
- rounds: u8,
- // Timer used by `measure_jitter`
- timer: fn() -> u64,
- // Memory for the Memory Access noise source
- mem_prev_index: u16,
- // Make `next_u32` not waste 32 bits
- data_half_used: bool,
-}
-
-// Note: `JitterRng` maintains a small 64-bit entropy pool. With every
-// `generate` 64 new bits should be integrated in the pool. If a round of
-// `generate` were to collect less than the expected 64 bit, then the returned
-// value, and the new state of the entropy pool, would be in some way related to
-// the initial state. It is therefore better if the initial state of the entropy
-// pool is different on each call to `generate`. This has a few implications:
-// - `generate` should be called once before using `JitterRng` to produce the
-// first usable value (this is done by default in `new`);
-// - We do not zero the entropy pool after generating a result. The reference
-// implementation also does not support zeroing, but recommends generating a
-// new value without using it if you want to protect a previously generated
-// 'secret' value from someone inspecting the memory;
-// - Implementing `Clone` seems acceptable, as it would not cause the systematic
-// bias a constant might cause. Only instead of one value that could be
-// potentially related to the same initial state, there are now two.
-
-// Entropy collector state.
-// These values are not necessary to preserve across runs.
-struct EcState {
- // Previous time stamp to determine the timer delta
- prev_time: u64,
- // Deltas used for the stuck test
- last_delta: i32,
- last_delta2: i32,
- // Memory for the Memory Access noise source
- mem: [u8; MEMORY_SIZE],
-}
-
-impl EcState {
- // Stuck test by checking the:
- // - 1st derivation of the jitter measurement (time delta)
- // - 2nd derivation of the jitter measurement (delta of time deltas)
- // - 3rd derivation of the jitter measurement (delta of delta of time
- // deltas)
- //
- // All values must always be non-zero.
- // This test is a heuristic to see whether the last measurement holds
- // entropy.
- fn stuck(&mut self, current_delta: i32) -> bool {
- let delta2 = self.last_delta - current_delta;
- let delta3 = delta2 - self.last_delta2;
-
- self.last_delta = current_delta;
- self.last_delta2 = delta2;
-
- current_delta == 0 || delta2 == 0 || delta3 == 0
- }
-}
-
-// Custom Debug implementation that does not expose the internal state
-impl fmt::Debug for JitterRng {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "JitterRng {{}}")
- }
-}
-
-impl Clone for JitterRng {
- fn clone(&self) -> JitterRng {
- JitterRng {
- data: self.data,
- rounds: self.rounds,
- timer: self.timer,
- mem_prev_index: self.mem_prev_index,
- // The 32 bits that may still be unused from the previous round are
- // for the original to use, not for the clone.
- data_half_used: false,
- }
- }
-}
-
-/// An error that can occur when [`JitterRng::test_timer`] fails.
-///
-/// [`JitterRng::test_timer`]: struct.JitterRng.html#method.test_timer
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum TimerError {
- /// No timer available.
- NoTimer,
- /// Timer too coarse to use as an entropy source.
- CoarseTimer,
- /// Timer is not monotonically increasing.
- NotMonotonic,
- /// Variations of deltas of time too small.
- TinyVariantions,
- /// Too many stuck results (indicating no added entropy).
- TooManyStuck,
- #[doc(hidden)]
- __Nonexhaustive,
-}
-
-impl TimerError {
- fn description(&self) -> &'static str {
- match *self {
- TimerError::NoTimer => "no timer available",
- TimerError::CoarseTimer => "coarse timer",
- TimerError::NotMonotonic => "timer not monotonic",
- TimerError::TinyVariantions => "time delta variations too small",
- TimerError::TooManyStuck => "too many stuck results",
- TimerError::__Nonexhaustive => unreachable!(),
- }
- }
-}
-
-impl fmt::Display for TimerError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", self.description())
- }
-}
-
-#[cfg(feature="std")]
-impl ::std::error::Error for TimerError {
- fn description(&self) -> &str {
- self.description()
- }
-}
-
-impl From<TimerError> for Error {
- fn from(err: TimerError) -> Error {
- // Timer check is already quite permissive of failures so we don't
- // expect false-positive failures, i.e. any error is irrecoverable.
- Error::with_cause(ErrorKind::Unavailable,
- "timer jitter failed basic quality tests", err)
- }
-}
-
-// Initialise to zero; must be positive
-#[cfg(all(feature="std", not(target_arch = "wasm32")))]
-static JITTER_ROUNDS: AtomicUsize = ATOMIC_USIZE_INIT;
-
-impl JitterRng {
- /// Create a new `JitterRng`. Makes use of `std::time` for a timer, or a
- /// platform-specific function with higher accuracy if necessary and
- /// available.
- ///
- /// During initialization CPU execution timing jitter is measured a few
- /// hundred times. If this does not pass basic quality tests, an error is
- /// returned. The test result is cached to make subsequent calls faster.
- #[cfg(all(feature="std", not(target_arch = "wasm32")))]
- pub fn new() -> Result<JitterRng, TimerError> {
- let mut state = JitterRng::new_with_timer(platform::get_nstime);
- let mut rounds = JITTER_ROUNDS.load(Ordering::Relaxed) as u8;
- if rounds == 0 {
- // No result yet: run test.
- // This allows the timer test to run multiple times; we don't care.
- rounds = state.test_timer()?;
- JITTER_ROUNDS.store(rounds as usize, Ordering::Relaxed);
- info!("JitterRng: using {} rounds per u64 output", rounds);
- }
- state.set_rounds(rounds);
-
- // Fill `data` with a non-zero value.
- state.gen_entropy();
- Ok(state)
- }
-
- /// Create a new `JitterRng`.
- /// A custom timer can be supplied, making it possible to use `JitterRng` in
- /// `no_std` environments.
- ///
- /// The timer must have nanosecond precision.
- ///
- /// This method is more low-level than `new()`. It is the responsibility of
- /// the caller to run [`test_timer`] before using any numbers generated with
- /// `JitterRng`, and optionally call [`set_rounds`]. Also it is important to
- /// consume at least one `u64` before using the first result to initialize
- /// the entropy collection pool.
- ///
- /// # Example
- ///
- /// ```
- /// # use rand::{Rng, Error};
- /// use rand::rngs::JitterRng;
- ///
- /// # fn try_inner() -> Result<(), Error> {
- /// fn get_nstime() -> u64 {
- /// use std::time::{SystemTime, UNIX_EPOCH};
- ///
- /// let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
- /// // The correct way to calculate the current time is
- /// // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64`
- /// // But this is faster, and the difference in terms of entropy is
- /// // negligible (log2(10^9) == 29.9).
- /// dur.as_secs() << 30 | dur.subsec_nanos() as u64
- /// }
- ///
- /// let mut rng = JitterRng::new_with_timer(get_nstime);
- /// let rounds = rng.test_timer()?;
- /// rng.set_rounds(rounds); // optional
- /// let _ = rng.gen::<u64>();
- ///
- /// // Ready for use
- /// let v: u64 = rng.gen();
- /// # Ok(())
- /// # }
- ///
- /// # let _ = try_inner();
- /// ```
- ///
- /// [`test_timer`]: struct.JitterRng.html#method.test_timer
- /// [`set_rounds`]: struct.JitterRng.html#method.set_rounds
- pub fn new_with_timer(timer: fn() -> u64) -> JitterRng {
- JitterRng {
- data: 0,
- rounds: 64,
- timer,
- mem_prev_index: 0,
- data_half_used: false,
- }
- }
-
- /// Configures how many rounds are used to generate each 64-bit value.
- /// This must be greater than zero, and has a big impact on performance
- /// and output quality.
- ///
- /// [`new_with_timer`] conservatively uses 64 rounds, but often less rounds
- /// can be used. The `test_timer()` function returns the minimum number of
- /// rounds required for full strength (platform dependent), so one may use
- /// `rng.set_rounds(rng.test_timer()?);` or cache the value.
- ///
- /// [`new_with_timer`]: struct.JitterRng.html#method.new_with_timer
- pub fn set_rounds(&mut self, rounds: u8) {
- assert!(rounds > 0);
- self.rounds = rounds;
- }
-
- // Calculate a random loop count used for the next round of an entropy
- // collection, based on bits from a fresh value from the timer.
- //
- // The timer is folded to produce a number that contains at most `n_bits`
- // bits.
- //
- // Note: A constant should be added to the resulting random loop count to
- // prevent loops that run 0 times.
- #[inline(never)]
- fn random_loop_cnt(&mut self, n_bits: u32) -> u32 {
- let mut rounds = 0;
-
- let mut time = (self.timer)();
- // Mix with the current state of the random number balance the random
- // loop counter a bit more.
- time ^= self.data;
-
- // We fold the time value as much as possible to ensure that as many
- // bits of the time stamp are included as possible.
- let folds = (64 + n_bits - 1) / n_bits;
- let mask = (1 << n_bits) - 1;
- for _ in 0..folds {
- rounds ^= time & mask;
- time >>= n_bits;
- }
-
- rounds as u32
- }
-
- // CPU jitter noise source
- // Noise source based on the CPU execution time jitter
- //
- // This function injects the individual bits of the time value into the
- // entropy pool using an LFSR.
- //
- // The code is deliberately inefficient with respect to the bit shifting.
- // This function not only acts as folding operation, but this function's
- // execution is used to measure the CPU execution time jitter. Any change to
- // the loop in this function implies that careful retesting must be done.
- #[inline(never)]
- fn lfsr_time(&mut self, time: u64, var_rounds: bool) {
- fn lfsr(mut data: u64, time: u64) -> u64{
- for i in 1..65 {
- let mut tmp = time << (64 - i);
- tmp >>= 64 - 1;
-
- // Fibonacci LSFR with polynomial of
- // x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
- // primitive according to
- // http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
- // (the shift values are the polynomial values minus one
- // due to counting bits from 0 to 63). As the current
- // position is always the LSB, the polynomial only needs
- // to shift data in from the left without wrap.
- data ^= tmp;
- data ^= (data >> 63) & 1;
- data ^= (data >> 60) & 1;
- data ^= (data >> 55) & 1;
- data ^= (data >> 30) & 1;
- data ^= (data >> 27) & 1;
- data ^= (data >> 22) & 1;
- data = data.rotate_left(1);
- }
- data
- }
-
- // Note: in the reference implementation only the last round effects
- // `self.data`, all the other results are ignored. To make sure the
- // other rounds are not optimised out, we first run all but the last
- // round on a throw-away value instead of the real `self.data`.
- let mut lfsr_loop_cnt = 0;
- if var_rounds { lfsr_loop_cnt = self.random_loop_cnt(4) };
-
- let mut throw_away: u64 = 0;
- for _ in 0..lfsr_loop_cnt {
- throw_away = lfsr(throw_away, time);
- }
- black_box(throw_away);
-
- self.data = lfsr(self.data, time);
- }
-
- // Memory Access noise source
- // This is a noise source based on variations in memory access times
- //
- // This function performs memory accesses which will add to the timing
- // variations due to an unknown amount of CPU wait states that need to be
- // added when accessing memory. The memory size should be larger than the L1
- // caches as outlined in the documentation and the associated testing.
- //
- // The L1 cache has a very high bandwidth, albeit its access rate is usually
- // slower than accessing CPU registers. Therefore, L1 accesses only add
- // minimal variations as the CPU has hardly to wait. Starting with L2,
- // significant variations are added because L2 typically does not belong to
- // the CPU any more and therefore a wider range of CPU wait states is
- // necessary for accesses. L3 and real memory accesses have even a wider
- // range of wait states. However, to reliably access either L3 or memory,
- // the `self.mem` memory must be quite large which is usually not desirable.
- #[inline(never)]
- fn memaccess(&mut self, mem: &mut [u8; MEMORY_SIZE], var_rounds: bool) {
- let mut acc_loop_cnt = 128;
- if var_rounds { acc_loop_cnt += self.random_loop_cnt(4) };
-
- let mut index = self.mem_prev_index as usize;
- for _ in 0..acc_loop_cnt {
- // Addition of memblocksize - 1 to index with wrap around logic to
- // ensure that every memory location is hit evenly.
- // The modulus also allows the compiler to remove the indexing
- // bounds check.
- index = (index + MEMORY_BLOCKSIZE - 1) % MEMORY_SIZE;
-
- // memory access: just add 1 to one byte
- // memory access implies read from and write to memory location
- mem[index] = mem[index].wrapping_add(1);
- }
- self.mem_prev_index = index as u16;
- }
-
- // This is the heart of the entropy generation: calculate time deltas and
- // use the CPU jitter in the time deltas. The jitter is injected into the
- // entropy pool.
- //
- // Ensure that `ec.prev_time` is primed before using the output of this
- // function. This can be done by calling this function and not using its
- // result.
- fn measure_jitter(&mut self, ec: &mut EcState) -> Option<()> {
- // Invoke one noise source before time measurement to add variations
- self.memaccess(&mut ec.mem, true);
-
- // Get time stamp and calculate time delta to previous
- // invocation to measure the timing variations
- let time = (self.timer)();
- // Note: wrapping_sub combined with a cast to `i64` generates a correct
- // delta, even in the unlikely case this is a timer that is not strictly
- // monotonic.
- let current_delta = time.wrapping_sub(ec.prev_time) as i64 as i32;
- ec.prev_time = time;
-
- // Call the next noise source which also injects the data
- self.lfsr_time(current_delta as u64, true);
-
- // Check whether we have a stuck measurement (i.e. does the last
- // measurement holds entropy?).
- if ec.stuck(current_delta) { return None };
-
- // Rotate the data buffer by a prime number (any odd number would
- // do) to ensure that every bit position of the input time stamp
- // has an even chance of being merged with a bit position in the
- // entropy pool. We do not use one here as the adjacent bits in
- // successive time deltas may have some form of dependency. The
- // chosen value of 7 implies that the low 7 bits of the next
- // time delta value is concatenated with the current time delta.
- self.data = self.data.rotate_left(7);
-
- Some(())
- }
-
- // Shuffle the pool a bit by mixing some value with a bijective function
- // (XOR) into the pool.
- //
- // The function generates a mixer value that depends on the bits set and
- // the location of the set bits in the random number generated by the
- // entropy source. Therefore, based on the generated random number, this
- // mixer value can have 2^64 different values. That mixer value is
- // initialized with the first two SHA-1 constants. After obtaining the
- // mixer value, it is XORed into the random number.
- //
- // The mixer value is not assumed to contain any entropy. But due to the
- // XOR operation, it can also not destroy any entropy present in the
- // entropy pool.
- #[inline(never)]
- fn stir_pool(&mut self) {
- // This constant is derived from the first two 32 bit initialization
- // vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1
- // The order does not really matter as we do not rely on the specific
- // numbers. We just pick the SHA-1 constants as they have a good mix of
- // bit set and unset.
- const CONSTANT: u64 = 0x67452301efcdab89;
-
- // The start value of the mixer variable is derived from the third
- // and fourth 32 bit initialization vector of SHA-1 as defined in
- // FIPS 180-4 section 5.3.1
- let mut mixer = 0x98badcfe10325476;
-
- // This is a constant time function to prevent leaking timing
- // information about the random number.
- // The normal code is:
- // ```
- // for i in 0..64 {
- // if ((self.data >> i) & 1) == 1 { mixer ^= CONSTANT; }
- // }
- // ```
- // This is a bit fragile, as LLVM really wants to use branches here, and
- // we rely on it to not recognise the opportunity.
- for i in 0..64 {
- let apply = (self.data >> i) & 1;
- let mask = !apply.wrapping_sub(1);
- mixer ^= CONSTANT & mask;
- mixer = mixer.rotate_left(1);
- }
-
- self.data ^= mixer;
- }
-
- fn gen_entropy(&mut self) -> u64 {
- trace!("JitterRng: collecting entropy");
-
- // Prime `ec.prev_time`, and run the noice sources to make sure the
- // first loop round collects the expected entropy.
- let mut ec = EcState {
- prev_time: (self.timer)(),
- last_delta: 0,
- last_delta2: 0,
- mem: [0; MEMORY_SIZE],
- };
- let _ = self.measure_jitter(&mut ec);
-
- for _ in 0..self.rounds {
- // If a stuck measurement is received, repeat measurement
- // Note: we do not guard against an infinite loop, that would mean
- // the timer suddenly became broken.
- while self.measure_jitter(&mut ec).is_none() {}
- }
-
- // Do a single read from `self.mem` to make sure the Memory Access noise
- // source is not optimised out.
- black_box(ec.mem[0]);
-
- self.stir_pool();
- self.data
- }
-
- /// Basic quality tests on the timer, by measuring CPU timing jitter a few
- /// hundred times.
- ///
- /// If succesful, this will return the estimated number of rounds necessary
- /// to collect 64 bits of entropy. Otherwise a [`TimerError`] with the cause
- /// of the failure will be returned.
- ///
- /// [`TimerError`]: enum.TimerError.html
- pub fn test_timer(&mut self) -> Result<u8, TimerError> {
- debug!("JitterRng: testing timer ...");
- // We could add a check for system capabilities such as `clock_getres`
- // or check for `CONFIG_X86_TSC`, but it does not make much sense as the
- // following sanity checks verify that we have a high-resolution timer.
-
- let mut delta_sum = 0;
- let mut old_delta = 0;
-
- let mut time_backwards = 0;
- let mut count_mod = 0;
- let mut count_stuck = 0;
-
- let mut ec = EcState {
- prev_time: (self.timer)(),
- last_delta: 0,
- last_delta2: 0,
- mem: [0; MEMORY_SIZE],
- };
-
- // TESTLOOPCOUNT needs some loops to identify edge systems.
- // 100 is definitely too little.
- const TESTLOOPCOUNT: u64 = 300;
- const CLEARCACHE: u64 = 100;
-
- for i in 0..(CLEARCACHE + TESTLOOPCOUNT) {
- // Measure time delta of core entropy collection logic
- let time = (self.timer)();
- self.memaccess(&mut ec.mem, true);
- self.lfsr_time(time, true);
- let time2 = (self.timer)();
-
- // Test whether timer works
- if time == 0 || time2 == 0 {
- return Err(TimerError::NoTimer);
- }
- let delta = time2.wrapping_sub(time) as i64 as i32;
-
- // Test whether timer is fine grained enough to provide delta even
- // when called shortly after each other -- this implies that we also
- // have a high resolution timer
- if delta == 0 {
- return Err(TimerError::CoarseTimer);
- }
-
- // Up to here we did not modify any variable that will be
- // evaluated later, but we already performed some work. Thus we
- // already have had an impact on the caches, branch prediction,
- // etc. with the goal to clear it to get the worst case
- // measurements.
- if i < CLEARCACHE { continue; }
-
- if ec.stuck(delta) { count_stuck += 1; }
-
- // Test whether we have an increasing timer.
- if !(time2 > time) { time_backwards += 1; }
-
- // Count the number of times the counter increases in steps of 100ns
- // or greater.
- if (delta % 100) == 0 { count_mod += 1; }
-
- // Ensure that we have a varying delta timer which is necessary for
- // the calculation of entropy -- perform this check only after the
- // first loop is executed as we need to prime the old_delta value
- delta_sum += (delta - old_delta).abs() as u64;
- old_delta = delta;
- }
-
- // Do a single read from `self.mem` to make sure the Memory Access noise
- // source is not optimised out.
- black_box(ec.mem[0]);
-
- // We allow the time to run backwards for up to three times.
- // This can happen if the clock is being adjusted by NTP operations.
- // If such an operation just happens to interfere with our test, it
- // should not fail. The value of 3 should cover the NTP case being
- // performed during our test run.
- if time_backwards > 3 {
- return Err(TimerError::NotMonotonic);
- }
-
- // Test that the available amount of entropy per round does not get to
- // low. We expect 1 bit of entropy per round as a reasonable minimum
- // (although less is possible, it means the collector loop has to run
- // much more often).
- // `assert!(delta_average >= log2(1))`
- // `assert!(delta_sum / TESTLOOPCOUNT >= 1)`
- // `assert!(delta_sum >= TESTLOOPCOUNT)`
- if delta_sum < TESTLOOPCOUNT {
- return Err(TimerError::TinyVariantions);
- }
-
- // Ensure that we have variations in the time stamp below 100 for at
- // least 10% of all checks -- on some platforms, the counter increments
- // in multiples of 100, but not always
- if count_mod > (TESTLOOPCOUNT * 9 / 10) {
- return Err(TimerError::CoarseTimer);
- }
-
- // If we have more than 90% stuck results, then this Jitter RNG is
- // likely to not work well.
- if count_stuck > (TESTLOOPCOUNT * 9 / 10) {
- return Err(TimerError::TooManyStuck);
- }
-
- // Estimate the number of `measure_jitter` rounds necessary for 64 bits
- // of entropy.
- //
- // We don't try very hard to come up with a good estimate of the
- // available bits of entropy per round here for two reasons:
- // 1. Simple estimates of the available bits (like Shannon entropy) are
- // too optimistic.
- // 2. Unless we want to waste a lot of time during intialization, there
- // only a small number of samples are available.
- //
- // Therefore we use a very simple and conservative estimate:
- // `let bits_of_entropy = log2(delta_average) / 2`.
- //
- // The number of rounds `measure_jitter` should run to collect 64 bits
- // of entropy is `64 / bits_of_entropy`.
- let delta_average = delta_sum / TESTLOOPCOUNT;
-
- if delta_average >= 16 {
- let log2 = 64 - delta_average.leading_zeros();
- // Do something similar to roundup(64/(log2/2)):
- Ok( ((64u32 * 2 + log2 - 1) / log2) as u8)
- } else {
- // For values < 16 the rounding error becomes too large, use a
- // lookup table.
- // Values 0 and 1 are invalid, and filtered out by the
- // `delta_sum < TESTLOOPCOUNT` test above.
- let log2_lookup = [0, 0, 128, 81, 64, 56, 50, 46,
- 43, 41, 39, 38, 36, 35, 34, 33];
- Ok(log2_lookup[delta_average as usize])
- }
- }
-
- /// Statistical test: return the timer delta of one normal run of the
- /// `JitterRng` entropy collector.
- ///
- /// Setting `var_rounds` to `true` will execute the memory access and the
- /// CPU jitter noice sources a variable amount of times (just like a real
- /// `JitterRng` round).
- ///
- /// Setting `var_rounds` to `false` will execute the noice sources the
- /// minimal number of times. This can be used to measure the minimum amount
- /// of entropy one round of the entropy collector can collect in the worst
- /// case.
- ///
- /// See [Quality testing](struct.JitterRng.html#quality-testing) on how to
- /// use `timer_stats` to test the quality of `JitterRng`.
- pub fn timer_stats(&mut self, var_rounds: bool) -> i64 {
- let mut mem = [0; MEMORY_SIZE];
-
- let time = (self.timer)();
- self.memaccess(&mut mem, var_rounds);
- self.lfsr_time(time, var_rounds);
- let time2 = (self.timer)();
- time2.wrapping_sub(time) as i64
- }
-}
-
-#[cfg(feature="std")]
-mod platform {
- #[cfg(not(any(target_os = "macos", target_os = "ios",
- target_os = "windows",
- target_arch = "wasm32")))]
- pub fn get_nstime() -> u64 {
- use std::time::{SystemTime, UNIX_EPOCH};
-
- let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
- // The correct way to calculate the current time is
- // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64`
- // But this is faster, and the difference in terms of entropy is
- // negligible (log2(10^9) == 29.9).
- dur.as_secs() << 30 | dur.subsec_nanos() as u64
- }
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- pub fn get_nstime() -> u64 {
- extern crate libc;
- // On Mac OS and iOS std::time::SystemTime only has 1000ns resolution.
- // We use `mach_absolute_time` instead. This provides a CPU dependent
- // unit, to get real nanoseconds the result should by multiplied by
- // numer/denom from `mach_timebase_info`.
- // But we are not interested in the exact nanoseconds, just entropy. So
- // we use the raw result.
- unsafe { libc::mach_absolute_time() }
- }
-
- #[cfg(target_os = "windows")]
- pub fn get_nstime() -> u64 {
- extern crate winapi;
- unsafe {
- let mut t = super::mem::zeroed();
- winapi::um::profileapi::QueryPerformanceCounter(&mut t);
- *t.QuadPart() as u64
- }
- }
-}
-
-// A function that is opaque to the optimizer to assist in avoiding dead-code
-// elimination. Taken from `bencher`.
-fn black_box<T>(dummy: T) -> T {
- unsafe {
- let ret = ptr::read_volatile(&dummy);
- mem::forget(dummy);
- ret
- }
-}
-
-impl RngCore for JitterRng {
- fn next_u32(&mut self) -> u32 {
- // We want to use both parts of the generated entropy
- if self.data_half_used {
- self.data_half_used = false;
- (self.data >> 32) as u32
- } else {
- self.data = self.next_u64();
- self.data_half_used = true;
- self.data as u32
- }
- }
-
- fn next_u64(&mut self) -> u64 {
- self.data_half_used = false;
- self.gen_entropy()
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- // Fill using `next_u32`. This is faster for filling small slices (four
- // bytes or less), while the overhead is negligible.
- //
- // This is done especially for wrappers that implement `next_u32`
- // themselves via `fill_bytes`.
- impls::fill_bytes_via_next(self, dest)
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- Ok(self.fill_bytes(dest))
- }
-}
-
-impl CryptoRng for JitterRng {}
-
-#[cfg(test)]
-mod test_jitter_init {
- use super::JitterRng;
-
- #[cfg(all(feature="std", not(target_arch = "wasm32")))]
- #[test]
- fn test_jitter_init() {
- use RngCore;
- // Because this is a debug build, measurements here are not representive
- // of the final release build.
- // Don't fail this test if initializing `JitterRng` fails because of a
- // bad timer (the timer from the standard library may not have enough
- // accuracy on all platforms).
- match JitterRng::new() {
- Ok(ref mut rng) => {
- // false positives are possible, but extremely unlikely
- assert!(rng.next_u32() | rng.next_u32() != 0);
- },
- Err(_) => {},
- }
- }
-
- #[test]
- fn test_jitter_bad_timer() {
- fn bad_timer() -> u64 { 0 }
- let mut rng = JitterRng::new_with_timer(bad_timer);
- assert!(rng.test_timer().is_err());
- }
-}
diff --git a/rand/src/rngs/mock.rs b/rand/src/rngs/mock.rs
deleted file mode 100644
index 3c9a994..0000000
--- a/rand/src/rngs/mock.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Mock random number generator
-
-use rand_core::{RngCore, Error, impls};
-
-/// A simple implementation of `RngCore` for testing purposes.
-///
-/// This generates an arithmetic sequence (i.e. adds a constant each step)
-/// over a `u64` number, using wrapping arithmetic. If the increment is 0
-/// the generator yields a constant.
-///
-/// ```
-/// use rand::Rng;
-/// use rand::rngs::mock::StepRng;
-///
-/// let mut my_rng = StepRng::new(2, 1);
-/// let sample: [u64; 3] = my_rng.gen();
-/// assert_eq!(sample, [2, 3, 4]);
-/// ```
-#[derive(Debug, Clone)]
-pub struct StepRng {
- v: u64,
- a: u64,
-}
-
-impl StepRng {
- /// Create a `StepRng`, yielding an arithmetic sequence starting with
- /// `initial` and incremented by `increment` each time.
- pub fn new(initial: u64, increment: u64) -> Self {
- StepRng { v: initial, a: increment }
- }
-}
-
-impl RngCore for StepRng {
- fn next_u32(&mut self) -> u32 {
- self.next_u64() as u32
- }
-
- fn next_u64(&mut self) -> u64 {
- let result = self.v;
- self.v = self.v.wrapping_add(self.a);
- result
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- impls::fill_bytes_via_next(self, dest);
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- Ok(self.fill_bytes(dest))
- }
-}
diff --git a/rand/src/rngs/mod.rs b/rand/src/rngs/mod.rs
deleted file mode 100644
index 847fc94..0000000
--- a/rand/src/rngs/mod.rs
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Random number generators and adapters for common usage:
-//!
-//! - [`ThreadRng`], a fast, secure, auto-seeded thread-local generator
-//! - [`StdRng`] and [`SmallRng`], algorithms to cover typical usage
-//! - [`EntropyRng`], [`OsRng`] and [`JitterRng`] as entropy sources
-//! - [`mock::StepRng`] as a simple counter for tests
-//! - [`adapter::ReadRng`] to read from a file/stream
-//! - [`adapter::ReseedingRng`] to reseed a PRNG on clone / process fork etc.
-//!
-//! # Background — Random number generators (RNGs)
-//!
-//! Computers are inherently deterministic, so to get *random* numbers one
-//! either has to use a hardware generator or collect bits of *entropy* from
-//! various sources (e.g. event timestamps, or jitter). This is a relatively
-//! slow and complicated operation.
-//!
-//! Generally the operating system will collect some entropy, remove bias, and
-//! use that to seed its own PRNG; [`OsRng`] provides an interface to this.
-//! [`JitterRng`] is an entropy collector included with Rand that measures
-//! jitter in the CPU execution time, and jitter in memory access time.
-//! [`EntropyRng`] is a wrapper that uses the best entropy source that is
-//! available.
-//!
-//! ## Pseudo-random number generators
-//!
-//! What is commonly used instead of "true" random number renerators, are
-//! *pseudo-random number generators* (PRNGs), deterministic algorithms that
-//! produce an infinite stream of pseudo-random numbers from a small random
-//! seed. PRNGs are faster, and have better provable properties. The numbers
-//! produced can be statistically of very high quality and can be impossible to
-//! predict. (They can also have obvious correlations and be trivial to predict;
-//! quality varies.)
-//!
-//! There are two different types of PRNGs: those developed for simulations
-//! and statistics, and those developed for use in cryptography; the latter are
-//! called Cryptographically Secure PRNGs (CSPRNG or CPRNG). Both types can
-//! have good statistical quality but the latter also have to be impossible to
-//! predict, even after seeing many previous output values. Rand provides a good
-//! default algorithm from each class:
-//!
-//! - [`SmallRng`] is a PRNG chosen for low memory usage, high performance and
-//! good statistical quality.
-//! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security
-//! (based on reviews, maturity and usage). The current algorithm is HC-128,
-//! which is one of the recommendations by ECRYPT's eSTREAM project.
-//!
-//! The above PRNGs do not cover all use-cases; more algorithms can be found in
-//! the [`prng` module], as well as in several other crates. For example, you
-//! may wish a CSPRNG with significantly lower memory usage than [`StdRng`]
-//! while being less concerned about performance, in which case [`ChaChaRng`]
-//! is a good choice.
-//!
-//! One complexity is that the internal state of a PRNG must change with every
-//! generated number. For APIs this generally means a mutable reference to the
-//! state of the PRNG has to be passed around.
-//!
-//! A solution is [`ThreadRng`]. This is a thread-local implementation of
-//! [`StdRng`] with automatic seeding on first use. It is the best choice if you
-//! "just" want a convenient, secure, fast random number source. Use via the
-//! [`thread_rng`] function, which gets a reference to the current thread's
-//! local instance.
-//!
-//! ## Seeding
-//!
-//! As mentioned above, PRNGs require a random seed in order to produce random
-//! output. This is especially important for CSPRNGs, which are still
-//! deterministic algorithms, thus can only be secure if their seed value is
-//! also secure. To seed a PRNG, use one of:
-//!
-//! - [`FromEntropy::from_entropy`]; this is the most convenient way to seed
-//! with fresh, secure random data.
-//! - [`SeedableRng::from_rng`]; this allows seeding from another PRNG or
-//! from an entropy source such as [`EntropyRng`].
-//! - [`SeedableRng::from_seed`]; this is mostly useful if you wish to be able
-//! to reproduce the output sequence by using a fixed seed. (Don't use
-//! [`StdRng`] or [`SmallRng`] in this case since different algorithms may be
-//! used by future versions of Rand; use an algorithm from the
-//! [`prng` module].)
-//!
-//! ## Conclusion
-//!
-//! - [`thread_rng`] is what you often want to use.
-//! - If you want more control, flexibility, or better performance, use
-//! [`StdRng`], [`SmallRng`] or an algorithm from the [`prng` module].
-//! - Use [`FromEntropy::from_entropy`] to seed new PRNGs.
-//! - If you need reproducibility, use [`SeedableRng::from_seed`] combined with
-//! a named PRNG.
-//!
-//! More information and notes on cryptographic security can be found
-//! in the [`prng` module].
-//!
-//! ## Examples
-//!
-//! Examples of seeding PRNGs:
-//!
-//! ```
-//! use rand::prelude::*;
-//! # use rand::Error;
-//!
-//! // StdRng seeded securely by the OS or local entropy collector:
-//! let mut rng = StdRng::from_entropy();
-//! # let v: u32 = rng.gen();
-//!
-//! // SmallRng seeded from thread_rng:
-//! # fn try_inner() -> Result<(), Error> {
-//! let mut rng = SmallRng::from_rng(thread_rng())?;
-//! # let v: u32 = rng.gen();
-//! # Ok(())
-//! # }
-//! # try_inner().unwrap();
-//!
-//! // SmallRng seeded by a constant, for deterministic results:
-//! let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]; // byte array
-//! let mut rng = SmallRng::from_seed(seed);
-//! # let v: u32 = rng.gen();
-//! ```
-//!
-//!
-//! # Implementing custom RNGs
-//!
-//! If you want to implement custom RNG, see the [`rand_core`] crate. The RNG
-//! will have to implement the [`RngCore`] trait, where the [`Rng`] trait is
-//! build on top of.
-//!
-//! If the RNG needs seeding, also implement the [`SeedableRng`] trait.
-//!
-//! [`CryptoRng`] is a marker trait cryptographically secure PRNGs can
-//! implement.
-//!
-//!
-// This module:
-//! [`ThreadRng`]: struct.ThreadRng.html
-//! [`StdRng`]: struct.StdRng.html
-//! [`SmallRng`]: struct.SmallRng.html
-//! [`EntropyRng`]: struct.EntropyRng.html
-//! [`OsRng`]: struct.OsRng.html
-//! [`JitterRng`]: struct.JitterRng.html
-// Other traits and functions:
-//! [`rand_core`]: https://crates.io/crates/rand_core
-//! [`prng` module]: ../prng/index.html
-//! [`CryptoRng`]: ../trait.CryptoRng.html
-//! [`FromEntropy`]: ../trait.FromEntropy.html
-//! [`FromEntropy::from_entropy`]: ../trait.FromEntropy.html#tymethod.from_entropy
-//! [`RngCore`]: ../trait.RngCore.html
-//! [`Rng`]: ../trait.Rng.html
-//! [`SeedableRng`]: ../trait.SeedableRng.html
-//! [`SeedableRng::from_rng`]: ../trait.SeedableRng.html#tymethod.from_rng
-//! [`SeedableRng::from_seed`]: ../trait.SeedableRng.html#tymethod.from_seed
-//! [`thread_rng`]: ../fn.thread_rng.html
-//! [`mock::StepRng`]: mock/struct.StepRng.html
-//! [`adapter::ReadRng`]: adapter/struct.ReadRng.html
-//! [`adapter::ReseedingRng`]: adapter/struct.ReseedingRng.html
-//! [`ChaChaRng`]: ../../rand_chacha/struct.ChaChaRng.html
-
-pub mod adapter;
-
-#[cfg(feature="std")] mod entropy;
-mod jitter;
-pub mod mock; // Public so we don't export `StepRng` directly, making it a bit
- // more clear it is intended for testing.
-mod small;
-mod std;
-#[cfg(feature="std")] pub(crate) mod thread;
-
-
-pub use self::jitter::{JitterRng, TimerError};
-#[cfg(feature="std")] pub use self::entropy::EntropyRng;
-
-pub use self::small::SmallRng;
-pub use self::std::StdRng;
-#[cfg(feature="std")] pub use self::thread::ThreadRng;
-
-#[cfg(feature="rand_os")]
-pub use rand_os::OsRng;
diff --git a/rand/src/rngs/small.rs b/rand/src/rngs/small.rs
deleted file mode 100644
index b652c8c..0000000
--- a/rand/src/rngs/small.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A small fast RNG
-
-use {RngCore, SeedableRng, Error};
-
-#[cfg(all(all(rustc_1_26, not(target_os = "emscripten")), target_pointer_width = "64"))]
-type Rng = ::rand_pcg::Pcg64Mcg;
-#[cfg(not(all(all(rustc_1_26, not(target_os = "emscripten")), target_pointer_width = "64")))]
-type Rng = ::rand_pcg::Pcg32;
-
-/// An RNG recommended when small state, cheap initialization and good
-/// performance are required. The PRNG algorithm in `SmallRng` is chosen to be
-/// efficient on the current platform, **without consideration for cryptography
-/// or security**. The size of its state is much smaller than for [`StdRng`].
-///
-/// Reproducibility of output from this generator is however not required, thus
-/// future library versions may use a different internal generator with
-/// different output. Further, this generator may not be portable and can
-/// produce different output depending on the architecture. If you require
-/// reproducible output, use a named RNG. Refer to the documentation on the
-/// [`prng` module](../prng/index.html).
-///
-/// The current algorithm is [`Pcg64Mcg`] on 64-bit platforms with Rust version
-/// 1.26 and later, or [`Pcg32`] otherwise.
-///
-/// # Examples
-///
-/// Initializing `SmallRng` with a random seed can be done using [`FromEntropy`]:
-///
-/// ```
-/// # use rand::Rng;
-/// use rand::FromEntropy;
-/// use rand::rngs::SmallRng;
-///
-/// // Create small, cheap to initialize and fast RNG with a random seed.
-/// // The randomness is supplied by the operating system.
-/// let mut small_rng = SmallRng::from_entropy();
-/// # let v: u32 = small_rng.gen();
-/// ```
-///
-/// When initializing a lot of `SmallRng`'s, using [`thread_rng`] can be more
-/// efficient:
-///
-/// ```
-/// use std::iter;
-/// use rand::{SeedableRng, thread_rng};
-/// use rand::rngs::SmallRng;
-///
-/// // Create a big, expensive to initialize and slower, but unpredictable RNG.
-/// // This is cached and done only once per thread.
-/// let mut thread_rng = thread_rng();
-/// // Create small, cheap to initialize and fast RNGs with random seeds.
-/// // One can generally assume this won't fail.
-/// let rngs: Vec<SmallRng> = iter::repeat(())
-/// .map(|()| SmallRng::from_rng(&mut thread_rng).unwrap())
-/// .take(10)
-/// .collect();
-/// ```
-///
-/// [`FromEntropy`]: ../trait.FromEntropy.html
-/// [`StdRng`]: struct.StdRng.html
-/// [`thread_rng`]: ../fn.thread_rng.html
-/// [`Pcg64Mcg`]: ../../rand_pcg/type.Pcg64Mcg.html
-/// [`Pcg32`]: ../../rand_pcg/type.Pcg32.html
-#[derive(Clone, Debug)]
-pub struct SmallRng(Rng);
-
-impl RngCore for SmallRng {
- #[inline(always)]
- fn next_u32(&mut self) -> u32 {
- self.0.next_u32()
- }
-
- #[inline(always)]
- fn next_u64(&mut self) -> u64 {
- self.0.next_u64()
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- self.0.fill_bytes(dest);
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- self.0.try_fill_bytes(dest)
- }
-}
-
-impl SeedableRng for SmallRng {
- type Seed = <Rng as SeedableRng>::Seed;
-
- fn from_seed(seed: Self::Seed) -> Self {
- SmallRng(Rng::from_seed(seed))
- }
-
- fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
- Rng::from_rng(rng).map(SmallRng)
- }
-}
diff --git a/rand/src/rngs/std.rs b/rand/src/rngs/std.rs
deleted file mode 100644
index ce1658b..0000000
--- a/rand/src/rngs/std.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The standard RNG
-
-use {RngCore, CryptoRng, Error, SeedableRng};
-use rand_hc::Hc128Rng;
-
-/// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient
-/// on the current platform, to be statistically strong and unpredictable
-/// (meaning a cryptographically secure PRNG).
-///
-/// The current algorithm used on all platforms is [HC-128].
-///
-/// Reproducibility of output from this generator is however not required, thus
-/// future library versions may use a different internal generator with
-/// different output. Further, this generator may not be portable and can
-/// produce different output depending on the architecture. If you require
-/// reproducible output, use a named RNG, for example [`ChaChaRng`].
-///
-/// [HC-128]: ../../rand_hc/struct.Hc128Rng.html
-/// [`ChaChaRng`]: ../../rand_chacha/struct.ChaChaRng.html
-#[derive(Clone, Debug)]
-pub struct StdRng(Hc128Rng);
-
-impl RngCore for StdRng {
- #[inline(always)]
- fn next_u32(&mut self) -> u32 {
- self.0.next_u32()
- }
-
- #[inline(always)]
- fn next_u64(&mut self) -> u64 {
- self.0.next_u64()
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- self.0.fill_bytes(dest);
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- self.0.try_fill_bytes(dest)
- }
-}
-
-impl SeedableRng for StdRng {
- type Seed = <Hc128Rng as SeedableRng>::Seed;
-
- fn from_seed(seed: Self::Seed) -> Self {
- StdRng(Hc128Rng::from_seed(seed))
- }
-
- fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
- Hc128Rng::from_rng(rng).map(StdRng)
- }
-}
-
-impl CryptoRng for StdRng {}
-
-
-#[cfg(test)]
-mod test {
- use {RngCore, SeedableRng};
- use rngs::StdRng;
-
- #[test]
- fn test_stdrng_construction() {
- let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0,
- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
- let mut rng1 = StdRng::from_seed(seed);
- assert_eq!(rng1.next_u64(), 15759097995037006553);
-
- let mut rng2 = StdRng::from_rng(rng1).unwrap();
- assert_eq!(rng2.next_u64(), 6766915756997287454);
- }
-}
diff --git a/rand/src/rngs/thread.rs b/rand/src/rngs/thread.rs
deleted file mode 100644
index 7977d85..0000000
--- a/rand/src/rngs/thread.rs
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Thread-local random number generator
-
-use std::cell::UnsafeCell;
-
-use {RngCore, CryptoRng, SeedableRng, Error};
-use rngs::adapter::ReseedingRng;
-use rngs::EntropyRng;
-use rand_hc::Hc128Core;
-
-// Rationale for using `UnsafeCell` in `ThreadRng`:
-//
-// Previously we used a `RefCell`, with an overhead of ~15%. There will only
-// ever be one mutable reference to the interior of the `UnsafeCell`, because
-// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
-// single thread (which is the definition of `ThreadRng`), there will only ever
-// be one of these methods active at a time.
-//
-// A possible scenario where there could be multiple mutable references is if
-// `ThreadRng` is used inside `next_u32` and co. But the implementation is
-// completely under our control. We just have to ensure none of them use
-// `ThreadRng` internally, which is nonsensical anyway. We should also never run
-// `ThreadRng` in destructors of its implementation, which is also nonsensical.
-//
-// The additional `Rc` is not strictly neccesary, and could be removed. For now
-// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.
-
-
-// Number of generated bytes after which to reseed `TreadRng`.
-//
-// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
-// We pick a treshold here that is large enough to not reduce the average
-// performance too much, but also small enough to not make reseeding something
-// that basically never happens.
-const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB
-
-/// The type returned by [`thread_rng`], essentially just a reference to the
-/// PRNG in thread-local memory.
-///
-/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
-/// which is reseeded after generating 32 MiB of random data. A single instance
-/// is cached per thread and the returned `ThreadRng` is a reference to this
-/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
-/// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`]
-/// as required.
-///
-/// Note that the reseeding is done as an extra precaution against entropy
-/// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an
-/// attacker would have to either determine most of the RNG's seed or internal
-/// state, or crack the algorithm used.
-///
-/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
-/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
-/// usage for better performance. This makes it similar to ISAAC, the algorithm
-/// used in `ThreadRng` before rand 0.5.
-///
-/// Cloning this handle just produces a new reference to the same thread-local
-/// generator.
-///
-/// [`thread_rng`]: ../fn.thread_rng.html
-/// [`ReseedingRng`]: adapter/struct.ReseedingRng.html
-/// [`StdRng`]: struct.StdRng.html
-/// [`EntropyRng`]: struct.EntropyRng.html
-/// [HC-128]: ../../rand_hc/struct.Hc128Rng.html
-#[derive(Clone, Debug)]
-pub struct ThreadRng {
- // use of raw pointer implies type is neither Send nor Sync
- rng: *mut ReseedingRng<Hc128Core, EntropyRng>,
-}
-
-thread_local!(
- static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>> = {
- let mut entropy_source = EntropyRng::new();
- let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err|
- panic!("could not initialize thread_rng: {}", err));
- let rng = ReseedingRng::new(r,
- THREAD_RNG_RESEED_THRESHOLD,
- entropy_source);
- UnsafeCell::new(rng)
- }
-);
-
-/// Retrieve the lazily-initialized thread-local random number generator,
-/// seeded by the system. Intended to be used in method chaining style,
-/// e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
-/// `let mut rng = thread_rng();`. Invoked by the `Default` trait, making
-/// `ThreadRng::default()` equivelent.
-///
-/// For more information see [`ThreadRng`].
-///
-/// [`ThreadRng`]: rngs/struct.ThreadRng.html
-pub fn thread_rng() -> ThreadRng {
- ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.get()) }
-}
-
-impl Default for ThreadRng {
- fn default() -> ThreadRng {
- ::prelude::thread_rng()
- }
-}
-
-impl RngCore for ThreadRng {
- #[inline(always)]
- fn next_u32(&mut self) -> u32 {
- unsafe { (*self.rng).next_u32() }
- }
-
- #[inline(always)]
- fn next_u64(&mut self) -> u64 {
- unsafe { (*self.rng).next_u64() }
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- unsafe { (*self.rng).fill_bytes(dest) }
- }
-
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
- unsafe { (*self.rng).try_fill_bytes(dest) }
- }
-}
-
-impl CryptoRng for ThreadRng {}
-
-
-#[cfg(test)]
-mod test {
- #[test]
- fn test_thread_rng() {
- use Rng;
- let mut r = ::thread_rng();
- r.gen::<i32>();
- assert_eq!(r.gen_range(0, 1), 0);
- }
-}