What changed, and why it matters
This commit adds a new performance optimization for SHA-256 hashing on modern x86 processors that support AVX2 instructions. It enables the library to process up to 8 hash calculations at once when the CPU supports it. There is no indication in the commit that this fixes a security bug; it appears to be a routine performance improvement.
No security action required. Treat as a normal performance optimization. If reviewing further, verify that avx2::sha256d_64_8way maintains the same output as the scalar/SSE/SHA-NI paths for all inputs and that unsafe preconditions (aligned buffers, valid lengths) are upheld by the caller.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces an 8-way AVX2 dispatch path in hashes/src/sha256/crypto/mod.rs. It adds a cpuid_avx2_x86 module using the cpufeatures crate and inserts two new code blocks (std-detected and cpufeatures-detected) that call avx2::sha256d_64_8way when AVX/AVX2 are available. The change removes a TODO comment for 8-way AVX2 and reorders dispatch paths. No unsafe invariants, input validation, or cryptographic correctness changes are visible in the diff.
Changed components
hashes/src/sha256/crypto/mod.rsSHA-256 multi-block hashing dispatchInspect captured patch +34 / −2
diff --git a/hashes/src/sha256/crypto/mod.rs b/hashes/src/sha256/crypto/mod.rs
index c141f28c..a0889a5f 100644
--- a/hashes/src/sha256/crypto/mod.rs
+++ b/hashes/src/sha256/crypto/mod.rs
@@ -51,6 +51,13 @@ mod cpuid_sse41_x86 {
cpufeatures::new!(inner, "sse2", "ssse3", "sse4.1");
pub fn get() -> bool { inner::get() }
}
+#[cfg(feature = "cpufeatures")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[allow(deprecated_in_future)]
+mod cpuid_avx2_x86 {
+ cpufeatures::new!(inner, "avx", "avx2");
+ pub fn get() -> bool { inner::get() }
+}
#[allow(non_snake_case)]
const fn Ch(x: u32, y: u32, z: u32) -> u32 { z ^ (x & (y ^ z)) }
@@ -351,8 +358,6 @@ impl HashEngine {
let mut i = 0;
let count = inputs.len();
- // TODO: 8-way AVX2
-
// 2-way x86 SHA-NI
#[cfg(feature = "std")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -411,6 +416,33 @@ impl HashEngine {
}
}
+ // 8-way AVX2
+ #[cfg(feature = "std")]
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ if std::is_x86_feature_detected!("avx") && std::is_x86_feature_detected!("avx2") {
+ while count - i >= 8 {
+ let out = <&mut [[u8; 32]; 8]>::try_from(&mut outputs[i..i + 8]).unwrap();
+ let inp = <&[[u8; 64]; 8]>::try_from(&inputs[i..i + 8]).unwrap();
+ unsafe { avx2::sha256d_64_8way(out, inp) };
+ i += 8;
+ }
+ }
+ }
+
+ #[cfg(feature = "cpufeatures")]
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ if cpuid_avx2_x86::get() {
+ while count - i >= 8 {
+ let out = <&mut [[u8; 32]; 8]>::try_from(&mut outputs[i..i + 8]).unwrap();
+ let inp = <&[[u8; 64]; 8]>::try_from(&inputs[i..i + 8]).unwrap();
+ unsafe { avx2::sha256d_64_8way(out, inp) };
+ i += 8;
+ }
+ }
+ }
+
// 4-way SSE4.1
#[cfg(feature = "std")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.