1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
// Copyright (c) 2018, The Tor Project, Inc.
// Copyright (c) 2018, isis agora lovecruft
// See LICENSE for licensing information
//! Wrappers for Tor's random number generator to provide implementations of
//! `rand_core` traits.
// This is the real implementation, in use in production, which calls into our C
// wrappers in /src/common/crypto_rand.c, which call into OpenSSL, system
// libraries, and make syscalls.
#[cfg(not(test))]
mod internal {
use std::u64;
use rand_core::CryptoRng;
use rand_core::Error;
use rand_core::RngCore;
use rand_core::impls::next_u32_via_fill;
use rand_core::impls::next_u64_via_fill;
use external::c_tor_crypto_strongest_rand;
use external::c_tor_crypto_seed_rng;
use tor_log::LogDomain;
use tor_log::LogSeverity;
/// Largest strong entropy request permitted.
//
// C_RUST_COUPLED: `MAX_STRONGEST_RAND_SIZE` /src/common/crypto_rand.c
const MAX_STRONGEST_RAND_SIZE: usize = 256;
/// A wrapper around OpenSSL's RNG.
pub struct TorRng {
// 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 TorRng {}
impl TorRng {
// 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,
"TorRng::from_seed()",
"The RNG could not be seeded!");
}
// XXX also log success at info level —isis
TorRng{ _unused: [0u8; 0] }
}
}
impl RngCore for TorRng {
// 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);
c_tor_crypto_strongest_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))
}
}
}
// For testing, we expose a pure-Rust implementation.
#[cfg(test)]
mod internal {
pub use rand::EntropyRng as TorRng;
}
// Finally, expose the public functionality of whichever appropriate internal
// module.
pub use self::internal::*;
|