diff --git a/.travis.yml b/.travis.yml index 8f889c6..1e26668 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ cache: cargo dist: trusty os: - linux - # - osx + - osx # Run builds for all the supported trains rust: @@ -12,19 +12,19 @@ rust: - beta - nightly -sudo: true -env: - global: - - RUSTFLAGS="-C link-dead-code" - -before_install: - - sudo apt-get update - -addons: - apt: - packages: - - libssl-dev +matrix: + include: + - rust: stable + os: linux + sudo: true + env: SKIPTEST=true RUSTFLAGS="-C link-dead-code" + before_install: + - sudo apt-get update + addons: + apt: + packages: + - libssl-dev # Add clippy before_script: @@ -36,18 +36,21 @@ before_script: # The main build script: - - cargo build - - cargo test + - | + if [[ -z $SKIPTEST ]]; then + cargo build + cargo test + make test + fi - | if [[ "$TRAVIS_RUST_VERSION" == "nightly" && $CLIPPY ]]; then cargo clippy fi - - make test # Coverage report after_success: - | - if [[ "$TRAVIS_RUST_VERSION" == stable ]]; then + if [[ "$TRAVIS_RUST_VERSION" == "stable" && "$TRAVIS_OS_NAME" = linux ]]; then bash <(curl https://raw.githubusercontent.com/xd009642/tarpaulin/master/travis-install.sh) # Uncomment the following line for coveralls.io # cargo tarpaulin --ciserver travis-ci --coveralls $TRAVIS_JOB_ID diff --git a/Cargo.toml b/Cargo.toml index 4cd0aa7..c62788b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,6 @@ repository = "https://github.com/libpasta/libpasta" argon2rs = "0.2.5" data-encoding = "2.1.2" error-chain = "0.12.0" -fastpbkdf2 = "0.1.0" -itertools = "0.8.0" lazy_static = "1.2.0" log = "0.4.6" num-traits = "0.2.6" diff --git a/Makefile b/Makefile index 7ff614d..009a6b9 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ -VERSION = 0.1.0-rc0 +VERSION = 0.1.0-rc1 all: libpasta.so libpasta.a clean: + cargo clean --manifest-path libpasta-capi/Cargo.toml rm -rf build/ force: @@ -11,7 +12,7 @@ force: make all libpasta: Cargo.toml libpasta-capi/Cargo.toml - cargo build --release --manifest-path libpasta-capi/Cargo.toml + RUSTFLAGS="--print native-static-libs" cargo build --release --manifest-path libpasta-capi/Cargo.toml libpasta.%: libpasta mkdir -p build diff --git a/libpasta-capi/ctest/compile.sh b/libpasta-capi/ctest/compile.sh index 5bcf1eb..25a5c8d 100644 --- a/libpasta-capi/ctest/compile.sh +++ b/libpasta-capi/ctest/compile.sh @@ -3,5 +3,5 @@ set -ex cargo build --release --manifest-path ../Cargo.toml -gcc -DDEBUG -ggdb -o test_c test.c -Wall -I../include -L../target/release/ -lpasta -g++ -DDEBUG -std=c++11 -ggdb -o test_cpp test.cpp -Wall -I../include -L../target/release/ -lpasta +${CC:="gcc"} -DDEBUG -ggdb -o test_c test.c -Wall -I../include -L../target/release/ -lpasta +${CXX:="g++"} -DDEBUG -std=c++11 -ggdb -o test_cpp test.cpp -Wall -I../include -L../target/release/ -lpasta diff --git a/libpasta-capi/include/pasta-bindings.h b/libpasta-capi/include/pasta-bindings.h index 99faee1..ccc30f0 100644 --- a/libpasta-capi/include/pasta-bindings.h +++ b/libpasta-capi/include/pasta-bindings.h @@ -38,10 +38,14 @@ typedef struct { }; } HashUpdateFfi; +void config_free(Config *config); + char *config_hash_password(const Config *config, const char *password); HashUpdateFfi *config_migrate_hash(const Config *config, const char *hash); +Config *config_new(void); + bool config_verify_password(const Config *config, const char *hash, const char *password); HashUpdateFfi *config_verify_password_update_hash(const Config *config, @@ -58,8 +62,6 @@ Primitive *default_pbkdf2i(void); Primitive *default_scrypt(void); -void free_Config(Config *config); - void free_Primitive(Primitive *prim); void free_string(char *s); diff --git a/libpasta-capi/include/pasta-bindings.hpp b/libpasta-capi/include/pasta-bindings.hpp index fb9a0be..39d2c52 100644 --- a/libpasta-capi/include/pasta-bindings.hpp +++ b/libpasta-capi/include/pasta-bindings.hpp @@ -35,10 +35,14 @@ struct HashUpdateFfi { extern "C" { +void config_free(Config *config); + char *config_hash_password(const Config *config, const char *password); HashUpdateFfi *config_migrate_hash(const Config *config, const char *hash); +Config *config_new(); + bool config_verify_password(const Config *config, const char *hash, const char *password); HashUpdateFfi *config_verify_password_update_hash(const Config *config, @@ -55,8 +59,6 @@ Primitive *default_pbkdf2i(); Primitive *default_scrypt(); -void free_Config(Config *config); - void free_Primitive(Primitive *prim); void free_string(char *s); diff --git a/libpasta-capi/src/lib.rs b/libpasta-capi/src/lib.rs index 23a7c2e..01c2397 100644 --- a/libpasta-capi/src/lib.rs +++ b/libpasta-capi/src/lib.rs @@ -75,6 +75,15 @@ pub extern fn hash_password(password: *const c_char) -> *mut c_char { CString::new(output).unwrap().into_raw() } +#[no_mangle] +pub extern "C" fn config_new() -> *mut Config { + box_ptr!(Config::default()) +} + +#[no_mangle] +pub extern "C" fn config_free(config: *mut Config) { + let _config = unsafe { ffi_ref!(config) }; +} #[no_mangle] pub extern "C" fn config_hash_password(config: *const Config, password: *const c_char) -> *mut c_char { @@ -183,11 +192,6 @@ pub extern "C" fn free_Primitive(prim: *mut Primitive) { let _prim = unsafe { ffi_ref!(prim) }; } -#[no_mangle] -pub extern "C" fn free_Config(config: *mut Config) { - let _config = unsafe { ffi_ref!(config) }; - -} #[cfg(test)] mod test { diff --git a/src/bench.rs b/src/bench.rs index 7d05b21..da4da72 100644 --- a/src/bench.rs +++ b/src/bench.rs @@ -15,11 +15,11 @@ macro_rules! benches { #[bench] fn short(b: &mut Bencher) { - let password = "hunter2*********".to_owned(); + let password = "hunter2*********"; let alg = Algorithm::Single(<$params>::default().into()); println!("Bench params: {:?}", alg); b.iter(|| { - alg.hash(password.clone().into()) + alg.hash(password) }) } @@ -30,7 +30,7 @@ macro_rules! benches { let alg = Algorithm::Single(<$params>::default().into()); println!("Bench params: {:?}", alg); b.iter(|| { - alg.hash(password.clone().into()) + alg.hash(&password) }) } } diff --git a/src/lib.rs b/src/lib.rs index edefc84..51455de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,9 +43,6 @@ //! `libpasta` attempts to support some legacy formats. For example, the `bcrypt` //! format `$2y$...`. -#![cfg_attr(all(feature="bench", test), feature(test))] - - #![allow(unknown_lints)] #![deny(clippy::pedantic)] #![allow( @@ -93,9 +90,10 @@ unused_unsafe, unused_variables, variant_size_differences, - warnings, while_true, )] +// Necessary for having benchmarks defined inline. +#![cfg_attr(all(feature="bench", test), feature(test))] #![cfg_attr(all(feature="bench", test), allow(unstable_features))] extern crate data_encoding; @@ -332,9 +330,11 @@ mod api_tests { fn nested_hash() { let password = "hunter2"; + let fast_prim = Bcrypt::new(5); + let params = Algorithm::Nested { - inner: Box::new(Algorithm::default()), - outer: DEFAULT_PRIM.clone(), + inner: Box::new(Algorithm::Single(fast_prim.clone())), + outer: fast_prim.clone(), }; let hash = params.hash(&password); @@ -372,7 +372,7 @@ mod api_tests { fn migrate() { let password = "hunter2"; - let params = Algorithm::Single(Bcrypt::default()); + let params = Algorithm::Single(Bcrypt::new(5)); let mut hash = serde_mcf::to_string(¶ms.hash(&password)).unwrap(); println!("Original: {:?}", hash); if let Some(new_hash) = migrate_hash(&hash) { diff --git a/src/primitives/mod.rs b/src/primitives/mod.rs index b6905e3..6f39d91 100644 --- a/src/primitives/mod.rs +++ b/src/primitives/mod.rs @@ -39,7 +39,7 @@ pub use self::hmac::Hmac; /// Implementations are from both `ring` and the C `fastpbkdf2` implementations. /// The latter is currently in use. mod pbkdf2; -pub use self::pbkdf2::{Pbkdf2, RingPbkdf2}; +pub use self::pbkdf2::Pbkdf2; /// `Scrypt` implementations. /// diff --git a/src/primitives/pbkdf2.rs b/src/primitives/pbkdf2.rs index 4a0c9a6..025666c 100644 --- a/src/primitives/pbkdf2.rs +++ b/src/primitives/pbkdf2.rs @@ -1,8 +1,6 @@ -/// Native Rust implementation of scrypt. -pub use self::fastpbkdf2::Pbkdf2; -pub use self::ring_pbkdf2::Pbkdf2 as RingPbkdf2; +/// PBKDF2 implementation from *ring* +pub use self::ring_pbkdf2::Pbkdf2; -/// Native Rust implementation of scrypt. mod ring_pbkdf2 { use primitives::{Primitive, PrimitiveImpl}; use sod::Sod; @@ -84,112 +82,6 @@ mod ring_pbkdf2 { } } - -/// Native Rust implementation of scrypt. -mod fastpbkdf2 { - extern crate fastpbkdf2; - use self::fastpbkdf2::*; - - use primitives::{Primitive, PrimitiveImpl}; - use sod::Sod; - - use ring::digest; - use serde_mcf::Hashes; - - use std::fmt; - use std::sync::Arc; - - use super::super::hash_to_id; - - /// Struct holding `PBKDF2` parameters. - /// - /// This implementation is backed by `fastpbkdf2`. - pub struct Pbkdf2 { - iterations: u32, - algorithm: fn(&[u8], &[u8], u32, &mut [u8]), - alg_id: &'static str, - } - - lazy_static! { - static ref DEFAULT: Arc> = { - Arc::new(Box::new(Pbkdf2::new_impl(10_000, &digest::SHA256))) - }; - } - - impl Pbkdf2 { - /// Create a new PBKDF2 instance using defaults. - pub fn default() -> Primitive { - Primitive(Sod::Dynamic(Arc::clone(&DEFAULT))) - } - - /// Create a new PBKDF2 instance. - pub fn new(iterations: u32, algorithm: &'static digest::Algorithm) -> Primitive { - Self::new_impl(iterations, algorithm).into() - } - - fn new_impl(iterations: u32, algorithm: &'static digest::Algorithm) -> Self { - match hash_to_id(algorithm).as_ref() { - "SHA1" => { - Self { - iterations, - algorithm: pbkdf2_hmac_sha1, - alg_id: "SHA1", - } - } - "SHA256" => { - Self { - iterations, - algorithm: pbkdf2_hmac_sha256, - alg_id: "SHA256", - } - } - "SHA512" => { - Self { - iterations, - algorithm: pbkdf2_hmac_sha512, - alg_id: "SHA512", - } - } - _ => panic!("unexpected digest algorithm"), - } - } - } - - impl ::primitives::PrimitiveImpl for Pbkdf2 { - /// Compute the scrypt hash - fn compute<'a>(&'a self, password: &[u8], salt: &[u8]) -> Vec { - let mut hash = vec![0_u8; 32]; - (self.algorithm)(password, salt, self.iterations, &mut hash); - hash - } - - /// Convert parameters into a vector of (key, value) tuples - /// for serializing. - fn params_as_vec(&self) -> Vec<(&'static str, String)> { - vec![("n", self.iterations.to_string())] - } - - fn hash_id(&self) -> Hashes { - match self.alg_id { - "SHA1" => Hashes::Pbkdf2Sha1, - "SHA256" => Hashes::Pbkdf2Sha256, - "SHA512" => Hashes::Pbkdf2Sha512, - _ => panic!("unexpected digest algorithm"), - } - } - } - - impl fmt::Debug for Pbkdf2 { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, - "PBKDF2-{:?}, iterations: {}", - self.alg_id, - self.iterations) - } - } -} - - #[cfg(test)] mod test { use ::hashing::*; @@ -213,23 +105,6 @@ mod test { println!("{:?}", serde_mcf::to_string(&out).unwrap()); } - #[test] - fn sanity_check_ring() { - let password = "hunter2"; - let params = super::RingPbkdf2::default(); - println!("{:?}", params); - let salt = ::get_salt(); - let hash = params.compute(password.as_bytes(), &salt); - let hash2 = params.compute(password.as_bytes(), &salt); - assert_eq!(hash, hash2); - let out = Output { - alg: Algorithm::Single(params.into()), - salt, - hash, - }; - println!("{:?}", serde_mcf::to_string(&out).unwrap()); - } - macro_rules! primitive_round_trip { ($prim:expr) => ( let hash = serde_mcf::to_string(&$prim.hash(&"hunter2")).unwrap(); @@ -247,27 +122,12 @@ mod test { let params = Algorithm::Single(super::Pbkdf2::new(1_000, &digest::SHA512)); primitive_round_trip!(params); - - let params = Algorithm::Single(super::RingPbkdf2::new(1_000, &digest::SHA1)); - primitive_round_trip!(params); - - let params = Algorithm::Single(super::RingPbkdf2::new(1_000, &digest::SHA256)); - primitive_round_trip!(params); - - let params = Algorithm::Single(super::RingPbkdf2::new(1_000, &digest::SHA512)); - primitive_round_trip!(params); - } } -#[cfg(features = "bench")] +#[cfg(feature="bench")] mod ring_bench { - use super::*; - benches!(RingPbkdf2); -} - -#[cfg(features = "bench")] -mod fast_bench { + #[allow(unused_imports)] use super::*; benches!(Pbkdf2); } diff --git a/tests/test_ringpbkdf2.rs b/tests/test_ringpbkdf2.rs deleted file mode 100644 index 4a03ee9..0000000 --- a/tests/test_ringpbkdf2.rs +++ /dev/null @@ -1,8 +0,0 @@ -extern crate libpasta; - -#[macro_use] -mod common; - -use libpasta::primitives::RingPbkdf2; - -config_test!(RingPbkdf2, "$$pbkdf2");