diff options
Diffstat (limited to 'src/rust/external/crypto_rand.rs')
-rw-r--r-- | src/rust/external/crypto_rand.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/rust/external/crypto_rand.rs b/src/rust/external/crypto_rand.rs new file mode 100644 index 0000000000..af1ade0161 --- /dev/null +++ b/src/rust/external/crypto_rand.rs @@ -0,0 +1,87 @@ +// Copyright (c) 2018, The Tor Project, Inc. +// Copyright (c) 2018, isis agora lovecruft +// See LICENSE for licensing information + +//! Bindings to external (P)RNG interfaces and utilities in +//! src/common/crypto_rand.[ch]. +//! +//! We wrap our C implementations in src/common/crypto_rand.[ch] here in order +//! to provide wrappers with native Rust types, and then provide more Rusty +//! types and and trait implementations in src/rust/crypto/rand/. + +use std::time::Duration; + +use libc::c_double; +use libc::c_int; +use libc::size_t; +use libc::time_t; +use libc::uint8_t; + +extern "C" { + fn crypto_seed_rng() -> c_int; + fn crypto_rand(out: *mut uint8_t, out_len: size_t); + fn crypto_strongest_rand(out: *mut uint8_t, out_len: size_t); + fn crypto_rand_time_range(min: time_t, max: time_t) -> time_t; + fn crypto_rand_double() -> c_double; +} + +/// Seed OpenSSL's random number generator with bytes from the operating +/// system. +/// +/// # Returns +/// +/// `true` on success; `false` on failure. +pub fn c_tor_crypto_seed_rng() -> bool { + let ret: c_int; + + unsafe { + ret = crypto_seed_rng(); + } + match ret { + 0 => return true, + _ => return false, + } +} + +/// Fill the bytes of `dest` with random data. +pub fn c_tor_crypto_rand(dest: &mut [u8]) { + unsafe { + crypto_rand(dest.as_mut_ptr(), dest.len() as size_t); + } +} + +/// Fill the bytes of `dest` with "strong" random data by hashing +/// together randomness obtained from OpenSSL's RNG and the operating +/// system. +pub fn c_tor_crypto_strongest_rand(dest: &mut [u8]) { + // We'll let the C side panic if the len is larger than + // MAX_STRONGEST_RAND_SIZE, rather than potentially panicking here. A + // paranoid caller should assert on the length of dest *before* calling this + // function. + unsafe { + crypto_strongest_rand(dest.as_mut_ptr(), dest.len() as size_t); + } +} + +/// Get a random time, in seconds since the Unix Epoch. +/// +/// # Returns +/// +/// A `std::time::Duration` of seconds since the Unix Epoch. +pub fn c_tor_crypto_rand_time_range(min: &Duration, max: &Duration) -> Duration { + let ret: time_t; + + unsafe { + ret = crypto_rand_time_range(min.as_secs() as time_t, max.as_secs() as time_t); + } + + Duration::from_secs(ret as u64) +} + +/// Return a pseudorandom 64-bit float, chosen uniformly from the range [0.0, 1.0). +pub fn c_tor_crypto_rand_double() -> f64 { + unsafe { + crypto_rand_double() + } +} + |