summaryrefslogtreecommitdiff
path: root/src/rust
diff options
context:
space:
mode:
Diffstat (limited to 'src/rust')
-rw-r--r--src/rust/.cargo/config.in3
-rw-r--r--src/rust/build.rs179
-rw-r--r--src/rust/crypto/Cargo.toml6
-rw-r--r--src/rust/crypto/digests/sha2.rs47
-rw-r--r--src/rust/crypto/lib.rs26
-rw-r--r--src/rust/crypto/rand/mod.rs10
-rw-r--r--src/rust/crypto/rand/rng.rs4
-rw-r--r--src/rust/external/crypto_digest.rs20
-rw-r--r--src/rust/include.am1
-rw-r--r--src/rust/protover/Cargo.toml1
-rw-r--r--src/rust/tor_log/Cargo.toml1
-rw-r--r--src/rust/tor_log/tor_log.rs4
12 files changed, 247 insertions, 55 deletions
diff --git a/src/rust/.cargo/config.in b/src/rust/.cargo/config.in
index 301e7fdbe7..70481bbcbe 100644
--- a/src/rust/.cargo/config.in
+++ b/src/rust/.cargo/config.in
@@ -6,3 +6,6 @@
@RUST_DL@ [source.vendored-sources]
@RUST_DL@ directory = '@TOR_RUST_DEPENDENCIES@'
+
+@RUST_WARN@ [build]
+@RUST_WARN@ rustflags = [ "-D", "warnings" ] \ No newline at end of file
diff --git a/src/rust/build.rs b/src/rust/build.rs
new file mode 100644
index 0000000000..b943aa5535
--- /dev/null
+++ b/src/rust/build.rs
@@ -0,0 +1,179 @@
+//! Build script for Rust modules in Tor.
+//!
+//! We need to use this because some of our Rust tests need to use some
+//! of our C modules, which need to link some external libraries.
+//!
+//! This script works by looking at a "config.rust" file generated by our
+//! configure script, and then building a set of options for cargo to pass to
+//! the compiler.
+
+use std::collections::HashMap;
+use std::env;
+use std::fs::File;
+use std::io::prelude::*;
+use std::io;
+use std::path::PathBuf;
+
+/// Wrapper around a key-value map.
+struct Config(
+ HashMap<String,String>
+);
+
+/// Locate a config.rust file generated by autoconf, starting in the OUT_DIR
+/// location provided by cargo and recursing up the directory tree. Note that
+/// we need to look in the OUT_DIR, since autoconf will place generated files
+/// in the build directory.
+fn find_cfg() -> io::Result<String> {
+ let mut path = PathBuf::from(env::var("OUT_DIR").unwrap());
+ loop {
+ path.push("config.rust");
+ if path.exists() {
+ return Ok(path.to_str().unwrap().to_owned());
+ }
+ path.pop(); // remove config.rust
+ if ! path.pop() { // can't remove last part of directory
+ return Err(io::Error::new(io::ErrorKind::NotFound,
+ "No config.rust"));
+ }
+ }
+}
+
+impl Config {
+ /// Find the config.rust file and try to parse it.
+ ///
+ /// The file format is a series of lines of the form KEY=VAL, with
+ /// any blank lines and lines starting with # ignored.
+ fn load() -> io::Result<Config> {
+ let path = find_cfg()?;
+ let f = File::open(&path)?;
+ let reader = io::BufReader::new(f);
+ let mut map = HashMap::new();
+ for line in reader.lines() {
+ let s = line?;
+ if s.trim().starts_with("#") || s.trim() == "" {
+ continue;
+ }
+ let idx = match s.find("=") {
+ None => {
+ return Err(io::Error::new(io::ErrorKind::InvalidData,
+ "missing ="));
+ },
+ Some(x) => x
+ };
+ let (var,eq_val) = s.split_at(idx);
+ let val = &eq_val[1..];
+ map.insert(var.to_owned(), val.to_owned());
+ }
+ Ok(Config(map))
+ }
+
+ /// Return a reference to the value whose key is 'key'.
+ ///
+ /// Panics if 'key' is not found in the configuration.
+ fn get(&self, key : &str) -> &str {
+ self.0.get(key).unwrap()
+ }
+
+ /// Add a dependency on a static C library that is part of Tor, by name.
+ fn component(&self, s : &str) {
+ println!("cargo:rustc-link-lib=static={}", s);
+ }
+
+ /// Add a dependency on a native library that is not part of Tor, by name.
+ fn dependency(&self, s : &str) {
+ println!("cargo:rustc-link-lib={}", s);
+ }
+
+ /// Add a link path, relative to Tor's build directory.
+ fn link_relpath(&self, s : &str) {
+ let builddir = self.get("BUILDDIR");
+ println!("cargo:rustc-link-search=native={}/{}", builddir, s);
+ }
+
+ /// Add an absolute link path.
+ fn link_path(&self, s : &str) {
+ println!("cargo:rustc-link-search=native={}", s);
+ }
+
+ /// Parse the CFLAGS in s, looking for -l and -L items, and adding
+ /// rust configuration as appropriate.
+ fn from_cflags(&self, s : &str) {
+ let mut next_is_lib = false;
+ let mut next_is_path = false;
+ for ent in self.get(s).split_whitespace() {
+ if next_is_lib {
+ self.dependency(ent);
+ next_is_lib = false;
+ } else if next_is_path {
+ self.link_path(ent);
+ next_is_path = false;
+ } else if ent == "-l" {
+ next_is_lib = true;
+ } else if ent == "-L" {
+ next_is_path = true;
+ } else if ent.starts_with("-L") {
+ self.link_path(&ent[2..]);
+ } else if ent.starts_with("-l") {
+ self.dependency(&ent[2..]);
+ }
+ }
+ }
+}
+
+pub fn main() {
+ let cfg = Config::load().unwrap();
+ let package = env::var("CARGO_PKG_NAME").unwrap();
+
+ match package.as_ref() {
+ "crypto" => {
+ // Right now, I'm having a separate configuration for each Rust
+ // package, since I'm hoping we can trim them down. Once we have a
+ // second Rust package that needs to use this build script, let's
+ // extract some of this stuff into a module.
+ //
+ // This is a ridiculous amount of code to be pulling in just
+ // to test our crypto library: modularity would be our
+ // friend here.
+ cfg.from_cflags("TOR_LDFLAGS_zlib");
+ cfg.from_cflags("TOR_LDFLAGS_openssl");
+ cfg.from_cflags("TOR_LDFLAGS_libevent");
+
+ cfg.link_relpath("src/common");
+ cfg.link_relpath("src/ext/keccak-tiny");
+ cfg.link_relpath("src/ext/keccak-tiny");
+ cfg.link_relpath("src/ext/ed25519/ref10");
+ cfg.link_relpath("src/ext/ed25519/donna");
+ cfg.link_relpath("src/trunnel");
+
+ // Note that we can't pull in "libtor-testing", or else we
+ // will have dependencies on all the other rust packages that
+ // tor uses. We must be careful with factoring and dependencies
+ // moving forward!
+ cfg.component("or-crypto-testing");
+ cfg.component("or-ctime-testing");
+ cfg.component("or-testing");
+ cfg.component("or-event-testing");
+ cfg.component("or-ctime-testing");
+ cfg.component("curve25519_donna");
+ cfg.component("keccak-tiny");
+ cfg.component("ed25519_ref10");
+ cfg.component("ed25519_donna");
+ cfg.component("or-trunnel-testing");
+
+ cfg.from_cflags("TOR_ZLIB_LIBS");
+ cfg.from_cflags("TOR_LIB_MATH");
+ cfg.from_cflags("TOR_OPENSSL_LIBS");
+ cfg.from_cflags("TOR_LIBEVENT_LIBS");
+ cfg.from_cflags("TOR_LIB_WS32");
+ cfg.from_cflags("TOR_LIB_GDI");
+ cfg.from_cflags("TOR_LIB_USERENV");
+ cfg.from_cflags("CURVE25519_LIBS");
+ cfg.from_cflags("TOR_LZMA_LIBS");
+ cfg.from_cflags("TOR_ZSTD_LIBS");
+ cfg.from_cflags("LIBS");
+ },
+ _ => {
+ panic!("No configuration in build.rs for package {}", package);
+ }
+ }
+}
diff --git a/src/rust/crypto/Cargo.toml b/src/rust/crypto/Cargo.toml
index 3d343344ae..869e0d6256 100644
--- a/src/rust/crypto/Cargo.toml
+++ b/src/rust/crypto/Cargo.toml
@@ -4,6 +4,7 @@ authors = ["The Tor Project",
name = "crypto"
version = "0.0.1"
publish = false
+build = "../build.rs"
[lib]
name = "crypto"
@@ -13,7 +14,7 @@ crate_type = ["rlib", "staticlib"]
[dependencies]
libc = "=0.2.39"
digest = "=0.7.2"
-rand_core = "=0.2.0-pre.0"
+rand_core = { version = "=0.2.0-pre.0", default-features = false }
external = { path = "../external" }
smartlist = { path = "../smartlist" }
@@ -22,7 +23,6 @@ tor_log = { path = "../tor_log" }
[dev-dependencies]
rand = { version = "=0.5.0-pre.2", default-features = false }
+rand_core = { version = "=0.2.0-pre.0", default-features = false }
[features]
-testing = ["tor_log/testing"]
-
diff --git a/src/rust/crypto/digests/sha2.rs b/src/rust/crypto/digests/sha2.rs
index 1cbb6c581e..03e0843dc0 100644
--- a/src/rust/crypto/digests/sha2.rs
+++ b/src/rust/crypto/digests/sha2.rs
@@ -43,10 +43,10 @@ pub struct Sha256 {
///
/// # Examples
///
-/// ```
-/// use crypto::digest::Sha256;
+/// ```rust,no_run
+/// use crypto::digests::sha2::{Sha256, Digest};
///
-/// let hasher: Sha256 = Sha256::default();
+/// let mut hasher: Sha256 = Sha256::default();
/// ```
///
/// # Returns
@@ -66,13 +66,13 @@ impl BlockInput for Sha256 {
///
/// # Examples
///
-/// ```
-/// use crypto::digest::Sha256;
+/// ```rust,no_run
+/// use crypto::digests::sha2::{Sha256, Digest};
///
-/// let hasher: Sha256 = Sha256::default();
+/// let mut hasher: Sha256 = Sha256::default();
///
-/// hasher.process(b"foo");
-/// hasher.process(b"bar");
+/// hasher.input(b"foo");
+/// hasher.input(b"bar");
/// ```
impl Input for Sha256 {
fn process(&mut self, msg: &[u8]) {
@@ -110,10 +110,10 @@ pub struct Sha512 {
///
/// # Examples
///
-/// ```
-/// use crypto::digest::Sha512;
+/// ```rust,no_run
+/// use crypto::digests::sha2::{Sha512, Digest};
///
-/// let hasher: Sha256 = Sha512::default();
+/// let mut hasher: Sha512 = Sha512::default();
/// ```
///
/// # Returns
@@ -133,13 +133,13 @@ impl BlockInput for Sha512 {
///
/// # Examples
///
-/// ```
-/// use crypto::digest::Sha512;
+/// ```rust,no_run
+/// use crypto::digests::sha2::{Sha512, Digest};
///
-/// let hasher: Sha512 = Sha512::default();
+/// let mut hasher: Sha512 = Sha512::default();
///
-/// hasher.process(b"foo");
-/// hasher.process(b"bar");
+/// hasher.input(b"foo");
+/// hasher.input(b"bar");
/// ```
impl Input for Sha512 {
fn process(&mut self, msg: &[u8]) {
@@ -154,7 +154,7 @@ impl Input for Sha512 {
// FIXME: Once const generics land in Rust, we should genericise calling
// crypto_digest_get_digest in external::crypto_digest.
impl FixedOutput for Sha512 {
- type OutputSize = U32;
+ type OutputSize = U64;
fn fixed_result(self) -> GenericArray<u8, Self::OutputSize> {
let buffer: [u8; DIGEST512_LEN] = get_512_bit_digest(self.engine);
@@ -178,6 +178,9 @@ mod test {
fn sha256_digest() {
let mut h: Sha256 = Sha256::new();
let mut result: [u8; DIGEST256_LEN] = [0u8; DIGEST256_LEN];
+ let expected = [151, 223, 53, 136, 181, 163, 242, 75, 171, 195,
+ 133, 27, 55, 47, 11, 167, 26, 157, 205, 222, 212,
+ 59, 20, 185, 208, 105, 97, 191, 193, 112, 125, 157];
h.input(b"foo");
h.input(b"bar");
@@ -187,7 +190,7 @@ mod test {
println!("{:?}", &result[..]);
- assert_eq!(&result[..], &b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"[..]);
+ assert_eq!(result, expected);
}
#[test]
@@ -200,6 +203,12 @@ mod test {
let mut h: Sha512 = Sha512::new();
let mut result: [u8; DIGEST512_LEN] = [0u8; DIGEST512_LEN];
+ let expected = [203, 55, 124, 16, 176, 245, 166, 44, 128, 54, 37, 167,
+ 153, 217, 233, 8, 190, 69, 231, 103, 245, 209, 71, 212, 116,
+ 73, 7, 203, 5, 89, 122, 164, 237, 211, 41, 160, 175, 20, 122,
+ 221, 12, 244, 24, 30, 211, 40, 250, 30, 121, 148, 38, 88, 38,
+ 179, 237, 61, 126, 246, 240, 103, 202, 153, 24, 90];
+
h.input(b"foo");
h.input(b"bar");
h.input(b"baz");
@@ -208,6 +217,6 @@ mod test {
println!("{:?}", &result[..]);
- assert_eq!(&result[..], &b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"[..]);
+ assert_eq!(&result[..], &expected[..]);
}
}
diff --git a/src/rust/crypto/lib.rs b/src/rust/crypto/lib.rs
index e7e3b22e03..f72a859dd7 100644
--- a/src/rust/crypto/lib.rs
+++ b/src/rust/crypto/lib.rs
@@ -9,19 +9,19 @@
//! The `digests` module contains submodules for specific hash digests
//! and extendable output functions.
//!
-//! ```
-//! use crypto::digests::sha256::Sha256;
+//! ```rust,no_run
+//! use crypto::digests::sha2::*;
//!
-//! let hasher: Sha256 = Sha256::default();
+//! let mut hasher: Sha256 = Sha256::default();
//! let mut result: [u8; 32] = [0u8; 32];
//!
-//! hasher.input("foo");
-//! hasher.input("bar");
-//! hasher.input("baz");
+//! hasher.input(b"foo");
+//! hasher.input(b"bar");
+//! hasher.input(b"baz");
//!
-//! result.copy_from_slice(hasher.result().as_bytes());
+//! result.copy_from_slice(hasher.result().as_slice());
//!
-//! assert!(result == "XXX");
+//! assert!(result == [b'X'; DIGEST256_LEN]);
//! ```
#[deny(missing_docs)]
@@ -29,9 +29,17 @@
// External crates from cargo or TOR_RUST_DEPENDENCIES.
extern crate digest;
extern crate libc;
+extern crate rand_core;
+
+// External dependencies for tests.
+#[cfg(test)]
+extern crate rand as rand_crate;
// Our local crates.
extern crate external;
+#[cfg(not(test))]
+#[macro_use]
+extern crate tor_log;
pub mod digests; // Unfortunately named "digests" plural to avoid name conflict with the digest crate
-
+pub mod rand;
diff --git a/src/rust/crypto/rand/mod.rs b/src/rust/crypto/rand/mod.rs
index 6b3058ad58..82d02a70bb 100644
--- a/src/rust/crypto/rand/mod.rs
+++ b/src/rust/crypto/rand/mod.rs
@@ -2,15 +2,5 @@
// 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
index d5fae8a32e..07a0a7bdc7 100644
--- a/src/rust/crypto/rand/rng.rs
+++ b/src/rust/crypto/rand/rng.rs
@@ -130,8 +130,8 @@ mod internal {
#[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;
+ pub use rand_crate::ChaChaRng as TorRng;
+ pub use rand_crate::ChaChaRng as TorStrongestRng;
}
// Finally, expose the public functionality of whichever appropriate internal
diff --git a/src/rust/external/crypto_digest.rs b/src/rust/external/crypto_digest.rs
index bc49e6124c..3e8801f203 100644
--- a/src/rust/external/crypto_digest.rs
+++ b/src/rust/external/crypto_digest.rs
@@ -66,13 +66,6 @@ const DIGEST_SHA512: digest_algorithm_t = 2;
const DIGEST_SHA3_256: digest_algorithm_t = 3;
const DIGEST_SHA3_512: digest_algorithm_t = 4;
-/// The total number of digest algorithms we currently support.
-///
-/// We can't access these from Rust, because their definitions in C require
-/// introspecting the `digest_algorithm_t` typedef, which is an enum, so we have
-/// to redefine them here.
-const N_DIGEST_ALGORITHMS: usize = DIGEST_SHA3_512 as usize + 1;
-
/// The number of hash digests we produce for a `common_digests_t`.
///
/// We can't access these from Rust, because their definitions in C require
@@ -117,6 +110,9 @@ struct common_digests_t {
/// A `smartlist_t` is just an alias for the `#[repr(C)]` type `Stringlist`, to
/// make it more clear that we're working with a smartlist which is owned by C.
#[allow(non_camel_case_types)]
+// BINDGEN_GENERATED: This type isn't actually bindgen generated, but the code
+// below it which uses it is. As such, this comes up as "dead code" as well.
+#[allow(dead_code)]
type smartlist_t = Stringlist;
/// All of the external functions from `src/common/crypto_digest.h`.
@@ -144,7 +140,7 @@ extern "C" {
fn crypto_digest_new() -> *mut crypto_digest_t;
fn crypto_digest256_new(algorithm: digest_algorithm_t) -> *mut crypto_digest_t;
fn crypto_digest512_new(algorithm: digest_algorithm_t) -> *mut crypto_digest_t;
- fn crypto_digest_free(digest: *mut crypto_digest_t);
+ fn crypto_digest_free_(digest: *mut crypto_digest_t);
fn crypto_digest_add_bytes(digest: *mut crypto_digest_t, data: *const c_char, len: size_t);
fn crypto_digest_get_digest(digest: *mut crypto_digest_t, out: *mut c_char, out_len: size_t);
fn crypto_digest_dup(digest: *const crypto_digest_t) -> *mut crypto_digest_t;
@@ -296,6 +292,14 @@ impl CryptoDigest {
}
}
+impl Drop for CryptoDigest {
+ fn drop(&mut self) {
+ unsafe {
+ crypto_digest_free_(self.0 as *mut crypto_digest_t);
+ }
+ }
+}
+
/// Get the 256-bit digest output of a `crypto_digest_t`.
///
/// # Inputs
diff --git a/src/rust/include.am b/src/rust/include.am
index 5fd9741e01..5e5b0b3faf 100644
--- a/src/rust/include.am
+++ b/src/rust/include.am
@@ -1,6 +1,7 @@
include src/rust/tor_rust/include.am
EXTRA_DIST +=\
+ src/rust/build.rs \
src/rust/Cargo.toml \
src/rust/Cargo.lock \
src/rust/.cargo/config.in \
diff --git a/src/rust/protover/Cargo.toml b/src/rust/protover/Cargo.toml
index af1089c914..a8480e142a 100644
--- a/src/rust/protover/Cargo.toml
+++ b/src/rust/protover/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.1"
name = "protover"
[features]
-testing = ["tor_log/testing"]
[dependencies]
libc = "=0.2.39"
diff --git a/src/rust/tor_log/Cargo.toml b/src/rust/tor_log/Cargo.toml
index 971cd658b1..9d06299c05 100644
--- a/src/rust/tor_log/Cargo.toml
+++ b/src/rust/tor_log/Cargo.toml
@@ -9,7 +9,6 @@ path = "lib.rs"
crate_type = ["rlib", "staticlib"]
[features]
-testing = []
[dependencies]
libc = "0.2.39"
diff --git a/src/rust/tor_log/tor_log.rs b/src/rust/tor_log/tor_log.rs
index 1fdc0026bf..ad6725f0f2 100644
--- a/src/rust/tor_log/tor_log.rs
+++ b/src/rust/tor_log/tor_log.rs
@@ -88,7 +88,7 @@ pub fn tor_log_msg_impl(
/// This implementation is used when compiling for actual use, as opposed to
/// testing.
-#[cfg(all(not(test), not(feature = "testing")))]
+#[cfg(not(test))]
pub mod log {
use libc::{c_char, c_int};
use super::LogDomain;
@@ -142,7 +142,7 @@ pub mod log {
/// This module exposes no-op functionality for testing other Rust modules
/// without linking to C.
-#[cfg(any(test, feature = "testing"))]
+#[cfg(test)]
pub mod log {
use libc::{c_char, c_int};
use super::LogDomain;