Skip to content

Commit

Permalink
Merge pull request #47 from dhardy/work
Browse files Browse the repository at this point in the history
rand_jitter v0.4, platform_ns_time feature, MSRV=1.51, rustfmt
  • Loading branch information
dhardy committed Dec 8, 2023
2 parents 0f25f7e + 8b94537 commit ac0cf3c
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 55 deletions.
31 changes: 27 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ jobs:
target: x86_64-pc-windows-msvc
toolchain: beta
# Test both windows-gnu and windows-msvc; use beta rust on one
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
toolchain: 1.36.0 # MSRV
- os: ubuntu-latest
deps: sudo apt-get update ; sudo apt install gcc-multilib
target: i686-unknown-linux-gnu
Expand Down Expand Up @@ -85,12 +82,38 @@ jobs:
cargo test --target ${{ matrix.target }} --manifest-path rand_xoshiro/Cargo.toml --all-features
cargo test --target ${{ matrix.target }} --manifest-path rand_jitter/Cargo.toml --all-features
msrv:
name: MSRV for rand_isaac / rand_xorshift / rand_xoshiro
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.56.0 # older versions may work (untested)
- run: cd rand_isaac && cargo test --all-features
- run: cd rand_xorshift && cargo test --all-features
- run: cd rand_xoshiro && cargo test --all-features

msrv_hc:
name: MSRV for rand_hc
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.36.0
- run: cd rand_hc && cargo test --all-features

msrv_jitter:
name: MSRV for rand_jitter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.51.0
- run: cd rand_jitter && cargo test --features std

test-cross:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [mips-unknown-linux-gnu]
target: [powerpc-unknown-linux-gnu]
toolchain: [stable]

steps:
Expand Down
8 changes: 7 additions & 1 deletion rand_jitter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ 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.4.0] - 2023-11-20
### Changed
- Update to `rand_core` v0.6
- Bump MSRV to 1.51
- Use return-position impl trait to fix `JitterRng::new` (#16)

## [0.3.0] - 2020-09-07
### Changed
- `JitterRng::new_with_timer` accepts closures
- `JitterRng::new_with_timer` accepts closures (this breaks `JitterRng::new`)

## [0.2.1] - 2019-08-16
### Changed
Expand Down
3 changes: 2 additions & 1 deletion rand_jitter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rand_jitter"
version = "0.3.0"
version = "0.4.0"
authors = ["The Rand Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand All @@ -9,6 +9,7 @@ documentation = "https://docs.rs/rand_jitter"
description = "Random number generator based on timing jitter"
keywords = ["random", "rng", "os"]
edition = "2018"
rust-version = "1.51"

[dependencies]
rand_core = { version = "0.6" }
Expand Down
2 changes: 1 addition & 1 deletion rand_jitter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![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.36+-lightgray.svg)](https://github.com/rust-random/rngs#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.51-lightgray.svg)](https://github.com/rust-random/rngs#rust-version-requirements)

Non-physical true random number generator based on timing jitter.

Expand Down
3 changes: 1 addition & 2 deletions rand_jitter/benches/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#![feature(test)]
#![cfg(std)]

use test::Bencher;
use rand_jitter::rand_core::RngCore;
use test::Bencher;

#[bench]
fn bench_add_two(b: &mut Bencher) {
Expand All @@ -14,4 +14,3 @@ fn bench_add_two(b: &mut Bencher) {
});
b.bytes = buf.len() as u64;
}

11 changes: 6 additions & 5 deletions rand_jitter/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rand_core::Error;
use core::fmt;
use rand_core::Error;

/// 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).
///
Expand Down Expand Up @@ -68,12 +68,13 @@ 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")] {
#[cfg(feature = "std")]
{
Error::new(err)
}
#[cfg(not(feature = "std"))] {
#[cfg(not(feature = "std"))]
{
Error::from(core::num::NonZeroU32::new(err as u32).unwrap())
}
}
}

81 changes: 51 additions & 30 deletions rand_jitter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@
//! [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/")]

#![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
Expand All @@ -64,7 +64,7 @@ pub use rand_core;
macro_rules! doc_comment {
($x:expr) => {
#[doc = $x]
extern {}
fn _doc_comment() {}
};
}

Expand Down Expand Up @@ -102,12 +102,12 @@ macro_rules! error { ($($x:tt)*) => (
}
) }

