aboutsummaryrefslogtreecommitdiff
path: root/rand/rand_jitter
diff options
context:
space:
mode:
Diffstat (limited to 'rand/rand_jitter')
-rw-r--r--rand/rand_jitter/CHANGELOG.md32
-rw-r--r--rand/rand_jitter/COPYRIGHT12
-rw-r--r--rand/rand_jitter/Cargo.toml30
-rw-r--r--rand/rand_jitter/LICENSE-APACHE201
-rw-r--r--rand/rand_jitter/LICENSE-MIT26
-rw-r--r--rand/rand_jitter/README.md119
-rw-r--r--rand/rand_jitter/benches/mod.rs17
-rw-r--r--rand/rand_jitter/src/error.rs77
-rw-r--r--rand/rand_jitter/src/lib.rs750
-rw-r--r--rand/rand_jitter/src/platform.rs44
-rw-r--r--rand/rand_jitter/tests/mod.rs28
11 files changed, 0 insertions, 1336 deletions
diff --git a/rand/rand_jitter/CHANGELOG.md b/rand/rand_jitter/CHANGELOG.md
deleted file mode 100644
index 9f4bb7e..0000000
--- a/rand/rand_jitter/CHANGELOG.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Changelog
-All notable changes to this project will be documented in this file.
-
-The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
-and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-
-## [0.2.1] - 2019-08-16
-### Changed
-- `TimerError` changed to `repr(u32)` (#864)
-- `TimerError` enum values all increased by `1<<30` to match new `rand_core::Error` range (#864)
-
-## [0.2.0] - 2019-06-06
-- Bump `rand_core` version
-- Support new `Error` type in `rand_core` 0.5
-- Remove CryptoRng trait bound (#699, #814)
-- Enable doc-testing of README
-
-## [0.1.4] - 2019-05-02
-- Change error conversion code to partially fix #738
-
-## [0.1.3] - 2019-02-05
-- Use libc in `no_std` mode to fix #723
-
-## [0.1.2] - 2019-01-31
-- Fix for older rustc compilers on Windows (#722)
-
-## [0.1.1] - 2019-01-29
-- Fix for older rustc compilers on Mac OSX / iOS (#720)
-- Misc. doc fixes
-
-## [0.1.0] - 2019-01-24
-Initial release.
diff --git a/rand/rand_jitter/COPYRIGHT b/rand/rand_jitter/COPYRIGHT
deleted file mode 100644
index 468d907..0000000
--- a/rand/rand_jitter/COPYRIGHT
+++ /dev/null
@@ -1,12 +0,0 @@
-Copyrights in the Rand project are retained by their contributors. No
-copyright assignment is required to contribute to the Rand project.
-
-For full authorship information, see the version control history.
-
-Except as otherwise noted (below and/or in individual files), Rand is
-licensed under the Apache License, Version 2.0 <LICENSE-APACHE> or
-<http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-<LICENSE-MIT> or <http://opensource.org/licenses/MIT>, at your option.
-
-The Rand project includes code from the Rust project
-published under these same licenses.
diff --git a/rand/rand_jitter/Cargo.toml b/rand/rand_jitter/Cargo.toml
deleted file mode 100644
index 5b7e3c3..0000000
--- a/rand/rand_jitter/Cargo.toml
+++ /dev/null
@@ -1,30 +0,0 @@
-[package]
-name = "rand_jitter"
-version = "0.2.1"
-authors = ["The Rand Project Developers"]
-license = "MIT OR Apache-2.0"
-readme = "README.md"
-repository = "https://github.com/rust-random/rand"
-documentation = "https://docs.rs/rand_jitter"
-description = "Random number generator based on timing jitter"
-keywords = ["random", "rng", "os"]
-edition = "2018"
-
-[badges]
-travis-ci = { repository = "rust-random/rand" }
-appveyor = { repository = "rust-random/rand" }
-
-[dependencies]
-rand_core = { path = "../rand_core", version = "0.5" }
-log = { version = "0.4", optional = true }
-
-[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
-# We don't need the 'use_std' feature and depending on it causes
-# issues due to: https://github.com/rust-lang/cargo/issues/1197
-libc = { version = "0.2", default_features = false }
-
-[target.'cfg(target_os = "windows")'.dependencies]
-winapi = { version = "0.3", features = ["profileapi"] }
-
-[features]
-std = ["rand_core/std"]
diff --git a/rand/rand_jitter/LICENSE-APACHE b/rand/rand_jitter/LICENSE-APACHE
deleted file mode 100644
index 17d7468..0000000
--- a/rand/rand_jitter/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- https://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/rand/rand_jitter/LICENSE-MIT b/rand/rand_jitter/LICENSE-MIT
deleted file mode 100644
index d93b5ba..0000000
--- a/rand/rand_jitter/LICENSE-MIT
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2018 Developers of the Rand project
-Copyright (c) 2014 The Rust Project Developers
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/rand/rand_jitter/README.md b/rand/rand_jitter/README.md
deleted file mode 100644
index 2091d6c..0000000
--- a/rand/rand_jitter/README.md
+++ /dev/null
@@ -1,119 +0,0 @@
-# rand_jitter
-[![Build Status](https://travis-ci.org/rust-random/rand.svg?branch=master)](https://travis-ci.org/rust-random/rand)
-[![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-random/rand?svg=true)](https://ci.appveyor.com/project/rust-random/rand)
-[![Latest version](https://img.shields.io/crates/v/rand_jitter.svg)](https://crates.io/crates/rand_jitter)
-[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
-[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_jitter)
-[![API](https://docs.rs/rand_jitter/badge.svg)](https://docs.rs/rand_jitter)
-[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
-
-Non-physical true random number generator based on timing jitter.
-
-Note that this RNG is not suited for use cases where cryptographic security is
-required (also see [this
-discussion](https://github.com/rust-random/rand/issues/699)).
-
-This crate depends on [rand_core](https://crates.io/crates/rand_core) and is
-part of the [Rand project](https://github.com/rust-random/rand).
-
-This crate aims to support all of Rust's `std` platforms with a system-provided
-entropy source. Unlike other Rand crates, this crate does not support `no_std`
-(handling this gracefully is a current discussion topic).
-
-Links:
-
-- [API documentation (master)](https://rust-random.github.io/rand/rand_jitter)
-- [API documentation (docs.rs)](https://docs.rs/rand_jitter)
-- [Changelog](https://github.com/rust-random/rand/blob/master/rand_jitter/CHANGELOG.md)
-
-## Features
-
-This crate has optional `std` support which is *disabled by default*;
-this feature is required to provide the `JitterRng::new` function;
-without `std` support a timer must be supplied via `JitterRng::new_with_timer`.
-
-## 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:
-
-```rust,no_run
-use rand_jitter::JitterRng;
-
-use std::error::Error;
-use std::fs::File;
-use std::io::Write;
-
-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
-}
-
-fn main() -> Result<(), Box<dyn Error>> {
- let mut rng = JitterRng::new_with_timer(get_nstime);
-
- // 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(())
-}
-```
-
-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 noise 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>
- ```
-
-## License
-
-`rand_jitter` is distributed under the terms of both the MIT license and the
-Apache License (Version 2.0).
-
-See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and
-[COPYRIGHT](COPYRIGHT) for details.
diff --git a/rand/rand_jitter/benches/mod.rs b/rand/rand_jitter/benches/mod.rs
deleted file mode 100644
index bf7c8a2..0000000
--- a/rand/rand_jitter/benches/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(test)]
-#![cfg(std)]
-
-use test::Bencher;
-use rand_jitter::rand_core::RngCore;
-
-#[bench]
-fn bench_add_two(b: &mut Bencher) {
- let mut rng = rand_jitter::JitterRng::new().unwrap();
- let mut buf = [0u8; 1024];
- b.iter(|| {
- rng.fill_bytes(&mut buf[..]);
- test::black_box(&buf);
- });
- b.bytes = buf.len() as u64;
-}
-
diff --git a/rand/rand_jitter/src/error.rs b/rand/rand_jitter/src/error.rs
deleted file mode 100644
index b54fffa..0000000
--- a/rand/rand_jitter/src/error.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-// Copyright 2013-2015 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.
-
-use rand_core::Error;
-use core::fmt;
-
-/// Base code for all `JitterRng` errors
-const ERROR_BASE: u32 = 0xAE53_0400;
-
-/// An error that can occur when [`JitterRng::test_timer`] fails.
-///
-/// All variants have a value of 0xAE530400 = 2924676096 plus a small
-/// increment (1 through 5).
-///
-/// [`JitterRng::test_timer`]: crate::JitterRng::test_timer
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[repr(u32)]
-pub enum TimerError {
- /// No timer available.
- NoTimer = ERROR_BASE + 1,
- /// Timer too coarse to use as an entropy source.
- CoarseTimer = ERROR_BASE + 2,
- /// Timer is not monotonically increasing.
- NotMonotonic = ERROR_BASE + 3,
- /// Variations of deltas of time too small.
- TinyVariantions = ERROR_BASE + 4,
- /// Too many stuck results (indicating no added entropy).
- TooManyStuck = ERROR_BASE + 5,
- #[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.
- #[cfg(feature = "std")] {
- Error::new(err)
- }
- #[cfg(not(feature = "std"))] {
- Error::from(core::num::NonZeroU32::new(err as u32).unwrap())
- }
- }
-}
-
diff --git a/rand/rand_jitter/src/lib.rs b/rand/rand_jitter/src/lib.rs
deleted file mode 100644
index 49c53e6..0000000
--- a/rand/rand_jitter/src/lib.rs
+++ /dev/null
@@ -1,750 +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 that this RNG is not suited for use cases where cryptographic security is
-//! required (also see this [discussion]).
-//!
-//! 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 it 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.
-//!
-//! `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 [`JitterRng::new_with_timer`].
-//!
-//! This implementation is based on [Jitterentropy] 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. It is also unavailable
-//! with disabled `std` feature.
-//!
-//! [Jitterentropy]: http://www.chronox.de/jent.html
-//! [discussion]: https://github.com/rust-random/rand/issues/699
-
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
- html_favicon_url = "https://www.rust-lang.org/favicon.ico",
- html_root_url = "https://rust-random.github.io/rand/")]
-
-#![deny(missing_docs)]
-#![deny(missing_debug_implementations)]
-#![doc(test(attr(allow(unused_variables), deny(warnings))))]
-
-// 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.
-#![no_std]
-#[cfg(feature = "std")]
-extern crate std;
-
-pub use rand_core;
-
-// Coming from https://crates.io/crates/doc-comment
-#[cfg(test)]
-macro_rules! doc_comment {
- ($x:expr) => {
- #[doc = $x]
- extern {}
- };
-}
-
-#[cfg(test)]
-doc_comment!(include_str!("../README.md"));
-
-#[allow(unused)]
-macro_rules! trace { ($($x:tt)*) => (
- #[cfg(feature = "log")] {
- log::trace!($($x)*)
- }
-) }
-#[allow(unused)]
-macro_rules! debug { ($($x:tt)*) => (
- #[cfg(feature = "log")] {
- log::debug!($($x)*)
- }
-) }
-#[allow(unused)]
-macro_rules! info { ($($x:tt)*) => (
- #[cfg(feature = "log")] {
- log::info!($($x)*)
- }
-) }
-#[allow(unused)]
-macro_rules! warn { ($($x:tt)*) => (
- #[cfg(feature = "log")] {
- log::warn!($($x)*)
- }
-) }
-#[allow(unused)]
-macro_rules! error { ($($x:tt)*) => (
- #[cfg(feature = "log")] {
- log::error!($($x)*)
- }
-) }
-
-#[cfg(feature = "std")]
-mod platform;
-mod error;
-
-use rand_core::{RngCore, Error, impls};
-pub use crate::error::TimerError;
-
-use core::{fmt, mem, ptr};
-#[cfg(feature = "std")]
-use std::sync::atomic::{AtomicUsize, 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.
-///
-/// Note that this RNG is not suitable for use cases where cryptographic
-/// security is required.
-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,
- }
- }
-}
-
-// Initialise to zero; must be positive
-#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
-static JITTER_ROUNDS: AtomicUsize = AtomicUsize::new(0);
-
-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> {
- if cfg!(target_arch = "wasm32") {
- return Err(TimerError::NoTimer);
- }
- 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_jitter::rand_core::{RngCore, Error};
- /// use rand_jitter::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.next_u64();
- ///
- /// // Ready for use
- /// let v: u64 = rng.next_u64();
- /// # Ok(())
- /// # }
- ///
- /// # let _ = try_inner();
- /// ```
- ///
- /// [`test_timer`]: JitterRng::test_timer
- /// [`set_rounds`]: JitterRng::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`]: JitterRng::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 successful, 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.
- 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 this crate's README 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
- }
-}
-
-// 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))
- }
-}
diff --git a/rand/rand_jitter/src/platform.rs b/rand/rand_jitter/src/platform.rs
deleted file mode 100644
index 8e3d0fb..0000000
--- a/rand/rand_jitter/src/platform.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-// Copyright 2013-2015 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.
-
-#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
-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 {
- use 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 {
- use winapi;
-
- unsafe {
- let mut t = super::mem::zeroed();
- winapi::um::profileapi::QueryPerformanceCounter(&mut t);
- *t.QuadPart() as u64
- }
-}
diff --git a/rand/rand_jitter/tests/mod.rs b/rand/rand_jitter/tests/mod.rs
deleted file mode 100644
index 961dc27..0000000
--- a/rand/rand_jitter/tests/mod.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use rand_jitter::JitterRng;
-#[cfg(feature = "std")]
-use rand_core::RngCore;
-
-#[cfg(feature = "std")]
-#[test]
-fn test_jitter_init() {
- // 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());
-}
-