mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +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 std::time::Duration;
|
||||||
|
|
||||||
use libc::c_char;
|
|
||||||
use libc::c_double;
|
use libc::c_double;
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use libc::c_uint;
|
|
||||||
use libc::c_void;
|
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
use libc::time_t;
|
use libc::time_t;
|
||||||
use libc::uint8_t;
|
use libc::uint8_t;
|
||||||
use libc::uint64_t;
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn crypto_seed_rng() -> c_int;
|
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_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_time_range(min: time_t, max: time_t) -> time_t;
|
||||||
fn crypto_rand_double() -> c_double;
|
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
|
/// 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]) {
|
pub fn c_tor_crypto_strongest_rand(dest: &mut [u8]) {
|
||||||
// We'll let the C side panic if the len is larger than
|
// We'll let the C side panic if the len is larger than
|
||||||
// MAX_STRONGEST_RAND_SIZE, rather than potentially panicking here. A
|
// 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
|
// Copyright (c) 2018, isis agora lovecruft
|
||||||
// See LICENSE for licensing information
|
// 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.
|
//! `rand_core` traits.
|
||||||
|
|
||||||
// This is the real implementation, in use in production, which calls into our C
|
// 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_u32_via_fill;
|
||||||
use rand_core::impls::next_u64_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_strongest_rand;
|
||||||
use external::c_tor_crypto_seed_rng;
|
use external::c_tor_crypto_seed_rng;
|
||||||
|
|
||||||
@ -64,6 +65,53 @@ mod internal {
|
|||||||
next_u64_via_fill(self)
|
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
|
// C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
|
||||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||||
debug_assert!(dest.len() <= MAX_STRONGEST_RAND_SIZE);
|
debug_assert!(dest.len() <= MAX_STRONGEST_RAND_SIZE);
|
||||||
@ -81,7 +129,9 @@ mod internal {
|
|||||||
// For testing, we expose a pure-Rust implementation.
|
// For testing, we expose a pure-Rust implementation.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod internal {
|
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
|
// Finally, expose the public functionality of whichever appropriate internal
|
||||||
|
Loading…
Reference in New Issue
Block a user