aboutsummaryrefslogtreecommitdiff
path: root/src/rust/crypto
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-05-16 09:16:04 -0400
committerNick Mathewson <nickm@torproject.org>2018-05-16 09:16:04 -0400
commit1442e818b67561c810c5d18894e29c57f8fdbbb0 (patch)
tree3bf8127f1a60a330df405df22e4ed0b1e9e2fc07 /src/rust/crypto
parente5974e51589e5d16aa4f518c86abac1f43f55e5a (diff)
parent4d349c6a6124b8d94dc787f0076c15b896272363 (diff)
downloadtor-1442e818b67561c810c5d18894e29c57f8fdbbb0.tar.gz
tor-1442e818b67561c810c5d18894e29c57f8fdbbb0.zip
Merge remote-tracking branch 'isis-github/bug26106'
Diffstat (limited to 'src/rust/crypto')
-rw-r--r--src/rust/crypto/Cargo.toml15
-rw-r--r--src/rust/crypto/rand/mod.rs16
-rw-r--r--src/rust/crypto/rand/rng.rs140
3 files changed, 167 insertions, 4 deletions
diff --git a/src/rust/crypto/Cargo.toml b/src/rust/crypto/Cargo.toml
index e6a8bffa27..3d343344ae 100644
--- a/src/rust/crypto/Cargo.toml
+++ b/src/rust/crypto/Cargo.toml
@@ -13,9 +13,16 @@ crate_type = ["rlib", "staticlib"]
[dependencies]
libc = "=0.2.39"
digest = "=0.7.2"
+rand_core = "=0.2.0-pre.0"
-[dependencies.external]
-path = "../external"
+external = { path = "../external" }
+smartlist = { path = "../smartlist" }
+tor_allocate = { path = "../tor_allocate" }
+tor_log = { path = "../tor_log" }
+
+[dev-dependencies]
+rand = { version = "=0.5.0-pre.2", default-features = false }
+
+[features]
+testing = ["tor_log/testing"]
-[dependencies.smartlist]
-path = "../smartlist"
diff --git a/src/rust/crypto/rand/mod.rs b/src/rust/crypto/rand/mod.rs
new file mode 100644
index 0000000000..6b3058ad58
--- /dev/null
+++ b/src/rust/crypto/rand/mod.rs
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, The Tor Project, Inc.
+// Copyright (c) 2018, isis agora lovecruft
+// See LICENSE for licensing information
+
+// External dependencies
+#[cfg(test)]
+extern crate rand;
+extern crate rand_core;
+
+// Internal dependencies
+extern crate external;
+#[cfg(not(test))]
+#[macro_use]
+extern crate tor_log;
+
+pub mod rng;
diff --git a/src/rust/crypto/rand/rng.rs b/src/rust/crypto/rand/rng.rs
new file mode 100644
index 0000000000..d5fae8a32e
--- /dev/null
+++ b/src/rust/crypto/rand/rng.rs
@@ -0,0 +1,140 @@
+// Copyright (c) 2018, The Tor Project, Inc.
+// Copyright (c) 2018, isis agora lovecruft
+// See LICENSE for licensing information
+
+//! 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
+// 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_rand;
+ 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)]
+ pub 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]) {
+ 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)]
+ pub 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);
+
+ 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 {
+ // 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
+// module.
+pub use self::internal::*;
+