Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
1
vendor/rdrand/.cargo-checksum.json
vendored
Normal file
1
vendor/rdrand/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"files":{"Cargo.toml":"f11ed31fc1b481c7d0e24251d7d60d34442f1d25747c887c49dc9fbad7e13e59","LICENSE":"00d7b0c8bf95ea93162fccc84da96b906b15add708eade04f7ee6141f7b53141","README.mkd":"93853e9e773543ed0d0cf696b5fb151b15bddc1ad9c39996c9eb11b20a3c7ff6","appveyor.yml":"f502d8a0755b98e904a40b07e8ba270bccd729045b03c24a7db0dfbb4047b515","benches/rdrand.rs":"f3684c360d43bc8a780868c0a3af43b20d56975e03575122cee87277787cc8d0","benches/rdseed.rs":"520097b15a3f11c0c6a357e6cd23add598be22f37839bbc71040b827b05d1064","benches/std.rs":"6a5b52b070b2a594e735aa617f16fc6a861e64534634cdb61801c3297444f6fe","src/changelog.rs":"644e08c06836ecdf94f9a43aec109e9f05f9d85f00541683c72d0d3893ff8d6a","src/lib.rs":"8fc306db8a304d24c28fcefaec1849c0d8bbca97417420af7b81449c352b2e92"},"package":"678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"}
|
28
vendor/rdrand/Cargo.toml
vendored
Normal file
28
vendor/rdrand/Cargo.toml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
authors = ["Simonas Kazlauskas <rdrand@kazlauskas.me>"]
|
||||
description = "An implementation of random number generator based on rdrand and rdseed instructions"
|
||||
documentation = "https://docs.rs/rdrand/0.4.0/"
|
||||
keywords = ["rand", "rdrand", "rdseed", "random"]
|
||||
license = "ISC"
|
||||
repository = "https://github.com/nagisa/rust_rdrand/"
|
||||
[dependencies.rand_core]
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
12
vendor/rdrand/LICENSE
vendored
Normal file
12
vendor/rdrand/LICENSE
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
Copyright © 2014, Simonas Kazlauskas
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without
|
||||
fee is hereby granted, provided that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
8
vendor/rdrand/README.mkd
vendored
Normal file
8
vendor/rdrand/README.mkd
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
An implementation of random number generators based on `rdrand` and `rdseed` instructions.
|
||||
|
||||
The random number generators provided by this crate are fairly slow (the latency for these
|
||||
instructions is pretty high), but provide high quality random bits. Caveat is: neither AMD’s
|
||||
nor Intel’s designs are public and therefore are not verifiable for lack of backdoors.
|
||||
|
||||
Unless you know what you are doing, use the random number generators provided by the `rand`
|
||||
crate (such as `EntropyRng`) instead.
|
27
vendor/rdrand/appveyor.yml
vendored
Normal file
27
vendor/rdrand/appveyor.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
environment:
|
||||
matrix:
|
||||
- TARGET: 1.30.0-x86_64-pc-windows-msvc
|
||||
- TARGET: 1.30.0-i686-pc-windows-msvc
|
||||
- TARGET: 1.30.0-x86_64-pc-windows-gnu
|
||||
- TARGET: 1.30.0-i686-pc-windows-gnu
|
||||
- TARGET: nightly-x86_64-pc-windows-msvc
|
||||
- TARGET: nightly-i686-pc-windows-msvc
|
||||
install:
|
||||
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust.exe"
|
||||
- ps: .\rust.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null
|
||||
- ps: $env:PATH="$env:PATH;C:\rust\bin"
|
||||
- rustc -vV
|
||||
- cargo -vV
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- cargo test
|
||||
- cargo test --no-default-features
|
||||
|
||||
for:
|
||||
- matrix:
|
||||
only:
|
||||
- TARGET: nightly-x86_64-pc-windows-msvc
|
||||
- TARGET: nightly-i686-pc-windows-msvc
|
||||
test_script:
|
||||
- cargo bench
|
49
vendor/rdrand/benches/rdrand.rs
vendored
Normal file
49
vendor/rdrand/benches/rdrand.rs
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#![feature(test)]
|
||||
extern crate rand_core;
|
||||
extern crate rdrand;
|
||||
extern crate test;
|
||||
|
||||
use rand_core::RngCore;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_u16(b : &mut Bencher) {
|
||||
if let Ok(gen) = rdrand::RdRand::new() {
|
||||
b.bytes = 2;
|
||||
b.iter(|| {
|
||||
gen.try_next_u16().unwrap()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_u32(b : &mut Bencher) {
|
||||
if let Ok(mut gen) = rdrand::RdRand::new() {
|
||||
b.bytes = 4;
|
||||
b.iter(|| {
|
||||
gen.next_u32()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_u64(b : &mut Bencher) {
|
||||
if let Ok(mut gen) = rdrand::RdRand::new() {
|
||||
b.bytes = 8;
|
||||
b.iter(|| {
|
||||
gen.next_u64()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fill(b : &mut Bencher) {
|
||||
if let Ok(mut gen) = rdrand::RdRand::new() {
|
||||
let mut buffer = [0; 128];
|
||||
b.bytes = 128;
|
||||
b.iter(|| {
|
||||
gen.fill_bytes(&mut buffer);
|
||||
buffer
|
||||
});
|
||||
}
|
||||
}
|
49
vendor/rdrand/benches/rdseed.rs
vendored
Normal file
49
vendor/rdrand/benches/rdseed.rs
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#![feature(test)]
|
||||
extern crate rand_core;
|
||||
extern crate rdrand;
|
||||
extern crate test;
|
||||
|
||||
use rand_core::RngCore;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_rdseed_u16(b : &mut Bencher) {
|
||||
if let Ok(gen) = rdrand::RdSeed::new() {
|
||||
b.bytes = 2;
|
||||
b.iter(|| {
|
||||
gen.try_next_u16().unwrap()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_rdseed_u32(b : &mut Bencher) {
|
||||
if let Ok(mut gen) = rdrand::RdSeed::new() {
|
||||
b.bytes = 4;
|
||||
b.iter(|| {
|
||||
gen.next_u32()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_rdseed_u64(b : &mut Bencher) {
|
||||
if let Ok(mut gen) = rdrand::RdSeed::new() {
|
||||
b.bytes = 8;
|
||||
b.iter(|| {
|
||||
gen.next_u64()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fill(b : &mut Bencher) {
|
||||
if let Ok(mut gen) = rdrand::RdSeed::new() {
|
||||
let mut buffer = [0; 128];
|
||||
b.bytes = 128;
|
||||
b.iter(|| {
|
||||
gen.fill_bytes(&mut buffer);
|
||||
buffer
|
||||
});
|
||||
}
|
||||
}
|
31
vendor/rdrand/benches/std.rs
vendored
Normal file
31
vendor/rdrand/benches/std.rs
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// #![feature(test)]
|
||||
// extern crate rand;
|
||||
// extern crate test;
|
||||
//
|
||||
// use test::Bencher;
|
||||
// use test::black_box;
|
||||
// use rand::Rng;
|
||||
// use rand::StdRng;
|
||||
// use rand::OsRng;
|
||||
//
|
||||
// // OsRng is supposed to be the default for crypto uses.
|
||||
// #[bench]
|
||||
// fn bench_osrng_u64(b : &mut Bencher) {
|
||||
// if let Ok(mut gen) = OsRng::new() {
|
||||
// b.bytes = 8;
|
||||
// b.iter(|| {
|
||||
// black_box(gen.next_u64());
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // StdRng is the default for everything else.
|
||||
// #[bench]
|
||||
// fn bench_stdrng_u64(b : &mut Bencher) {
|
||||
// if let Ok(mut gen) = StdRng::new() {
|
||||
// b.bytes = 8;
|
||||
// b.iter(|| {
|
||||
// gen.next_u64();
|
||||
// });
|
||||
// }
|
||||
// }
|
25
vendor/rdrand/src/changelog.rs
vendored
Normal file
25
vendor/rdrand/src/changelog.rs
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
//! Project changelog
|
||||
|
||||
/// ## Breaking changes
|
||||
///
|
||||
/// Crate gained an enabled-by-default `std` feature. If you relied on rdrand being `core`-able
|
||||
/// change your dependency to appear as such:
|
||||
///
|
||||
/// ```toml
|
||||
/// rdrand = { version = "0.4", default-features = false }
|
||||
/// ```
|
||||
///
|
||||
/// This is done so that an advantage of the common feature detection functionality could be
|
||||
/// employed by users that are not constrained by `core`. This functionality is faster, caches the
|
||||
/// results and is shared between all users of the functionality.
|
||||
///
|
||||
/// For `core` usage the feature detection has also been improved and will not be done if e.g.
|
||||
/// crate is built with `rdrand` instructions enabled globally.
|
||||
pub mod r0_4_0 {}
|
||||
|
||||
/// Crate now works on stable!
|
||||
///
|
||||
/// ## Breaking changes
|
||||
///
|
||||
/// * Updated to `rand_core = ^0.3`.
|
||||
pub mod r0_3_0 {}
|
472
vendor/rdrand/src/lib.rs
vendored
Normal file
472
vendor/rdrand/src/lib.rs
vendored
Normal file
@ -0,0 +1,472 @@
|
||||
// Copyright © 2014, Simonas Kazlauskas <rdrand@kazlauskas.me>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
|
||||
// fee is hereby granted, provided that the above copyright notice and this permission notice
|
||||
// appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
// OF THIS SOFTWARE.
|
||||
//! An implementation of random number generators based on `rdrand` and `rdseed` instructions.
|
||||
//!
|
||||
//! The random number generators provided by this crate are fairly slow (the latency for these
|
||||
//! instructions is pretty high), but provide high quality random bits. Caveat is: neither AMD’s
|
||||
//! nor Intel’s designs are public and therefore are not verifiable for lack of backdoors.
|
||||
//!
|
||||
//! Unless you know what you are doing, use the random number generators provided by the `rand`
|
||||
//! crate (such as `OsRng`) instead.
|
||||
//!
|
||||
//! Here are a measurements for select processor architectures. Check [Agner’s instruction tables]
|
||||
//! for up-to-date listings.
|
||||
//!
|
||||
//! <table>
|
||||
//! <tr>
|
||||
//! <th>Architecture</th>
|
||||
//! <th colspan="3">Latency (cycles)</th>
|
||||
//! <th>Maximum throughput (per core)</th>
|
||||
//! </tr>
|
||||
//! <tr>
|
||||
//! <td></td>
|
||||
//! <td>u16</td>
|
||||
//! <td>u32</td>
|
||||
//! <td>u64</td>
|
||||
//! <td></td>
|
||||
//! </tr>
|
||||
//! <tr>
|
||||
//! <td>AMD Ryzen</td>
|
||||
//! <td>~1200</td>
|
||||
//! <td>~1200</td>
|
||||
//! <td>~2500</td>
|
||||
//! <td>~12MB/s @ 3.7GHz</td>
|
||||
//! </tr>
|
||||
//! <tr>
|
||||
//! <td>Intel Skylake</td>
|
||||
//! <td>460</td>
|
||||
//! <td>460</td>
|
||||
//! <td>460</td>
|
||||
//! <td>~72MB/s @ 4.2GHz</td>
|
||||
//! </tr>
|
||||
//! <tr>
|
||||
//! <td>Intel Haswell</td>
|
||||
//! <td>320</td>
|
||||
//! <td>320</td>
|
||||
//! <td>320</td>
|
||||
//! <td>~110MB/s @ 4.4GHz</td>
|
||||
//! </tr>
|
||||
//! </table>
|
||||
//!
|
||||
//! [Agner’s instruction tables]: http://agner.org/optimize/
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate rand_core;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
|
||||
pub mod changelog;
|
||||
|
||||
use rand_core::{RngCore, CryptoRng, Error, ErrorKind};
|
||||
use core::slice;
|
||||
|
||||
const RETRY_LIMIT: u8 = 127;
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
pub(crate) fn busy_loop_fail() -> ! {
|
||||
panic!("hardware generator failure");
|
||||
}
|
||||
|
||||
/// A cryptographically secure statistically uniform, non-periodic and non-deterministic random bit
|
||||
/// generator.
|
||||
///
|
||||
/// Note that this generator may be implemented using a deterministic algorithm that is reseeded
|
||||
/// routinely from a non-deterministic entropy source to achieve the desirable properties.
|
||||
///
|
||||
/// This generator is a viable replacement to any generator, however, since nobody has audited
|
||||
/// Intel or AMD hardware yet, the usual disclaimers as to their suitability apply.
|
||||
///
|
||||
/// It is potentially faster than `OsRng`, but is only supported on more recent Intel (Ivy Bridge
|
||||
/// and later) and AMD (Ryzen and later) processors.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RdRand(());
|
||||
|
||||
/// A cryptographically secure non-deterministic random bit generator.
|
||||
///
|
||||
/// This generator produces high-entropy output and is suited to seed other pseudo-random
|
||||
/// generators.
|
||||
///
|
||||
/// This instruction currently is only available in Intel Broadwell (and later) and AMD Ryzen
|
||||
/// processors.
|
||||
///
|
||||
/// This generator is not intended for general random number generation purposes and should be used
|
||||
/// to seed other generators implementing [rand_core::SeedableRng].
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RdSeed(());
|
||||
|
||||
impl CryptoRng for RdRand {}
|
||||
impl CryptoRng for RdSeed {}
|
||||
|
||||
mod arch {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use core::arch::x86_64::*;
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub use core::arch::x86::*;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub(crate) unsafe fn _rdrand64_step(dest: &mut u64) -> i32 {
|
||||
let mut ret1: u32 = ::core::mem::uninitialized();
|
||||
let mut ret2: u32 = ::core::mem::uninitialized();
|
||||
if _rdrand32_step(&mut ret1) != 0 && _rdrand32_step(&mut ret2) != 0 {
|
||||
*dest = (ret1 as u64) << 32 | (ret2 as u64);
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub(crate) unsafe fn _rdseed64_step(dest: &mut u64) -> i32 {
|
||||
let mut ret1: u32 = ::core::mem::uninitialized();
|
||||
let mut ret2: u32 = ::core::mem::uninitialized();
|
||||
if _rdseed32_step(&mut ret1) != 0 && _rdseed32_step(&mut ret2) != 0 {
|
||||
*dest = (ret1 as u64) << 32 | (ret2 as u64);
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
macro_rules! is_x86_feature_detected {
|
||||
("rdrand") => {{
|
||||
if cfg!(target_feature="rdrand") {
|
||||
true
|
||||
} else if cfg!(target_env = "sgx") {
|
||||
false
|
||||
} else {
|
||||
const FLAG : u32 = 1 << 30;
|
||||
unsafe { ::arch::__cpuid(1).ecx & FLAG == FLAG }
|
||||
}
|
||||
}};
|
||||
("rdseed") => {{
|
||||
if cfg!(target_feature = "rdseed") {
|
||||
true
|
||||
} else if cfg!(target_env = "sgx") {
|
||||
false
|
||||
} else {
|
||||
const FLAG : u32 = 1 << 18;
|
||||
unsafe { ::arch::__cpuid(7).ebx & FLAG == FLAG }
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! loop_rand {
|
||||
($el: ty, $step: path) => { {
|
||||
let mut idx = 0;
|
||||
loop {
|
||||
let mut el: $el = ::core::mem::uninitialized();
|
||||
if $step(&mut el) != 0 {
|
||||
break Some(el);
|
||||
} else if idx == RETRY_LIMIT {
|
||||
break None;
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
macro_rules! impl_rand {
|
||||
($gen:ident, $feat:tt, $step16: path, $step32:path, $step64:path,
|
||||
maxstep = $maxstep:path, maxty = $maxty: ty) => {
|
||||
impl $gen {
|
||||
/// Create a new instance of the random number generator.
|
||||
///
|
||||
/// This constructor checks whether the CPU the program is running on supports the
|
||||
/// instruction necessary for this generator to operate. If the instruction is not
|
||||
/// supported, an error is returned.
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
if is_x86_feature_detected!($feat) {
|
||||
Ok($gen(()))
|
||||
} else {
|
||||
Err(Error::new(rand_core::ErrorKind::Unavailable,
|
||||
"the instruction is not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a single random `u16` value.
|
||||
///
|
||||
/// The underlying instruction may fail for variety reasons (such as actual hardware
|
||||
/// failure or exhausted entropy), however the exact reason for the failure is not
|
||||
/// usually exposed.
|
||||
///
|
||||
/// This method will retry calling the instruction a few times, however if all the
|
||||
/// attempts fail, it will return `None`.
|
||||
///
|
||||
/// In case `None` is returned, the caller should assume that an non-recoverable
|
||||
/// hardware failure has occured and use another random number genrator instead.
|
||||
#[inline(always)]
|
||||
pub fn try_next_u16(&self) -> Option<u16> {
|
||||
#[target_feature(enable = $feat)]
|
||||
unsafe fn imp()
|
||||
-> Option<u16> {
|
||||
loop_rand!(u16, $step16)
|
||||
}
|
||||
unsafe { imp() }
|
||||
}
|
||||
|
||||
/// Generate a single random `u32` value.
|
||||
///
|
||||
/// The underlying instruction may fail for variety reasons (such as actual hardware
|
||||
/// failure or exhausted entropy), however the exact reason for the failure is not
|
||||
/// usually exposed.
|
||||
///
|
||||
/// This method will retry calling the instruction a few times, however if all the
|
||||
/// attempts fail, it will return `None`.
|
||||
///
|
||||
/// In case `None` is returned, the caller should assume that an non-recoverable
|
||||
/// hardware failure has occured and use another random number genrator instead.
|
||||
#[inline(always)]
|
||||
pub fn try_next_u32(&self) -> Option<u32> {
|
||||
#[target_feature(enable = $feat)]
|
||||
unsafe fn imp()
|
||||
-> Option<u32> {
|
||||
loop_rand!(u32, $step32)
|
||||
}
|
||||
unsafe { imp() }
|
||||
}
|
||||
|
||||
/// Generate a single random `u64` value.
|
||||
///
|
||||
/// The underlying instruction may fail for variety reasons (such as actual hardware
|
||||
/// failure or exhausted entropy), however the exact reason for the failure is not
|
||||
/// usually exposed.
|
||||
///
|
||||
/// This method will retry calling the instruction a few times, however if all the
|
||||
/// attempts fail, it will return `None`.
|
||||
///
|
||||
/// In case `None` is returned, the caller should assume that an non-recoverable
|
||||
/// hardware failure has occured and use another random number genrator instead.
|
||||
///
|
||||
/// Note, that on 32-bit targets, there’s no underlying instruction to generate a
|
||||
/// 64-bit number, so it is emulated with the 32-bit version of the instruction.
|
||||
#[inline(always)]
|
||||
pub fn try_next_u64(&self) -> Option<u64> {
|
||||
#[target_feature(enable = $feat)]
|
||||
unsafe fn imp()
|
||||
-> Option<u64> {
|
||||
loop_rand!(u64, $step64)
|
||||
}
|
||||
unsafe { imp() }
|
||||
}
|
||||
}
|
||||
|
||||
impl RngCore for $gen {
|
||||
/// Generate a single random `u32` value.
|
||||
///
|
||||
/// The underlying instruction may fail for variety reasons (such as actual hardware
|
||||
/// failure or exhausted entropy), however the exact reason for the failure is not
|
||||
/// usually exposed.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// This method will retry calling the instruction a few times, however if all the
|
||||
/// attempts fail, it will `panic`.
|
||||
///
|
||||
/// In case `panic` occurs, the caller should assume that an non-recoverable
|
||||
/// hardware failure has occured and use another random number genrator instead.
|
||||
#[inline(always)]
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
if let Some(result) = self.try_next_u32() {
|
||||
result
|
||||
} else {
|
||||
busy_loop_fail()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a single random `u64` value.
|
||||
///
|
||||
/// The underlying instruction may fail for variety reasons (such as actual hardware
|
||||
/// failure or exhausted entropy), however the exact reason for the failure is not
|
||||
/// usually exposed.
|
||||
///
|
||||
/// Note, that on 32-bit targets, there’s no underlying instruction to generate a
|
||||
/// 64-bit number, so it is emulated with the 32-bit version of the instruction.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// This method will retry calling the instruction a few times, however if all the
|
||||
/// attempts fail, it will `panic`.
|
||||
///
|
||||
/// In case `panic` occurs, the caller should assume that an non-recoverable
|
||||
/// hardware failure has occured and use another random number genrator instead.
|
||||
#[inline(always)]
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
if let Some(result) = self.try_next_u64() {
|
||||
result
|
||||
} else {
|
||||
busy_loop_fail()
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill a buffer `dest` with random data.
|
||||
///
|
||||
/// See `try_fill_bytes` for a more extensive documentation.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// This method will panic any time `try_fill_bytes` would return an error.
|
||||
#[inline(always)]
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
if let Err(_) = self.try_fill_bytes(dest) {
|
||||
busy_loop_fail()
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill a buffer `dest` with random data.
|
||||
///
|
||||
/// This method will use the most appropriate variant of the instruction available on
|
||||
/// the machine to achieve the greatest single-core throughput, however it has a
|
||||
/// slightly higher setup cost than the plain `next_u32` or `next_u64` methods.
|
||||
///
|
||||
/// The underlying instruction may fail for variety reasons (such as actual hardware
|
||||
/// failure or exhausted entropy), however the exact reason for the failure is not
|
||||
/// usually exposed.
|
||||
///
|
||||
/// This method will retry calling the instruction a few times, however if all the
|
||||
/// attempts fail, it will return an error.
|
||||
///
|
||||
/// If an error is returned, the caller should assume that an non-recoverable hardware
|
||||
/// failure has occured and use another random number genrator instead.
|
||||
#[inline(always)]
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8])
|
||||
-> Result<(), Error> {
|
||||
#[target_feature(enable = $feat)]
|
||||
unsafe fn imp(dest: &mut [u8])
|
||||
-> Result<(), Error>
|
||||
{
|
||||
unsafe fn imp_less_fast(mut dest: &mut [u8], word: &mut $maxty,
|
||||
buffer: &mut &[u8])
|
||||
-> Result<(), Error>
|
||||
{
|
||||
while !dest.is_empty() {
|
||||
if buffer.is_empty() {
|
||||
if let Some(w) = loop_rand!($maxty, $maxstep) {
|
||||
*word = w;
|
||||
*buffer = slice::from_raw_parts(
|
||||
word as *const _ as *const u8,
|
||||
::core::mem::size_of::<$maxty>()
|
||||
);
|
||||
} else {
|
||||
return Err(Error::new(ErrorKind::Unexpected,
|
||||
"hardware generator failure"));
|
||||
}
|
||||
}
|
||||
|
||||
let len = dest.len().min(buffer.len());
|
||||
let (copy_src, leftover) = buffer.split_at(len);
|
||||
let (copy_dest, dest_leftover) = { dest }.split_at_mut(len);
|
||||
*buffer = leftover;
|
||||
dest = dest_leftover;
|
||||
::core::ptr::copy_nonoverlapping(
|
||||
copy_src.as_ptr(), copy_dest.as_mut_ptr(), len
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let destlen = dest.len();
|
||||
if destlen > ::core::mem::size_of::<$maxty>() {
|
||||
let (left, mid, right) = dest.align_to_mut();
|
||||
let mut word = 0;
|
||||
let mut buffer: &[u8] = &[];
|
||||
|
||||
for el in mid {
|
||||
if let Some(val) = loop_rand!($maxty, $maxstep) {
|
||||
*el = val;
|
||||
} else {
|
||||
return Err(Error::new(ErrorKind::Unexpected,
|
||||
"hardware generator failure"));
|
||||
}
|
||||
}
|
||||
|
||||
imp_less_fast(left, &mut word, &mut buffer)?;
|
||||
imp_less_fast(right, &mut word, &mut buffer)
|
||||
} else {
|
||||
let mut word = 0;
|
||||
let mut buffer: &[u8] = &[];
|
||||
imp_less_fast(dest, &mut word, &mut buffer)
|
||||
}
|
||||
}
|
||||
unsafe { imp(dest) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl_rand!(RdRand, "rdrand",
|
||||
::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
|
||||
maxstep = ::arch::_rdrand64_step, maxty = u64);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl_rand!(RdSeed, "rdseed",
|
||||
::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
|
||||
maxstep = ::arch::_rdseed64_step, maxty = u64);
|
||||
#[cfg(target_arch = "x86")]
|
||||
impl_rand!(RdRand, "rdrand",
|
||||
::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
|
||||
maxstep = ::arch::_rdrand32_step, maxty = u32);
|
||||
#[cfg(target_arch = "x86")]
|
||||
impl_rand!(RdSeed, "rdseed",
|
||||
::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
|
||||
maxstep = ::arch::_rdseed32_step, maxty = u32);
|
||||
|
||||
#[test]
|
||||
fn rdrand_works() {
|
||||
let _ = RdRand::new().map(|mut r| {
|
||||
r.next_u32();
|
||||
r.next_u64();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fill_fills_all_bytes() {
|
||||
let _ = RdRand::new().map(|mut r| {
|
||||
let mut peach;
|
||||
let mut banana;
|
||||
let mut start = 0;
|
||||
let mut end = 128;
|
||||
'outer: while start < end {
|
||||
banana = [0; 128];
|
||||
for _ in 0..512 {
|
||||
peach = [0; 128];
|
||||
r.fill_bytes(&mut peach[start..end]);
|
||||
for (b, p) in banana.iter_mut().zip(peach.iter()) {
|
||||
*b = *b | *p;
|
||||
}
|
||||
if (&banana[start..end]).iter().all(|x| *x != 0) {
|
||||
assert!(banana[..start].iter().all(|x| *x == 0), "all other values must be 0");
|
||||
assert!(banana[end..].iter().all(|x| *x == 0), "all other values must be 0");
|
||||
if start < 17 {
|
||||
start += 1;
|
||||
} else {
|
||||
end -= 3;
|
||||
}
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
panic!("wow, we broke it? {} {} {:?}", start, end, &banana[..])
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdseed_works() {
|
||||
let _ = RdSeed::new().map(|mut r| {
|
||||
r.next_u32();
|
||||
r.next_u64();
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user