|
@@ -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
|