mod error;
#[cfg(feature = "std")]
mod platform;
mod error;

use rand_core::{RngCore, Error, impls};
pub use crate::error::TimerError;
use rand_core::{impls, Error, RngCore};

use core::{fmt, mem, ptr};
#[cfg(feature = "std")]
Expand Down Expand Up @@ -191,7 +191,9 @@ impl<F> fmt::Debug for JitterRng<F> {
}

impl<F> Clone for JitterRng<F>
where F: Clone {
where
F: Clone,
{
fn clone(&self) -> JitterRng<F> {
JitterRng {
data: self.data,
Expand All @@ -209,9 +211,7 @@ where F: Clone {
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
static JITTER_ROUNDS: AtomicUsize = AtomicUsize::new(0);

impl<F> JitterRng<F>
where F: Fn() -> u64 + Send + Sync {
/* FIXME: this method is broken - see #16
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.
Expand All @@ -220,7 +220,7 @@ where F: Fn() -> u64 + Send + Sync {
/// 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<fn() -> u64>, TimerError> {
pub fn new() -> Result<JitterRng<impl Fn() -> u64 + Send + Sync>, TimerError> {
if cfg!(target_arch = "wasm32") {
return Err(TimerError::NoTimer);
}
Expand All @@ -239,8 +239,12 @@ where F: Fn() -> u64 + Send + Sync {
state.gen_entropy();
Ok(state)
}
*/
}

impl<F> JitterRng<F>
where
F: Fn() -> u64 + Send + Sync,
{
/// Create a new `JitterRng`.
/// A custom timer can be supplied, making it possible to use `JitterRng` in
/// `no_std` environments.
Expand Down Expand Up @@ -352,7 +356,7 @@ where F: Fn() -> u64 + Send + Sync {
// 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{
fn lfsr(mut data: u64, time: u64) -> u64 {
for i in 1..65 {
let mut tmp = time << (64 - i);
tmp >>= 64 - 1;
Expand Down Expand Up @@ -382,7 +386,9 @@ where F: Fn() -> u64 + Send + Sync {
// 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) };
if var_rounds {
lfsr_loop_cnt = self.random_loop_cnt(4)
};

let mut throw_away: u64 = 0;
for _ in 0..lfsr_loop_cnt {
Expand Down Expand Up @@ -412,7 +418,9 @@ where F: Fn() -> u64 + Send + Sync {
#[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) };
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 {
Expand Down Expand Up @@ -454,7 +462,9 @@ where F: Fn() -> u64 + Send + Sync {

// Check whether we have a stuck measurement (i.e. does the last
// measurement holds entropy?).
if ec.stuck(current_delta) { return None };
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
Expand Down Expand Up @@ -599,21 +609,29 @@ where F: Fn() -> u64 + Send + Sync {
// 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 i < CLEARCACHE {
continue;
}

if ec.stuck(delta) { count_stuck += 1; }
if ec.stuck(delta) {
count_stuck += 1;
}

// Test whether we have an increasing timer.
if time2 <= time { time_backwards += 1; }
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; }
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;
delta_sum += (delta - old_delta).unsigned_abs() as u64;
old_delta = delta;
}

Expand Down Expand Up @@ -674,14 +692,15 @@ where F: Fn() -> u64 + Send + Sync {
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)
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];
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])
}
}
Expand Down Expand Up @@ -721,8 +740,10 @@ fn black_box<T>(dummy: T) -> T {
}
}

impl<F> RngCore for JitterRng<F>
where F: Fn() -> u64 + Send + Sync {
impl<F> RngCore for JitterRng<F>
where
F: Fn() -> u64 + Send + Sync,
{
fn next_u32(&mut self) -> u32 {
// We want to use both parts of the generated entropy
if self.data_half_used {
Expand All @@ -736,8 +757,8 @@ where F: Fn() -> u64 + Send + Sync {
}

fn next_u64(&mut self) -> u64 {
self.data_half_used = false;
self.gen_entropy()
self.data_half_used = false;
self.gen_entropy()
}

fn fill_bytes(&mut self, dest: &mut [u8]) {
Expand Down
2 changes: 1 addition & 1 deletion rand_jitter/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub fn get_nstime() -> 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
Expand Down

0 comments on commit ac0cf3c

Please sign in to comment.