diff --git a/Cargo.toml b/Cargo.toml index 28868a5..32811d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ doctest = false [dependencies] [features] -default = ["blake2", "sha1", "sha2", "sha3", "ripemd160", "chacha", "salsa", "hkdf", "hmac", "pbkdf2", "poly1305", "scrypt", "curve25519", "ed25519", "x25519"] +default = ["std", "blake2", "sha1", "sha2", "sha3", "ripemd160", "chacha", "salsa", "hkdf", "hmac", "pbkdf2", "poly1305", "scrypt", "curve25519", "ed25519", "x25519"] blake2 = ["digest", "mac"] sha1 = ["digest"] sha2 = ["digest"] @@ -45,3 +45,4 @@ x25519 = ["curve25519"] with-bench = [] force-32bits = [] use-stdsimd = [] +std = [] diff --git a/src/hashing/blake2/mod.rs b/src/hashing/blake2/mod.rs index 0e3f350..6f30d12 100644 --- a/src/hashing/blake2/mod.rs +++ b/src/hashing/blake2/mod.rs @@ -9,12 +9,24 @@ mod reference; pub use common::LastBlock; -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "avx" +))] mod avx; -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "avx2" +))] mod avx2; +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + any(target_feature = "avx", target_feature = "avx2") +))] +use crate::simd_check::*; + use common::{b, s}; /// Blake2s Context @@ -55,11 +67,7 @@ impl EngineS { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { #[cfg(target_feature = "avx")] - const HAS_AVX: bool = true; - #[cfg(not(target_feature = "avx"))] - const HAS_AVX: bool = false; - - if HAS_AVX { + if avx_available() { return avx::compress_s(&mut self.h, &mut self.t, buf, last); } } @@ -105,20 +113,13 @@ impl EngineB { pub fn compress(&mut self, buf: &[u8], last: LastBlock) { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { - #[cfg(target_feature = "avx")] - const HAS_AVX: bool = true; - #[cfg(not(target_feature = "avx"))] - const HAS_AVX: bool = false; - #[cfg(target_feature = "avx2")] - const HAS_AVX2: bool = true; - #[cfg(not(target_feature = "avx2"))] - const HAS_AVX2: bool = false; - - if HAS_AVX2 { + if avx2_available() { return avx2::compress_b(&mut self.h, &mut self.t, buf, last); } - if HAS_AVX { + + #[cfg(target_feature = "avx")] + if avx_available() { return avx::compress_b(&mut self.h, &mut self.t, buf, last); } } diff --git a/src/hashing/sha2/impl256/mod.rs b/src/hashing/sha2/impl256/mod.rs index 30365ab..82d8f29 100644 --- a/src/hashing/sha2/impl256/mod.rs +++ b/src/hashing/sha2/impl256/mod.rs @@ -10,38 +10,45 @@ #[cfg(all(target_arch = "aarch64", feature = "use-stdsimd"))] mod aarch64; -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "avx" +))] mod avx; -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] + +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse4.1" +))] mod sse41; //TODO not finished yet //#[cfg(all(target_arch = "x86_64", target_feature = "sha"))] //mod x64sha; +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + any(target_feature = "avx", target_feature = "sse4.1") +))] +use crate::simd_check::*; + // software implementation valid for all architectures mod reference; pub(crate) fn digest_block(state: &mut [u32; 8], block: &[u8]) { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { - /// in waiting for https://github.com/rust-lang/rfcs/pull/2725 #[cfg(target_feature = "avx")] - const HAS_AVX: bool = true; - #[cfg(not(target_feature = "avx"))] - const HAS_AVX: bool = false; - - #[cfg(target_feature = "sse4.1")] - const HAS_SSE41: bool = true; - #[cfg(not(target_feature = "sse4.1"))] - const HAS_SSE41: bool = false; - - if HAS_AVX { + if avx_available() { return avx::digest_block(state, block); } - if HAS_SSE41 { + + #[cfg(target_feature = "sse4.1")] + if sse4_1_available() { return sse41::digest_block(state, block); } } + #[cfg(target_arch = "aarch64")] { #[cfg(feature = "use-stdsimd")] diff --git a/src/lib.rs b/src/lib.rs index 70a7a53..e97a3c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,20 +32,18 @@ #![allow(clippy::wrong_self_convention)] #![allow(clippy::identity_op)] #![allow(clippy::many_single_char_names)] -#![no_std] #![cfg_attr(feature = "with-bench", feature(test))] #![cfg_attr(feature = "use-stdsimd", feature(stdsimd))] +#![cfg_attr(not(any(feature = "std", test)), no_std)] #[cfg(test)] #[cfg(feature = "with-bench")] extern crate test; -#[cfg(not(feature = "std"))] +#[cfg(not(any(feature = "std", test)))] extern crate alloc; - -#[cfg(test)] -#[macro_use] -extern crate std; +#[cfg(any(feature = "std", test))] +extern crate std as alloc; #[cfg(feature = "blake2")] pub mod blake2b; @@ -107,5 +105,6 @@ pub mod ripemd160; mod cryptoutil; mod simd; +mod simd_check; pub mod constant_time; diff --git a/src/simd_check.rs b/src/simd_check.rs new file mode 100644 index 0000000..a7c5acf --- /dev/null +++ b/src/simd_check.rs @@ -0,0 +1,38 @@ +#![allow(unreachable_code)] +#![allow(dead_code)] + +pub fn avx_available() -> bool { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + #[cfg(feature = "std")] { + return std::is_x86_feature_detected!("avx"); + } + #[cfg(all(not(feature = "std"), target_feature = "avx"))] { + return true; + } + } + return false; +} + +pub fn avx2_available() -> bool { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + #[cfg(feature = "std")] { + return std::is_x86_feature_detected!("avx2"); + } + #[cfg(all(not(feature = "std"), target_feature = "avx2"))] { + return true; + } + } + return false; +} + +pub fn sse4_1_available() -> bool { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + #[cfg(feature = "std")] { + return std::is_x86_feature_detected!("sse4.1"); + } + #[cfg(all(not(feature = "std"), target_feature = "sse4.1"))] { + return true; + } + } + return false; +} \ No newline at end of file