mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
rust: Expose crypto_rand() as an impl of rand_core::RngCore.
This commit is contained in:
parent
b5013e841c
commit
94dcd38a14
30
src/rust/external/crypto_rand.rs
vendored
30
src/rust/external/crypto_rand.rs
vendored
@ -11,23 +11,18 @@
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use libc::c_char;
|
||||
use libc::c_double;
|
||||
use libc::c_int;
|
||||
use libc::c_uint;
|
||||
use libc::c_void;
|
||||
use libc::size_t;
|
||||
use libc::time_t;
|
||||
use libc::uint8_t;
|
||||
use libc::uint64_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;
|
||||
// fn crypto_random_hostname(min_rand_len: c_int, max_rand_len: c_int,
|
||||
// prefix: *const c_char, suffix: *const c_char) -> *mut c_char;
|
||||
}
|
||||
|
||||
/// Seed OpenSSL's random number generator with bytes from the operating
|
||||
@ -48,7 +43,16 @@ pub fn c_tor_crypto_seed_rng() -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill the bytes of `dest` with strong random data.
|
||||
/// 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
|
||||
@ -81,15 +85,3 @@ pub fn c_tor_crypto_rand_double() -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_layout_tor_weak_rng_t() {
|
||||
assert_eq!(::std::mem::size_of::<tor_weak_rng_t>(), 0usize,
|
||||
concat!("Size of: ", stringify!(tor_weak_rng_t)));
|
||||
assert_eq!(::std::mem::align_of::<tor_weak_rng_t>(), 1usize,
|
||||
concat!("Alignment of ", stringify!(tor_weak_rng_t)));
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Copyright (c) 2018, isis agora lovecruft
|
||||
// See LICENSE for licensing information
|
||||
|
||||
//! Wrappers for Tor's random number generator to provide implementations of
|
||||
//! Wrappers for Tor's random number generators to provide implementations of
|
||||
//! `rand_core` traits.
|
||||
|
||||
// This is the real implementation, in use in production, which calls into our C
|
||||
@ -18,6 +18,7 @@ mod internal {
|
||||
use rand_core::impls::next_u32_via_fill;
|
||||
use rand_core::impls::next_u64_via_fill;
|
||||
|
||||
use external::c_tor_crypto_rand;
|
||||
use external::c_tor_crypto_strongest_rand;
|
||||
use external::c_tor_crypto_seed_rng;
|
||||
|
||||
@ -64,6 +65,53 @@ mod internal {
|
||||
next_u64_via_fill(self)
|
||||
}
|
||||
|
||||
// C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
c_tor_crypto_rand(dest);
|
||||
}
|
||||
|
||||
// C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
||||
Ok(self.fill_bytes(dest))
|
||||
}
|
||||
}
|
||||
|
||||
/// A CSPRNG which hashes together randomness from OpenSSL's RNG and entropy
|
||||
/// obtained from the operating system.
|
||||
pub struct TorStrongestRng {
|
||||
// This private, zero-length field forces the struct to be treated the
|
||||
// same as its opaque C couterpart.
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
|
||||
/// Mark `TorRng` as being suitable for cryptographic purposes.
|
||||
impl CryptoRng for TorStrongestRng {}
|
||||
|
||||
impl TorStrongestRng {
|
||||
// C_RUST_COUPLED: `crypto_seed_rng()` /src/common/crypto_rand.c
|
||||
#[allow(dead_code)]
|
||||
fn new() -> Self {
|
||||
if !c_tor_crypto_seed_rng() {
|
||||
tor_log_msg!(LogSeverity::Warn, LogDomain::General,
|
||||
"TorStrongestRng::from_seed()",
|
||||
"The RNG could not be seeded!");
|
||||
}
|
||||
// XXX also log success at info level —isis
|
||||
TorStrongestRng{ _unused: [0u8; 0] }
|
||||
}
|
||||
}
|
||||
|
||||
impl RngCore for TorStrongestRng {
|
||||
// C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
next_u32_via_fill(self)
|
||||
}
|
||||
|
||||
// C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
next_u64_via_fill(self)
|
||||
}
|
||||
|
||||
// C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
debug_assert!(dest.len() <= MAX_STRONGEST_RAND_SIZE);
|
||||
@ -81,7 +129,9 @@ mod internal {
|
||||
// For testing, we expose a pure-Rust implementation.
|
||||
#[cfg(test)]
|
||||
mod internal {
|
||||
pub use rand::EntropyRng as TorRng;
|
||||
// It doesn't matter if we pretend ChaCha is a CSPRNG in tests.
|
||||
pub use rand::ChaChaRng as TorRng;
|
||||
pub use rand::ChaChaRng as TorStrongestRng;
|
||||
}
|
||||
|
||||
// Finally, expose the public functionality of whichever appropriate internal
|
||||
|
Loading…
Reference in New Issue
Block a user